ethdev: add meter color mark flow action

Create a new Flow API action: METER_MARK.
It Meters a packet stream and marks its packets with colors.
The marking is done on a metadata, not on a packet field.
Unlike the METER action, it performs no policing at all.
A user has the flexibility to create any policies with the help of
the METER_COLOR item later, only meter profile is mandatory here.

Add testpmd command line to match for METER_MARK action:
	flow create ... actions meter_mark mtr_profile 20 / end

Signed-off-by: Alexander Kozyrev <akozyrev@nvidia.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
This commit is contained in:
Alexander Kozyrev 2022-09-26 17:57:42 +03:00 committed by Andrew Rybchenko
parent ece19cca30
commit 9c4a0c1859
8 changed files with 294 additions and 1 deletions

View File

@ -54,6 +54,7 @@ enum index {
COMMON_GROUP_ID,
COMMON_PRIORITY_LEVEL,
COMMON_INDIRECT_ACTION_ID,
COMMON_PROFILE_ID,
COMMON_POLICY_ID,
COMMON_FLEX_HANDLE,
COMMON_FLEX_TOKEN,
@ -506,6 +507,14 @@ enum index {
ACTION_METER_COLOR_YELLOW,
ACTION_METER_COLOR_RED,
ACTION_METER_ID,
ACTION_METER_MARK,
ACTION_METER_PROFILE,
ACTION_METER_PROFILE_ID2PTR,
ACTION_METER_POLICY,
ACTION_METER_POLICY_ID2PTR,
ACTION_METER_COLOR_MODE,
ACTION_METER_INIT_COLOR,
ACTION_METER_STATE,
ACTION_OF_SET_MPLS_TTL,
ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
ACTION_OF_DEC_MPLS_TTL,
@ -1827,6 +1836,7 @@ static const enum index next_action[] = {
ACTION_PORT_ID,
ACTION_METER,
ACTION_METER_COLOR,
ACTION_METER_MARK,
ACTION_OF_SET_MPLS_TTL,
ACTION_OF_DEC_MPLS_TTL,
ACTION_OF_SET_NW_TTL,
@ -1936,6 +1946,16 @@ static const enum index action_meter_color[] = {
ZERO,
};
static const enum index action_meter_mark[] = {
ACTION_METER_PROFILE,
ACTION_METER_POLICY,
ACTION_METER_COLOR_MODE,
ACTION_METER_INIT_COLOR,
ACTION_METER_STATE,
ACTION_NEXT,
ZERO,
};
static const enum index action_of_set_mpls_ttl[] = {
ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
ACTION_NEXT,
@ -2371,6 +2391,14 @@ static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
static int parse_mp(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
static int parse_meter_profile_id2ptr(struct context *ctx,
const struct token *token,
const char *str, unsigned int len,
void *buf, unsigned int size);
static int parse_meter_policy_id2ptr(struct context *ctx,
const struct token *token,
const char *str, unsigned int len,
void *buf, unsigned int size);
static int parse_meter_color(struct context *ctx, const struct token *token,
const char *str, unsigned int len, void *buf,
unsigned int size);
@ -2535,6 +2563,13 @@ static const struct token token_list[] = {
.call = parse_int,
.comp = comp_none,
},
[COMMON_PROFILE_ID] = {
.name = "{profile_id}",
.type = "PROFILE_ID",
.help = "profile id",
.call = parse_int,
.comp = comp_none,
},
[COMMON_POLICY_ID] = {
.name = "{policy_id}",
.type = "POLICY_ID",
@ -5378,6 +5413,62 @@ static const struct token token_list[] = {
.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
.call = parse_vc_conf,
},
[ACTION_METER_MARK] = {
.name = "meter_mark",
.help = "meter the directed packets using profile and policy",
.priv = PRIV_ACTION(METER_MARK,
sizeof(struct rte_flow_action_meter_mark)),
.next = NEXT(action_meter_mark),
.call = parse_vc,
},
[ACTION_METER_PROFILE] = {
.name = "mtr_profile",
.help = "meter profile id to use",
.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
},
[ACTION_METER_PROFILE_ID2PTR] = {
.name = "{mtr_profile_id}",
.type = "PROFILE_ID",
.help = "meter profile id",
.next = NEXT(action_meter_mark),
.call = parse_meter_profile_id2ptr,
.comp = comp_none,
},
[ACTION_METER_POLICY] = {
.name = "mtr_policy",
.help = "meter policy id to use",
.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
},
[ACTION_METER_POLICY_ID2PTR] = {
.name = "{mtr_policy_id}",
.type = "POLICY_ID",
.help = "meter policy id",
.next = NEXT(action_meter_mark),
.call = parse_meter_policy_id2ptr,
.comp = comp_none,
},
[ACTION_METER_COLOR_MODE] = {
.name = "mtr_color_mode",
.help = "meter color awareness mode",
.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
.call = parse_vc_conf,
},
[ACTION_METER_INIT_COLOR] = {
.name = "mtr_init_color",
.help = "meter initial color",
.next = NEXT(action_meter_mark, NEXT_ENTRY(ITEM_METER_COLOR_NAME)),
.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, init_color)),
},
[ACTION_METER_STATE] = {
.name = "mtr_state",
.help = "meter state",
.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
.call = parse_vc_conf,
},
[ACTION_OF_SET_MPLS_TTL] = {
.name = "of_set_mpls_ttl",
.help = "OpenFlow's OFPAT_SET_MPLS_TTL",
@ -9699,6 +9790,68 @@ parse_ia_id2ptr(struct context *ctx, const struct token *token,
return ret;
}
static int
parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
const char *str, unsigned int len,
void *buf, unsigned int size)
{
struct rte_flow_action *action = ctx->object;
struct rte_flow_action_meter_mark *meter;
struct rte_flow_meter_profile *profile = NULL;
uint32_t id = 0;
int ret;
(void)buf;
(void)size;
ctx->objdata = 0;
ctx->object = &id;
ctx->objmask = NULL;
ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
ctx->object = action;
if (ret != (int)len)
return ret;
/* set meter profile */
if (action) {
meter = (struct rte_flow_action_meter_mark *)
(uintptr_t)(action->conf);
profile = port_meter_profile_get_by_id(ctx->port, id);
meter->profile = profile;
ret = (profile) ? ret : -1;
}
return ret;
}
static int
parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
const char *str, unsigned int len,
void *buf, unsigned int size)
{
struct rte_flow_action *action = ctx->object;
struct rte_flow_action_meter_mark *meter;
struct rte_flow_meter_policy *policy = NULL;
uint32_t id = 0;
int ret;
(void)buf;
(void)size;
ctx->objdata = 0;
ctx->object = &id;
ctx->objmask = NULL;
ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
ctx->object = action;
if (ret != (int)len)
return ret;
/* set meter policy */
if (action) {
meter = (struct rte_flow_action_meter_mark *)
(uintptr_t)(action->conf);
policy = port_meter_policy_get_by_id(ctx->port, id);
meter->policy = policy;
ret = (policy) ? ret : -1;
}
return ret;
}
/** Parse set command, initialize output buffer for subsequent tokens. */
static int
parse_set_raw_encap_decap(struct context *ctx, const struct token *token,

View File

@ -2125,6 +2125,29 @@ port_meter_policy_add(portid_t port_id, uint32_t policy_id,
return ret;
}
struct rte_flow_meter_profile *
port_meter_profile_get_by_id(portid_t port_id, uint32_t id)
{
struct rte_mtr_error error;
struct rte_flow_meter_profile *profile;
profile = rte_mtr_meter_profile_get(port_id, id, &error);
if (!profile)
print_mtr_err_msg(&error);
return profile;
}
struct rte_flow_meter_policy *
port_meter_policy_get_by_id(portid_t port_id, uint32_t id)
{
struct rte_mtr_error error;
struct rte_flow_meter_policy *policy;
policy = rte_mtr_meter_policy_get(port_id, id, &error);
if (!policy)
print_mtr_err_msg(&error);
return policy;
}
/** Validate flow rule. */
int
port_flow_validate(portid_t port_id,
@ -2750,6 +2773,9 @@ port_queue_action_handle_update(portid_t port_id,
struct rte_flow_error error;
struct rte_flow_action_handle *action_handle;
struct queue_job *job;
struct port_indirect_action *pia;
struct rte_flow_update_meter_mark mtr_update;
const void *update;
action_handle = port_action_handle_get_by_id(port_id, id);
if (!action_handle)
@ -2768,8 +2794,27 @@ port_queue_action_handle_update(portid_t port_id,
}
job->type = QUEUE_JOB_TYPE_ACTION_UPDATE;
pia = action_get_by_id(port_id, id);
if (!pia) {
free(job);
return -EINVAL;
}
if (pia->type == RTE_FLOW_ACTION_TYPE_METER_MARK) {
rte_memcpy(&mtr_update.meter_mark, action->conf,
sizeof(struct rte_flow_action_meter_mark));
mtr_update.profile_valid = 1;
mtr_update.policy_valid = 1;
mtr_update.color_mode_valid = 1;
mtr_update.init_color_valid = 1;
mtr_update.state_valid = 1;
update = &mtr_update;
} else {
update = action;
}
if (rte_flow_async_action_handle_update(port_id, queue_id, &attr,
action_handle, action, job, &error)) {
action_handle, update, job, &error)) {
free(job);
return port_flow_complain(&error);
}

View File

@ -966,6 +966,10 @@ void port_flow_tunnel_create(portid_t port_id, const struct tunnel_ops *ops);
int port_flow_isolate(portid_t port_id, int set);
int port_meter_policy_add(portid_t port_id, uint32_t policy_id,
const struct rte_flow_action *actions);
struct rte_flow_meter_profile *port_meter_profile_get_by_id(portid_t port_id,
uint32_t id);
struct rte_flow_meter_policy *port_meter_policy_get_by_id(portid_t port_id,
uint32_t id);
void rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id);
void tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id);

View File

@ -3274,6 +3274,31 @@ This action is meant to use the same structure as `Action: PORT_REPRESENTOR`_.
See also `Item: REPRESENTED_PORT`_.
Action: ``METER_MARK``
^^^^^^^^^^^^^^^^^^^^^^
Meters a packet stream and marks its packets with colors.
Unlike the ``METER`` action, policing is optional and may be
performed later with the help of the ``METER_COLOR`` item.
The profile and/or policy objects have to be created
using the rte_mtr_profile_add()/rte_mtr_policy_add() API.
Pointers to these objects are used as action parameters
and need to be retrieved using the rte_mtr_profile_get() API
and rte_mtr_policy_get() API respectively.
.. _table_rte_flow_action_meter_mark:
.. table:: METER_MARK
+------------------+----------------------+
| Field | Value |
+==================+======================+
| ``profile`` | Meter profile object |
+------------------+----------------------+
| ``policy`` | Meter policy object |
+------------------+----------------------+
Negative types
~~~~~~~~~~~~~~

View File

@ -79,6 +79,7 @@ New Features
* Added METER_COLOR item to match color marker set by a meter.
* Added ability to set color marker via modify field flow API.
* Added meter API to get a pointer to profile/policy by their ID.
* Added METER_MARK action for metering with lockless profile/policy access.
* **Updated Intel iavf driver.**

View File

@ -3971,6 +3971,14 @@ This section lists supported actions and their attributes, if any.
- ``ethdev_port_id {unsigned}``: ethdev port ID
- ``meter_mark``: meter the directed packets using profile and policy
- ``mtr_profile {unsigned}``: meter profile ID to use
- ``mtr_policy {unsigned}``: meter policy ID to use
- ``mtr_color_mode {unsigned}``: meter color-awareness mode (blind/aware)
- ``mtr_init_color {value}``: initial color value (green/yellow/red)
- ``mtr_state {unsigned}``: meter state (disabled/enabled)
Destroying flow rules
~~~~~~~~~~~~~~~~~~~~~

View File

@ -256,6 +256,7 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = {
MK_FLOW_ACTION(CONNTRACK, sizeof(struct rte_flow_action_conntrack)),
MK_FLOW_ACTION(PORT_REPRESENTOR, sizeof(struct rte_flow_action_ethdev)),
MK_FLOW_ACTION(REPRESENTED_PORT, sizeof(struct rte_flow_action_ethdev)),
MK_FLOW_ACTION(METER_MARK, sizeof(struct rte_flow_action_meter_mark)),
};
int

View File

@ -2789,6 +2789,14 @@ enum rte_flow_action_type {
* @see struct rte_flow_action_ethdev
*/
RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
/**
* Traffic metering and marking (MTR).
*
* @see struct rte_flow_action_meter_mark
* See file rte_mtr.h for MTR profile object configuration.
*/
RTE_FLOW_ACTION_TYPE_METER_MARK,
};
/**
@ -3640,6 +3648,54 @@ struct rte_flow_action_modify_field {
uint32_t width; /**< Number of bits to use from a source field. */
};
/**
* RTE_FLOW_ACTION_TYPE_METER_MARK
*
* Traffic metering and marking (MTR).
*
* Meters a packet stream and marks its packets either
* green, yellow, or red according to the specified profile.
* The policy is optional and may be specified for defining
* subsequent actions based on a color assigned by MTR.
* Alternatively, the METER_COLOR item may be used for this.
*/
struct rte_flow_action_meter_mark {
/**< Profile config retrieved with rte_mtr_profile_get(). */
struct rte_flow_meter_profile *profile;
/**< Policy config retrieved with rte_mtr_policy_get(). */
struct rte_flow_meter_policy *policy;
/** Metering mode: 0 - Color-Blind, 1 - Color-Aware. */
int color_mode;
/** Initial Color applied to packets in Color-Aware mode. */
enum rte_color init_color;
/** Metering state: 0 - Disabled, 1 - Enabled. */
int state;
};
/**
* RTE_FLOW_ACTION_TYPE_METER_MARK
*
* Wrapper structure for the context update interface.
*
*/
struct rte_flow_update_meter_mark {
/** New meter_mark parameters to be updated. */
struct rte_flow_action_meter_mark meter_mark;
/** The profile will be updated. */
uint32_t profile_valid:1;
/** The policy will be updated. */
uint32_t policy_valid:1;
/** The color mode will be updated. */
uint32_t color_mode_valid:1;
/** The initial color will be updated. */
uint32_t init_color_valid:1;
/** The meter state will be updated. */
uint32_t state_valid:1;
/** Reserved bits for the future usage. */
uint32_t reserved:27;
};
/* Mbuf dynamic field offset for metadata. */
extern int32_t rte_flow_dynf_metadata_offs;