Skip to content

Commit

Permalink
ethdev: add indirect list flow action
Browse files Browse the repository at this point in the history
Indirect API creates a shared flow action with unique action handle.
Flow rules can access the shared flow action and resources related to
that action through the indirect action handle.
In addition, the API allows to update existing shared flow action
configuration.  After the update completes, new action configuration
is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several
  flow actions, while legacy indirect action handle references
  single action only.
  Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to
  existing shared handle.
  Updates of flow rule specific configuration will not change the base
  action configuration.
  Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation
  and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows
  that referenced indirect actions list handle.
  Action mutable context can be changed by explicit invocation
  of indirect handle update function.
• Flow mutable context is private to a flow.
  Flow mutable context can be updated by indirect list handle
  flow rule configuration.

flow 1:
 / indirect handle H conf C1 /
                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------
            v                action immutable context
            =========================================================

Indirect action types - immutable, action / flow mutable, are mutually
exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is
  action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable
  member.
• Indirect QUOTA flow action does not define flow mutable members.

If indirect list handle was created from a list of actions
A1 / A2 ... An / END
indirect list flow action can update Ai flow mutable context in the
action configuration parameter.
Indirect list action configuration is and array [C1, C2,  .., Cn]
where Ci corresponds to Ai in the action handle source.
Ci configuration element points Ai flow mutable update, or it's NULL
if Ai has no flow mutable update.
Indirect list action configuration can be NULL if the action
has no flow mutable updates.

Template API:

Action template format:

	template .. indirect_list handle Htmpl conf Ctmpl ..
	mask     .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), it will be fixed in that template.
  Otherwise, indirect action value is set in a flow rule.

2 If Htmpl and Ctmpl[i] were masked (Hmask !=0 and Cmask[i] != 0),
  Htmpl's Ai action flow mutable context fill be updated to
  Ctmpl[i] values and will be fixed in that template.

Flow rule format:

	actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was not masked in actions template, Hflow references an
  action of the same type as Htmpl.

4 Cflow[i] updates handle's Ai flow mutable configuration if
  the Ci was not masked in action template.

Signed-off-by: Gregory Etelson <getelson@nvidia.com>
Signed-off-by: 0-day Robot <robot@bytheb.org>
  • Loading branch information
getelson-at-mellanox authored and ovsrobot committed May 28, 2023
1 parent c9df59b commit 902cda4
Show file tree
Hide file tree
Showing 12 changed files with 1,061 additions and 42 deletions.
207 changes: 206 additions & 1 deletion app/test-pmd/cmdline_flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ enum index {

/* Queue indirect action arguments */
QUEUE_INDIRECT_ACTION_CREATE,
QUEUE_INDIRECT_ACTION_LIST_CREATE,
QUEUE_INDIRECT_ACTION_UPDATE,
QUEUE_INDIRECT_ACTION_DESTROY,
QUEUE_INDIRECT_ACTION_QUERY,
Expand All @@ -157,6 +158,7 @@ enum index {
QUEUE_INDIRECT_ACTION_TRANSFER,
QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
QUEUE_INDIRECT_ACTION_SPEC,
QUEUE_INDIRECT_ACTION_LIST,

/* Queue indirect action update arguments */
QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
Expand Down Expand Up @@ -242,6 +244,8 @@ enum index {

/* Indirect action arguments */
INDIRECT_ACTION_CREATE,
INDIRECT_ACTION_LIST_CREATE,
INDIRECT_ACTION_FLOW_CONF_CREATE,
INDIRECT_ACTION_UPDATE,
INDIRECT_ACTION_DESTROY,
INDIRECT_ACTION_QUERY,
Expand All @@ -253,6 +257,8 @@ enum index {
INDIRECT_ACTION_EGRESS,
INDIRECT_ACTION_TRANSFER,
INDIRECT_ACTION_SPEC,
INDIRECT_ACTION_LIST,
INDIRECT_ACTION_FLOW_CONF,

/* Indirect action destroy arguments */
INDIRECT_ACTION_DESTROY_ID,
Expand Down Expand Up @@ -626,6 +632,11 @@ enum index {
ACTION_SAMPLE_INDEX,
ACTION_SAMPLE_INDEX_VALUE,
ACTION_INDIRECT,
ACTION_INDIRECT_LIST,
ACTION_INDIRECT_LIST_HANDLE,
ACTION_INDIRECT_LIST_CONF,
INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
INDIRECT_LIST_ACTION_ID2PTR_CONF,
ACTION_SHARED_INDIRECT,
INDIRECT_ACTION_PORT,
INDIRECT_ACTION_ID2PTR,
Expand Down Expand Up @@ -1266,6 +1277,7 @@ static const enum index next_qia_create_attr[] = {
QUEUE_INDIRECT_ACTION_TRANSFER,
QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
QUEUE_INDIRECT_ACTION_SPEC,
QUEUE_INDIRECT_ACTION_LIST,
ZERO,
};

Expand Down Expand Up @@ -1294,6 +1306,8 @@ static const enum index next_ia_create_attr[] = {
INDIRECT_ACTION_EGRESS,
INDIRECT_ACTION_TRANSFER,
INDIRECT_ACTION_SPEC,
INDIRECT_ACTION_LIST,
INDIRECT_ACTION_FLOW_CONF,
ZERO,
};

Expand All @@ -1303,6 +1317,13 @@ static const enum index next_ia[] = {
ZERO
};

static const enum index next_ial[] = {
ACTION_INDIRECT_LIST_HANDLE,
ACTION_INDIRECT_LIST_CONF,
ACTION_NEXT,
ZERO
};

static const enum index next_qia_qu_attr[] = {
QUEUE_INDIRECT_ACTION_QU_MODE,
QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
Expand Down Expand Up @@ -2013,6 +2034,7 @@ static const enum index next_action[] = {
ACTION_AGE_UPDATE,
ACTION_SAMPLE,
ACTION_INDIRECT,
ACTION_INDIRECT_LIST,
ACTION_SHARED_INDIRECT,
ACTION_MODIFY_FIELD,
ACTION_CONNTRACK,
Expand Down Expand Up @@ -2289,6 +2311,7 @@ static const enum index next_action_sample[] = {
ACTION_RAW_ENCAP,
ACTION_VXLAN_ENCAP,
ACTION_NVGRE_ENCAP,
ACTION_REPRESENTED_PORT,
ACTION_NEXT,
ZERO,
};
Expand Down Expand Up @@ -2539,6 +2562,10 @@ static int parse_ia_destroy(struct context *ctx, const struct token *token,
static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
const char *str, unsigned int len, void *buf,
unsigned int size);

static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
const char *str, unsigned int len, void *buf,
unsigned int size);
static int parse_ia_port(struct context *ctx, const struct token *token,
const char *str, unsigned int len, void *buf,
unsigned int size);
Expand Down Expand Up @@ -2627,6 +2654,16 @@ static int
comp_qu_mode_name(struct context *ctx, const struct token *token,
unsigned int ent, char *buf, unsigned int size);

struct indlst_conf {
uint32_t id;
uint32_t conf_num;
struct rte_flow_action *actions;
const void **conf;
SLIST_ENTRY(indlst_conf) next;
};

static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);

/** Token definitions. */
static const struct token token_list[] = {
/* Special tokens. */
Expand Down Expand Up @@ -3426,6 +3463,12 @@ static const struct token token_list[] = {
.help = "specify action to create indirect handle",
.next = NEXT(next_action),
},
[QUEUE_INDIRECT_ACTION_LIST] = {
.name = "list",
.help = "specify actions for indirect handle list",
.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
.call = parse_qia,
},
/* Top-level command. */
[PUSH] = {
.name = "push",
Expand Down Expand Up @@ -6775,6 +6818,37 @@ static const struct token token_list[] = {
.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
.call = parse_vc,
},
[ACTION_INDIRECT_LIST] = {
.name = "indirect_list",
.help = "apply indirect list action by id",
.priv = PRIV_ACTION(INDIRECT_LIST,
sizeof(struct
rte_flow_action_indirect_list)),
.next = NEXT(next_ial),
.call = parse_vc,
},
[ACTION_INDIRECT_LIST_HANDLE] = {
.name = "handle",
.help = "indirect list handle",
.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
},
[ACTION_INDIRECT_LIST_CONF] = {
.name = "conf",
.help = "indirect list configuration",
.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
},
[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
.type = "UNSIGNED",
.help = "unsigned integer value",
.call = parse_indlst_id2ptr,
},
[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
.type = "UNSIGNED",
.help = "unsigned integer value",
.call = parse_indlst_id2ptr,
},
[ACTION_SHARED_INDIRECT] = {
.name = "shared_indirect",
.help = "apply indirect action by id and port",
Expand Down Expand Up @@ -6823,6 +6897,18 @@ static const struct token token_list[] = {
.help = "specify action to create indirect handle",
.next = NEXT(next_action),
},
[INDIRECT_ACTION_LIST] = {
.name = "list",
.help = "specify actions for indirect handle list",
.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
.call = parse_ia,
},
[INDIRECT_ACTION_FLOW_CONF] = {
.name = "flow_conf",
.help = "specify actions configuration for indirect handle list",
.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
.call = parse_ia,
},
[ACTION_POL_G] = {
.name = "g_actions",
.help = "submit a list of associated actions for green",
Expand Down Expand Up @@ -7181,6 +7267,12 @@ parse_ia(struct context *ctx, const struct token *token,
return len;
case INDIRECT_ACTION_QU_MODE:
return len;
case INDIRECT_ACTION_LIST:
out->command = INDIRECT_ACTION_LIST_CREATE;
return len;
case INDIRECT_ACTION_FLOW_CONF:
out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
return len;
default:
return -1;
}
Expand Down Expand Up @@ -7278,6 +7370,9 @@ parse_qia(struct context *ctx, const struct token *token,
return len;
case QUEUE_INDIRECT_ACTION_QU_MODE:
return len;
case QUEUE_INDIRECT_ACTION_LIST:
out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
return len;
default:
return -1;
}
Expand Down Expand Up @@ -7454,10 +7549,12 @@ parse_vc(struct context *ctx, const struct token *token,
return -1;
break;
case ACTIONS:
out->args.vc.actions =
out->args.vc.actions = out->args.vc.pattern ?
(void *)RTE_ALIGN_CEIL((uintptr_t)
(out->args.vc.pattern +
out->args.vc.pattern_n),
sizeof(double)) :
(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
sizeof(double));
ctx->object = out->args.vc.actions;
ctx->objmask = NULL;
Expand Down Expand Up @@ -10412,6 +10509,49 @@ parse_ia_id2ptr(struct context *ctx, const struct token *token,
return ret;
}

static int
parse_indlst_id2ptr(struct context *ctx, const struct token *token,
const char *str, unsigned int len,
void __rte_unused *buf, unsigned int __rte_unused size)
{
struct rte_flow_action *action = ctx->object;
struct rte_flow_action_indirect_list *action_conf;
const struct indlst_conf *indlst_conf;
uint32_t id;
int ret;

if (!action)
return -1;
ctx->objdata = 0;
ctx->object = &id;
ctx->objmask = NULL;
ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
if (ret != (int)len)
return ret;
ctx->object = action;
action_conf = (void *)(uintptr_t)action->conf;
action_conf->conf = NULL;
switch (ctx->curr) {
case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
action_conf->handle = (typeof(action_conf->handle))
port_action_handle_get_by_id(ctx->port, id);
if (!action_conf->handle) {
printf("no indirect list handle for id %u\n", id);
return -1;
}
break;
case INDIRECT_LIST_ACTION_ID2PTR_CONF:
indlst_conf = indirect_action_list_conf_get(id);
if (!indlst_conf)
return -1;
action_conf->conf = (const void **)indlst_conf->conf;
break;
default:
break;
}
return ret;
}

static int
parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
const char *str, unsigned int len,
Expand Down Expand Up @@ -11453,6 +11593,64 @@ cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
*hdr = &cmd_flow_token_hdr;
}

static SLIST_HEAD(, indlst_conf) indlst_conf_head =
SLIST_HEAD_INITIALIZER();

static void
indirect_action_flow_conf_create(const struct buffer *in)
{
int len, ret;
uint32_t i;
struct indlst_conf *indlst_conf = NULL;
size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
struct rte_flow_action *src = in->args.vc.actions;

if (!in->args.vc.actions_n)
goto end;
len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
if (len <= 0)
goto end;
len = RTE_ALIGN(len, 16);

indlst_conf = calloc(1, base + len +
in->args.vc.actions_n * sizeof(uintptr_t));
if (!indlst_conf)
goto end;
indlst_conf->id = in->args.vc.attr.group;
indlst_conf->conf_num = in->args.vc.actions_n - 1;
indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
len, src, NULL);
if (ret <= 0) {
free(indlst_conf);
indlst_conf = NULL;
goto end;
}
indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
for (i = 0; i < indlst_conf->conf_num; i++)
indlst_conf->conf[i] = indlst_conf->actions[i].conf;
SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
end:
if (indlst_conf)
printf("created indirect action list configuration %u\n",
in->args.vc.attr.group);
else
printf("cannot create indirect action list configuration %u\n",
in->args.vc.attr.group);
}

static const struct indlst_conf *
indirect_action_list_conf_get(uint32_t conf_id)
{
const struct indlst_conf *conf;

SLIST_FOREACH(conf, &indlst_conf_head, next) {
if (conf->id == conf_id)
return conf;
}
return NULL;
}

/** Dispatch parsed buffer to function calls. */
static void
cmd_flow_parsed(const struct buffer *in)
Expand Down Expand Up @@ -11532,6 +11730,7 @@ cmd_flow_parsed(const struct buffer *in)
in->args.aged.destroy);
break;
case QUEUE_INDIRECT_ACTION_CREATE:
case QUEUE_INDIRECT_ACTION_LIST_CREATE:
port_queue_action_handle_create(
in->port, in->queue, in->postpone,
in->args.vc.attr.group,
Expand Down Expand Up @@ -11567,15 +11766,20 @@ cmd_flow_parsed(const struct buffer *in)
in->args.vc.actions);
break;
case INDIRECT_ACTION_CREATE:
case INDIRECT_ACTION_LIST_CREATE:
port_action_handle_create(
in->port, in->args.vc.attr.group,
in->command == INDIRECT_ACTION_LIST_CREATE,
&((const struct rte_flow_indir_action_conf) {
.ingress = in->args.vc.attr.ingress,
.egress = in->args.vc.attr.egress,
.transfer = in->args.vc.attr.transfer,
}),
in->args.vc.actions);
break;
case INDIRECT_ACTION_FLOW_CONF_CREATE:
indirect_action_flow_conf_create(in);
break;
case INDIRECT_ACTION_DESTROY:
port_action_handle_destroy(in->port,
in->args.ia_destroy.action_id_n,
Expand Down Expand Up @@ -11653,6 +11857,7 @@ cmd_flow_parsed(const struct buffer *in)
default:
break;
}
fflush(stdout);
}

/** Token generator and output processing callback (cmdline API). */
Expand Down

0 comments on commit 902cda4

Please sign in to comment.