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:
parent
ece19cca30
commit
9c4a0c1859
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -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.**
|
||||
|
||||
|
@ -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
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user