@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
};
@@ -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,
};
@@ -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,
@@ -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,
@@ -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,
};
@@ -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);
@@ -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. */
@@ -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",
@@ -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",
@@ -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",
@@ -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;
}
@@ -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;
}
@@ -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;
@@ -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,
@@ -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)
@@ -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,
@@ -11567,8 +11766,10 @@ 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,
@@ -11576,6 +11777,9 @@ cmd_flow_parsed(const struct buffer *in)
}),
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,
@@ -11653,6 +11857,7 @@ cmd_flow_parsed(const struct buffer *in)
default:
break;
}
+ fflush(stdout);
}
/** Token generator and output processing callback (cmdline API). */
@@ -1764,19 +1764,13 @@ port_flow_configure(portid_t port_id,
return 0;
}
-/** Create indirect action */
-int
-port_action_handle_create(portid_t port_id, uint32_t id,
- const struct rte_flow_indir_action_conf *conf,
- const struct rte_flow_action *action)
+static int
+action_handle_create(portid_t port_id,
+ struct port_indirect_action *pia,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error)
{
- struct port_indirect_action *pia;
- int ret;
- struct rte_flow_error error;
-
- ret = action_alloc(port_id, id, &pia);
- if (ret)
- return ret;
if (action->type == RTE_FLOW_ACTION_TYPE_AGE) {
struct rte_flow_action_age *age =
(struct rte_flow_action_age *)(uintptr_t)(action->conf);
@@ -1785,20 +1779,52 @@ port_action_handle_create(portid_t port_id, uint32_t id,
age->context = &pia->age_type;
} else if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK) {
struct rte_flow_action_conntrack *ct =
- (struct rte_flow_action_conntrack *)(uintptr_t)(action->conf);
+ (struct rte_flow_action_conntrack *)(uintptr_t)(action->conf);
memcpy(ct, &conntrack_context, sizeof(*ct));
}
+ pia->type = action->type;
+ pia->handle = rte_flow_action_handle_create(port_id, conf, action,
+ error);
+ return pia->handle ? 0 : -1;
+}
+
+static int
+action_list_handle_create(portid_t port_id,
+ struct port_indirect_action *pia,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error)
+{
+ pia->type = RTE_FLOW_ACTION_TYPE_INDIRECT_LIST;
+ pia->list_handle =
+ rte_flow_action_list_handle_create(port_id, conf,
+ actions, error);
+ return pia->list_handle ? 0 : -1;
+}
+/** Create indirect action */
+int
+port_action_handle_create(portid_t port_id, uint32_t id, bool indirect_list,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *action)
+{
+ struct port_indirect_action *pia;
+ int ret;
+ struct rte_flow_error error;
+
+ ret = action_alloc(port_id, id, &pia);
+ if (ret)
+ return ret;
/* Poisoning to make sure PMDs update it in case of error. */
memset(&error, 0x22, sizeof(error));
- pia->handle = rte_flow_action_handle_create(port_id, conf, action,
- &error);
- if (!pia->handle) {
+ ret = indirect_list ?
+ action_list_handle_create(port_id, pia, conf, action, &error) :
+ action_handle_create(port_id, pia, conf, action, &error);
+ if (ret) {
uint32_t destroy_id = pia->id;
port_action_handle_destroy(port_id, 1, &destroy_id);
return port_flow_complain(&error);
}
- pia->type = action->type;
printf("Indirect action #%u created\n", pia->id);
return 0;
}
@@ -1833,10 +1859,17 @@ port_action_handle_destroy(portid_t port_id,
*/
memset(&error, 0x33, sizeof(error));
- if (pia->handle && rte_flow_action_handle_destroy(
- port_id, pia->handle, &error)) {
- ret = port_flow_complain(&error);
- continue;
+ if (pia->handle) {
+ ret = pia->type ==
+ RTE_FLOW_ACTION_TYPE_INDIRECT_LIST ?
+ rte_flow_action_list_handle_destroy
+ (port_id, pia->list_handle, &error) :
+ rte_flow_action_handle_destroy
+ (port_id, pia->handle, &error);
+ if (ret) {
+ ret = port_flow_complain(&error);
+ continue;
+ }
}
*tmp = pia->next;
printf("Indirect action #%u destroyed\n", pia->id);
@@ -1867,11 +1900,18 @@ port_action_handle_flush(portid_t port_id)
/* Poisoning to make sure PMDs update it in case of error. */
memset(&error, 0x44, sizeof(error));
- if (pia->handle != NULL &&
- rte_flow_action_handle_destroy
- (port_id, pia->handle, &error) != 0) {
- printf("Indirect action #%u not destroyed\n", pia->id);
- ret = port_flow_complain(&error);
+ if (pia->handle != NULL) {
+ ret = pia->type ==
+ RTE_FLOW_ACTION_TYPE_INDIRECT_LIST ?
+ rte_flow_action_list_handle_destroy
+ (port_id, pia->list_handle, &error) :
+ rte_flow_action_handle_destroy
+ (port_id, pia->handle, &error);
+ if (ret) {
+ printf("Indirect action #%u not destroyed\n",
+ pia->id);
+ ret = port_flow_complain(&error);
+ }
tmp = &pia->next;
} else {
*tmp = pia->next;
@@ -2822,6 +2862,45 @@ port_queue_flow_destroy(portid_t port_id, queueid_t queue_id,
return ret;
}
+static void
+queue_action_handle_create(portid_t port_id, uint32_t queue_id,
+ struct port_indirect_action *pia,
+ struct queue_job *job,
+ const struct rte_flow_op_attr *attr,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error)
+{
+ if (action->type == RTE_FLOW_ACTION_TYPE_AGE) {
+ struct rte_flow_action_age *age =
+ (struct rte_flow_action_age *)(uintptr_t)(action->conf);
+
+ pia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION;
+ age->context = &pia->age_type;
+ }
+ /* Poisoning to make sure PMDs update it in case of error. */
+ pia->handle = rte_flow_async_action_handle_create(port_id, queue_id,
+ attr, conf, action,
+ job, error);
+ pia->type = action->type;
+}
+
+static void
+queue_action_list_handle_create(portid_t port_id, uint32_t queue_id,
+ struct port_indirect_action *pia,
+ struct queue_job *job,
+ const struct rte_flow_op_attr *attr,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error)
+{
+ /* Poisoning to make sure PMDs update it in case of error. */
+ pia->type = RTE_FLOW_ACTION_TYPE_INDIRECT_LIST;
+ pia->list_handle = rte_flow_async_action_list_handle_create
+ (port_id, queue_id, attr, conf, action,
+ job, error);
+}
+
/** Enqueue indirect action create operation. */
int
port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
@@ -2835,6 +2914,8 @@ port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
int ret;
struct rte_flow_error error;
struct queue_job *job;
+ bool is_indirect_list = action[1].type != RTE_FLOW_ACTION_TYPE_END;
+
ret = action_alloc(port_id, id, &pia);
if (ret)
@@ -2853,17 +2934,16 @@ port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
job->type = QUEUE_JOB_TYPE_ACTION_CREATE;
job->pia = pia;
- if (action->type == RTE_FLOW_ACTION_TYPE_AGE) {
- struct rte_flow_action_age *age =
- (struct rte_flow_action_age *)(uintptr_t)(action->conf);
-
- pia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION;
- age->context = &pia->age_type;
- }
/* Poisoning to make sure PMDs update it in case of error. */
memset(&error, 0x88, sizeof(error));
- pia->handle = rte_flow_async_action_handle_create(port_id, queue_id,
- &attr, conf, action, job, &error);
+
+ if (is_indirect_list)
+ queue_action_list_handle_create(port_id, queue_id, pia, job,
+ &attr, conf, action, &error);
+ else
+ queue_action_handle_create(port_id, queue_id, pia, job, &attr,
+ conf, action, &error);
+
if (!pia->handle) {
uint32_t destroy_id = pia->id;
port_queue_action_handle_destroy(port_id, queue_id,
@@ -2871,7 +2951,6 @@ port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
free(job);
return port_flow_complain(&error);
}
- pia->type = action->type;
printf("Indirect action #%u creation queued\n", pia->id);
return 0;
}
@@ -2920,9 +2999,15 @@ port_queue_action_handle_destroy(portid_t port_id,
}
job->type = QUEUE_JOB_TYPE_ACTION_DESTROY;
job->pia = pia;
-
- if (rte_flow_async_action_handle_destroy(port_id,
- queue_id, &attr, pia->handle, job, &error)) {
+ ret = pia->type == RTE_FLOW_ACTION_TYPE_INDIRECT_LIST ?
+ rte_flow_async_action_list_handle_destroy
+ (port_id, queue_id,
+ &attr, pia->list_handle,
+ job, &error) :
+ rte_flow_async_action_handle_destroy
+ (port_id, queue_id, &attr, pia->handle,
+ job, &error);
+ if (ret) {
free(job);
ret = port_flow_complain(&error);
continue;
@@ -228,7 +228,12 @@ struct port_indirect_action {
struct port_indirect_action *next; /**< Next flow in list. */
uint32_t id; /**< Indirect action ID. */
enum rte_flow_action_type type; /**< Action type. */
- struct rte_flow_action_handle *handle; /**< Indirect action handle. */
+ union {
+ struct rte_flow_action_handle *handle;
+ /**< Indirect action handle. */
+ struct rte_flow_action_list_handle *list_handle;
+ /**< Indirect action list handle*/
+ };
enum age_action_context_type age_type; /**< Age action context type. */
};
@@ -921,7 +926,7 @@ void update_fwd_ports(portid_t new_pid);
void set_fwd_eth_peer(portid_t port_id, char *peer_addr);
void port_mtu_set(portid_t port_id, uint16_t mtu);
-int port_action_handle_create(portid_t port_id, uint32_t id,
+int port_action_handle_create(portid_t port_id, uint32_t id, bool indirect_list,
const struct rte_flow_indir_action_conf *conf,
const struct rte_flow_action *action);
int port_action_handle_destroy(portid_t port_id,
@@ -158,6 +158,7 @@ drop =
flag =
inc_tcp_ack =
inc_tcp_seq =
+indirect_list =
jump =
mac_swap =
mark =
@@ -3300,6 +3300,125 @@ The ``quota`` value is reduced according to ``mode`` setting.
| ``RTE_FLOW_QUOTA_MODE_L3`` | Count packet bytes starting from L3 |
+------------------+----------------------------------------------------+
+Action: ``INDIRECT_LIST``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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.
+
+Indirect action types - immutable, action / flow mutable, are mutually
+exclusive and depend on the action definition.
+
+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 is NULL if the action has no flow
+mutable updates. Otherwise it points to an array of n flow mutable
+configuration pointers.
+
+**Template API:**
+
+*Action template format:*
+
+``template .. indirect_list handle Htmpl conf Ctmpl ..``
+
+``mask .. indirect_list handle Hmask conf Cmask ..``
+
+- If Htmpl was masked (Hmask != 0), it will be fixed in that template.
+ Otherwise, indirect action value is set in a flow rule.
+
+- 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 ..``
+
+- If Htmpl was not masked in actions template, Hflow references an
+ action of the same type as Htmpl.
+
+- Cflow[i] updates handle's Ai flow mutable configuration if
+ the Ci was not masked in action template.
+
+.. _table_rte_flow_action_indirect_list:
+
+.. table:: INDIRECT_LIST
+
+ +------------------+----------------------------------+
+ | Field | Value |
+ +==================+==================================+
+ | ``handle`` | Indirect action list handle |
+ +------------------+----------------------------------+
+ | ``conf`` | Flow mutable configuration array |
+ +------------------+----------------------------------+
+
+.. code-block:: text
+
+ 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
+ =========================================================
+
Negative types
~~~~~~~~~~~~~~
@@ -55,6 +55,8 @@ New Features
Also, make sure to start the actual text at the margin.
=======================================================
+ * **Added INDIRECT_LIST flow action.**
+
Removed Items
-------------
@@ -2447,6 +2447,94 @@ RTE_TRACE_POINT_FP(
rte_trace_point_emit_int(ret);
)
+RTE_TRACE_POINT_FP(
+ rte_flow_trace_action_list_handle_create,
+ RTE_TRACE_POINT_ARGS
+ (uint16_t port_id,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *actions, int ret),
+ rte_trace_point_emit_u16(port_id);
+ rte_trace_point_emit_ptr(conf);
+ rte_trace_point_emit_ptr(actions);
+ rte_trace_point_emit_int(ret);
+)
+
+RTE_TRACE_POINT_FP(
+ rte_flow_trace_action_list_handle_destroy,
+ RTE_TRACE_POINT_ARGS
+ (uint16_t port_id,
+ const struct rte_flow_action_list_handle *handle, int ret),
+ rte_trace_point_emit_u16(port_id);
+ rte_trace_point_emit_ptr(handle);
+ rte_trace_point_emit_int(ret);
+)
+
+RTE_TRACE_POINT_FP(
+ rte_flow_trace_async_action_list_handle_create,
+ RTE_TRACE_POINT_ARGS
+ (uint16_t port_id, uint32_t queue_id,
+ const struct rte_flow_op_attr *op_attr,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *action,
+ const void *user_data, int ret),
+ rte_trace_point_emit_u16(port_id);
+ rte_trace_point_emit_u32(queue_id);
+ rte_trace_point_emit_ptr(op_attr);
+ rte_trace_point_emit_ptr(conf);
+ rte_trace_point_emit_ptr(action);
+ rte_trace_point_emit_ptr(user_data);
+ rte_trace_point_emit_int(ret);
+)
+
+RTE_TRACE_POINT_FP(
+ rte_flow_trace_async_action_list_handle_destroy,
+ RTE_TRACE_POINT_ARGS
+ (uint16_t port_id, uint32_t queue_id,
+ const struct rte_flow_op_attr *op_attr,
+ const struct rte_flow_action_list_handle *handle,
+ const void *user_data, int ret),
+ rte_trace_point_emit_u16(port_id);
+ rte_trace_point_emit_u32(queue_id);
+ rte_trace_point_emit_ptr(op_attr);
+ rte_trace_point_emit_ptr(handle);
+ rte_trace_point_emit_ptr(user_data);
+ rte_trace_point_emit_int(ret);
+)
+
+RTE_TRACE_POINT_FP(
+ rte_flow_trace_action_list_handle_query_update,
+ RTE_TRACE_POINT_ARGS
+ (uint16_t port_id,
+ const struct rte_flow_action_list_handle *handle,
+ const void **update, void **query,
+ enum rte_flow_query_update_mode mode, int ret),
+ rte_trace_point_emit_u16(port_id);
+ rte_trace_point_emit_ptr(handle);
+ rte_trace_point_emit_ptr(update);
+ rte_trace_point_emit_ptr(query);
+ rte_trace_point_emit_int(mode);
+ rte_trace_point_emit_int(ret);
+)
+
+RTE_TRACE_POINT_FP(
+ rte_flow_trace_async_action_list_handle_query_update,
+ RTE_TRACE_POINT_ARGS
+ (uint16_t port_id, uint32_t queue_id,
+ const struct rte_flow_op_attr *attr,
+ const struct rte_flow_action_list_handle *handle,
+ const void **update, void **query,
+ enum rte_flow_query_update_mode mode,
+ void *user_data, int ret),
+ rte_trace_point_emit_u16(port_id);
+ rte_trace_point_emit_u32(queue_id);
+ rte_trace_point_emit_ptr(attr);
+ rte_trace_point_emit_ptr(handle);
+ rte_trace_point_emit_ptr(update);
+ rte_trace_point_emit_ptr(query);
+ rte_trace_point_emit_int(mode);
+ rte_trace_point_emit_ptr(user_data);
+ rte_trace_point_emit_int(ret);
+)
#ifdef __cplusplus
}
#endif
@@ -750,3 +750,21 @@ RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_add,
RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_delete,
lib.ethdev.tm.wred_profile_delete)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_create,
+ lib.ethdev.flow.action_list_handle_create)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_destroy,
+ lib.ethdev.flow.action_list_handle_destroy)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_query_update,
+ lib.ethdev.flow.action_list_handle_query_update)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_create,
+ lib.ethdev.flow.async_action_list_handle_create)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_destroy,
+ lib.ethdev.flow.async_action_list_handle_destroy)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_query_update,
+ lib.ethdev.flow.async_action_list_handle_query_update)
@@ -259,6 +259,8 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = {
MK_FLOW_ACTION(METER_MARK, sizeof(struct rte_flow_action_meter_mark)),
MK_FLOW_ACTION(SEND_TO_KERNEL, 0),
MK_FLOW_ACTION(QUOTA, sizeof(struct rte_flow_action_quota)),
+ MK_FLOW_ACTION(INDIRECT_LIST,
+ sizeof(struct rte_flow_action_indirect_list)),
};
int
@@ -2171,3 +2173,172 @@ rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,
user_data, error);
return flow_err(port_id, ret, error);
}
+
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+ const
+ struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error)
+{
+ int ret;
+ struct rte_eth_dev *dev;
+ const struct rte_flow_ops *ops;
+ struct rte_flow_action_list_handle *handle;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, NULL);
+ ops = rte_flow_ops_get(port_id, error);
+ if (!ops || !ops->action_list_handle_create) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "action_list handle not supported");
+ return NULL;
+ }
+ dev = &rte_eth_devices[port_id];
+ handle = ops->action_list_handle_create(dev, conf, actions, error);
+ ret = flow_err(port_id, -rte_errno, error);
+ rte_flow_trace_action_list_handle_create(port_id, conf, actions, ret);
+ return handle;
+}
+
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+ struct rte_flow_action_list_handle *handle,
+ struct rte_flow_error *error)
+{
+ int ret;
+ struct rte_eth_dev *dev;
+ const struct rte_flow_ops *ops;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ ops = rte_flow_ops_get(port_id, error);
+ if (!ops || !ops->action_list_handle_destroy)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "action_list handle not supported");
+ dev = &rte_eth_devices[port_id];
+ ret = ops->action_list_handle_destroy(dev, handle, error);
+ ret = flow_err(port_id, ret, error);
+ rte_flow_trace_action_list_handle_destroy(port_id, handle, ret);
+ return ret;
+}
+
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t queue_id,
+ const struct rte_flow_op_attr *attr,
+ const struct
+ rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *actions,
+ void *user_data,
+ struct rte_flow_error *error)
+{
+ int ret;
+ struct rte_eth_dev *dev;
+ const struct rte_flow_ops *ops;
+ struct rte_flow_action_list_handle *handle;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, NULL);
+ ops = rte_flow_ops_get(port_id, error);
+ if (!ops || !ops->async_action_list_handle_create) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "action_list handle not supported");
+ return NULL;
+ }
+ dev = &rte_eth_devices[port_id];
+ handle = ops->async_action_list_handle_create(dev, queue_id, attr, conf,
+ actions, user_data,
+ error);
+ ret = flow_err(port_id, -rte_errno, error);
+ rte_flow_trace_async_action_list_handle_create(port_id, queue_id, attr,
+ conf, actions, user_data,
+ ret);
+ return handle;
+}
+
+int
+rte_flow_async_action_list_handle_destroy
+ (uint16_t port_id, uint32_t queue_id,
+ const struct rte_flow_op_attr *op_attr,
+ struct rte_flow_action_list_handle *handle,
+ void *user_data, struct rte_flow_error *error)
+{
+ int ret;
+ struct rte_eth_dev *dev;
+ const struct rte_flow_ops *ops;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ ops = rte_flow_ops_get(port_id, error);
+ if (!ops || !ops->async_action_list_handle_destroy)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "async action_list handle not supported");
+ dev = &rte_eth_devices[port_id];
+ ret = ops->async_action_list_handle_destroy(dev, queue_id, op_attr,
+ handle, user_data, error);
+ ret = flow_err(port_id, ret, error);
+ rte_flow_trace_async_action_list_handle_destroy(port_id, queue_id,
+ op_attr, handle,
+ user_data, ret);
+ return ret;
+}
+
+int
+rte_flow_action_list_handle_query_update
+ (uint16_t port_id,
+ const struct rte_flow_action_list_handle *handle,
+ const void **update, void **query,
+ enum rte_flow_query_update_mode mode,
+ struct rte_flow_error *error)
+{
+ int ret;
+ struct rte_eth_dev *dev;
+ const struct rte_flow_ops *ops;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ ops = rte_flow_ops_get(port_id, error);
+ if (!ops || !ops->action_list_handle_query_update)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "action_list query_update not supported");
+ dev = &rte_eth_devices[port_id];
+ ret = ops->action_list_handle_query_update(dev, handle, update, query,
+ mode, error);
+ ret = flow_err(port_id, ret, error);
+ rte_flow_trace_action_list_handle_query_update(port_id, handle, update,
+ query, mode, ret);
+ return ret;
+}
+
+int
+rte_flow_async_action_list_handle_query_update
+ (uint16_t port_id, uint32_t queue_id,
+ const struct rte_flow_op_attr *attr,
+ const struct rte_flow_action_list_handle *handle,
+ const void **update, void **query,
+ enum rte_flow_query_update_mode mode,
+ void *user_data, struct rte_flow_error *error)
+{
+ int ret;
+ struct rte_eth_dev *dev;
+ const struct rte_flow_ops *ops;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ ops = rte_flow_ops_get(port_id, error);
+ if (!ops || !ops->async_action_list_handle_query_update)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "action_list async query_update not supported");
+ dev = &rte_eth_devices[port_id];
+ ret = ops->async_action_list_handle_query_update(dev, queue_id, attr,
+ handle, update, query,
+ mode, user_data,
+ error);
+ ret = flow_err(port_id, ret, error);
+ rte_flow_trace_async_action_list_handle_query_update(port_id, queue_id,
+ attr, handle,
+ update, query,
+ mode, user_data,
+ ret);
+ return ret;
+}
@@ -2912,6 +2912,13 @@ enum rte_flow_action_type {
* applied to the given ethdev Rx queue.
*/
RTE_FLOW_ACTION_TYPE_SKIP_CMAN,
+
+ /**
+ * Action handle to reference flow actions list.
+ *
+ * @see struct rte_flow_action_indirect_list
+ */
+ RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
};
/**
@@ -6118,6 +6125,268 @@ rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,
void *user_data,
struct rte_flow_error *error);
+struct rte_flow_action_list_handle;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Configure INDIRECT_LIST flow action.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ */
+struct rte_flow_action_indirect_list {
+ /** Indirect action list handle */
+ struct rte_flow_action_list_handle *handle;
+ /**
+ * Flow mutable configuration array.
+ * NULL if the handle has no flow mutable configuration update.
+ * Otherwise, if the handle was created with list A1 / A2 .. An / END
+ * size of conf is n.
+ * conf[i] points to flow mutable update of Ai in the handle
+ * actions list or NULL if Ai has no update.
+ */
+ const void **conf;
+};
+
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create an indirect flow action object from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ * The port identifier of the Ethernet device.
+ * @param[in] conf
+ * Action configuration for the indirect action list creation.
+ * @param[in] actions
+ * Specific configuration of the indirect action lists.
+ * @param[out] error
+ * Perform verbose error reporting if not NULL. PMDs initialize this
+ * structure in case of error only.
+ * @return
+ * A valid handle in case of success, NULL otherwise and rte_errno is set
+ * to one of the error codes defined:
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOSYS) if underlying device does not support this functionality.
+ * - (-EIO) if underlying device is removed.
+ * - (-EINVAL) if *actions* list invalid.
+ * - (-ENOTSUP) if *action* list element valid but unsupported.
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+ const
+ struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Async function call to create an indirect flow action object
+ * from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ * The port identifier of the Ethernet device.
+ * @param[in] queue_id
+ * Flow queue which is used to update the rule.
+ * @param[in] attr
+ * Indirect action update operation attributes.
+ * @param[in] conf
+ * Action configuration for the indirect action list creation.
+ * @param[in] actions
+ * Specific configuration of the indirect action list.
+ * @param[in] user_data
+ * The user data that will be returned on async completion event.
+ * @param[out] error
+ * Perform verbose error reporting if not NULL. PMDs initialize this
+ * structure in case of error only.
+ * @return
+ * A valid handle in case of success, NULL otherwise and rte_errno is set
+ * to one of the error codes defined:
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOSYS) if underlying device does not support this functionality.
+ * - (-EIO) if underlying device is removed.
+ * - (-EINVAL) if *actions* list invalid.
+ * - (-ENOTSUP) if *action* list element valid but unsupported.
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t queue_id,
+ const struct rte_flow_op_attr *attr,
+ const struct
+ rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *actions,
+ void *user_data,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy indirect actions list by handle.
+ *
+ * @param[in] port_id
+ * The port identifier of the Ethernet device.
+ * @param[in] handle
+ * Handle for the indirect actions list to be destroyed.
+ * @param[out] error
+ * Perform verbose error reporting if not NULL. PMDs initialize this
+ * structure in case of error only.
+ * @return
+ * - (0) if success.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOSYS) if underlying device does not support this functionality.
+ * - (-EIO) if underlying device is removed.
+ * - (-ENOENT) if actions list pointed by *action* handle was not found.
+ * - (-EBUSY) if actions list pointed by *action* handle still used
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+ struct rte_flow_action_list_handle *handle,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action list destruction operation.
+ * The destroy queue must be the same
+ * as the queue on which the action was created.
+ *
+ * @param[in] port_id
+ * Port identifier of Ethernet device.
+ * @param[in] queue_id
+ * Flow queue which is used to destroy the rule.
+ * @param[in] op_attr
+ * Indirect action destruction operation attributes.
+ * @param[in] handle
+ * Handle for the indirect action object to be destroyed.
+ * @param[in] user_data
+ * The user data that will be returned on the completion events.
+ * @param[out] error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * - (0) if success.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOSYS) if underlying device does not support this functionality.
+ * - (-EIO) if underlying device is removed.
+ * - (-ENOENT) if actions list pointed by *action* handle was not found.
+ * - (-EBUSY) if actions list pointed by *action* handle still used
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_destroy
+ (uint16_t port_id, uint32_t queue_id,
+ const struct rte_flow_op_attr *op_attr,
+ struct rte_flow_action_list_handle *handle,
+ void *user_data, struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query and/or update indirect flow actions list.
+ * If both query and update not NULL, the function atomically
+ * queries and updates indirect action. Query and update are carried in order
+ * specified in the mode parameter.
+ * If ether query or update is NULL, the function executes
+ * complementing operation.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param handle
+ * Handle for the indirect actions list object to be updated.
+ * @param update
+ * If not NULL, update profile specification used to modify the action
+ * pointed by handle.
+ * @see struct rte_flow_action_indirect_list
+ * @param query
+ * If not NULL pointer to storage for the associated query data type.
+ * @see struct rte_flow_action_indirect_list
+ * @param mode
+ * Operational mode.
+ * @param error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * - (0) if success.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ * both *query* and *update* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_query_update(uint16_t port_id,
+ const struct
+ rte_flow_action_list_handle *handle,
+ const void **update, void **query,
+ enum rte_flow_query_update_mode mode,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue async indirect flow actions list query and/or update
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param queue_id
+ * Flow queue which is used to update the rule.
+ * @param attr
+ * Indirect action update operation attributes.
+ * @param handle
+ * Handle for the indirect actions list object to be updated.
+ * @param update
+ * If not NULL, update profile specification used to modify the action
+ * pointed by handle.
+ * @see struct rte_flow_action_indirect_list
+ * @param query
+ * If not NULL, pointer to storage for the associated query data type.
+ * Query result returned on async completion event.
+ * @see struct rte_flow_action_indirect_list
+ * @param mode
+ * Operational mode.
+ * @param user_data
+ * The user data that will be returned on async completion event.
+ * @param error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * - (0) if success.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ * both *update* and *query* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_query_update(uint16_t port_id, uint32_t queue_id,
+ const struct rte_flow_op_attr *attr,
+ const struct
+ rte_flow_action_list_handle *handle,
+ const void **update, void **query,
+ enum rte_flow_query_update_mode mode,
+ void *user_data,
+ struct rte_flow_error *error);
+
+
#ifdef __cplusplus
}
#endif
@@ -121,6 +121,17 @@ struct rte_flow_ops {
const void *update, void *query,
enum rte_flow_query_update_mode qu_mode,
struct rte_flow_error *error);
+ /** @see rte_flow_action_list_handle_create() */
+ struct rte_flow_action_list_handle *(*action_list_handle_create)
+ (struct rte_eth_dev *dev,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error);
+ /** @see rte_flow_action_list_handle_destroy() */
+ int (*action_list_handle_destroy)
+ (struct rte_eth_dev *dev,
+ struct rte_flow_action_list_handle *handle,
+ struct rte_flow_error *error);
/** See rte_flow_tunnel_decap_set() */
int (*tunnel_decap_set)
(struct rte_eth_dev *dev,
@@ -302,6 +313,36 @@ struct rte_flow_ops {
const void *update, void *query,
enum rte_flow_query_update_mode qu_mode,
void *user_data, struct rte_flow_error *error);
+ /** @see rte_flow_async_action_list_handle_create() */
+ struct rte_flow_action_list_handle *
+ (*async_action_list_handle_create)
+ (struct rte_eth_dev *dev, uint32_t queue_id,
+ const struct rte_flow_op_attr *attr,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *actions,
+ void *user_data, struct rte_flow_error *error);
+ /** @see rte_flow_async_action_list_handle_destroy() */
+ int (*async_action_list_handle_destroy)
+ (struct rte_eth_dev *dev, uint32_t queue_id,
+ const struct rte_flow_op_attr *op_attr,
+ struct rte_flow_action_list_handle *action_handle,
+ void *user_data, struct rte_flow_error *error);
+ /** @see rte_flow_action_list_handle_query_update() */
+ int (*action_list_handle_query_update)
+ (struct rte_eth_dev *dev,
+ const struct rte_flow_action_list_handle *handle,
+ const void **update, void **query,
+ enum rte_flow_query_update_mode mode,
+ struct rte_flow_error *error);
+ /** @see rte_flow_async_action_list_handle_query_update() */
+ int (*async_action_list_handle_query_update)
+ (struct rte_eth_dev *dev, uint32_t queue_id,
+ const struct rte_flow_op_attr *attr,
+ const struct rte_flow_action_list_handle *handle,
+ const void **update, void **query,
+ enum rte_flow_query_update_mode mode,
+ void *user_data, struct rte_flow_error *error);
+
};
/**
@@ -299,6 +299,14 @@ EXPERIMENTAL {
rte_flow_action_handle_query_update;
rte_flow_async_action_handle_query_update;
rte_flow_async_create_by_index;
+
+ # added in 23.07
+ rte_flow_action_list_handle_create;
+ rte_flow_action_list_handle_destroy;
+ rte_flow_action_list_handle_query_update;
+ rte_flow_async_action_list_handle_create;
+ rte_flow_async_action_list_handle_destroy;
+ rte_flow_async_action_list_handle_query_update;
};
INTERNAL {