TUNNEL,
FLEX,
QUEUE,
+ PUSH,
+ PULL,
/* Flex arguments */
FLEX_ITEM_INIT,
/* Queue arguments. */
QUEUE_CREATE,
QUEUE_DESTROY,
+ QUEUE_INDIRECT_ACTION,
/* Queue create arguments. */
QUEUE_CREATE_ID,
QUEUE_DESTROY_ID,
QUEUE_DESTROY_POSTPONE,
+ /* Queue indirect action arguments */
+ QUEUE_INDIRECT_ACTION_CREATE,
+ QUEUE_INDIRECT_ACTION_UPDATE,
+ QUEUE_INDIRECT_ACTION_DESTROY,
+
+ /* Queue indirect action create arguments */
+ QUEUE_INDIRECT_ACTION_CREATE_ID,
+ QUEUE_INDIRECT_ACTION_INGRESS,
+ QUEUE_INDIRECT_ACTION_EGRESS,
+ QUEUE_INDIRECT_ACTION_TRANSFER,
+ QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
+ QUEUE_INDIRECT_ACTION_SPEC,
+
+ /* Queue indirect action update arguments */
+ QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
+
+ /* Queue indirect action destroy arguments */
+ QUEUE_INDIRECT_ACTION_DESTROY_ID,
+ QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
+
+ /* Push arguments. */
+ PUSH_QUEUE,
+
+ /* Pull arguments. */
+ PULL_QUEUE,
+
/* Table arguments. */
TABLE_CREATE,
TABLE_DESTROY,
static const enum index next_queue_subcmd[] = {
QUEUE_CREATE,
QUEUE_DESTROY,
+ QUEUE_INDIRECT_ACTION,
ZERO,
};
ZERO,
};
+static const enum index next_qia_subcmd[] = {
+ QUEUE_INDIRECT_ACTION_CREATE,
+ QUEUE_INDIRECT_ACTION_UPDATE,
+ QUEUE_INDIRECT_ACTION_DESTROY,
+ ZERO,
+};
+
+static const enum index next_qia_create_attr[] = {
+ QUEUE_INDIRECT_ACTION_CREATE_ID,
+ QUEUE_INDIRECT_ACTION_INGRESS,
+ QUEUE_INDIRECT_ACTION_EGRESS,
+ QUEUE_INDIRECT_ACTION_TRANSFER,
+ QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
+ QUEUE_INDIRECT_ACTION_SPEC,
+ ZERO,
+};
+
+static const enum index next_qia_update_attr[] = {
+ QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
+ QUEUE_INDIRECT_ACTION_SPEC,
+ ZERO,
+};
+
+static const enum index next_qia_destroy_attr[] = {
+ QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
+ QUEUE_INDIRECT_ACTION_DESTROY_ID,
+ END,
+ ZERO,
+};
+
static const enum index next_ia_create_attr[] = {
INDIRECT_ACTION_CREATE_ID,
INDIRECT_ACTION_INGRESS,
static int parse_qo_destroy(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
+static int parse_qia(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_qia_destroy(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_push(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_pull(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
static int parse_tunnel(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
ISOLATE,
TUNNEL,
FLEX,
- QUEUE)),
+ QUEUE,
+ PUSH,
+ PULL)),
.call = parse_init,
},
/* Top-level command. */
.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
.call = parse_qo_destroy,
},
+ [QUEUE_INDIRECT_ACTION] = {
+ .name = "indirect_action",
+ .help = "queue indirect actions",
+ .next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
+ .call = parse_qia,
+ },
/* Queue arguments. */
[QUEUE_TEMPLATE_TABLE] = {
.name = "template table",
args.destroy.rule)),
.call = parse_qo_destroy,
},
+ /* Queue indirect action arguments */
+ [QUEUE_INDIRECT_ACTION_CREATE] = {
+ .name = "create",
+ .help = "create indirect action",
+ .next = NEXT(next_qia_create_attr),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_UPDATE] = {
+ .name = "update",
+ .help = "update indirect action",
+ .next = NEXT(next_qia_update_attr,
+ NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_DESTROY] = {
+ .name = "destroy",
+ .help = "destroy indirect action",
+ .next = NEXT(next_qia_destroy_attr),
+ .call = parse_qia_destroy,
+ },
+ /* Indirect action destroy arguments. */
+ [QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
+ .name = "postpone",
+ .help = "postpone destroy operation",
+ .next = NEXT(next_qia_destroy_attr,
+ NEXT_ENTRY(COMMON_BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
+ },
+ [QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
+ .name = "action_id",
+ .help = "specify a indirect action id to destroy",
+ .next = NEXT(next_qia_destroy_attr,
+ NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
+ args.ia_destroy.action_id)),
+ .call = parse_qia_destroy,
+ },
+ /* Indirect action update arguments. */
+ [QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
+ .name = "postpone",
+ .help = "postpone update operation",
+ .next = NEXT(next_qia_update_attr,
+ NEXT_ENTRY(COMMON_BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
+ },
+ /* Indirect action create arguments. */
+ [QUEUE_INDIRECT_ACTION_CREATE_ID] = {
+ .name = "action_id",
+ .help = "specify a indirect action id to create",
+ .next = NEXT(next_qia_create_attr,
+ NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+ },
+ [QUEUE_INDIRECT_ACTION_INGRESS] = {
+ .name = "ingress",
+ .help = "affect rule to ingress",
+ .next = NEXT(next_qia_create_attr),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_EGRESS] = {
+ .name = "egress",
+ .help = "affect rule to egress",
+ .next = NEXT(next_qia_create_attr),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_TRANSFER] = {
+ .name = "transfer",
+ .help = "affect rule to transfer",
+ .next = NEXT(next_qia_create_attr),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
+ .name = "postpone",
+ .help = "postpone create operation",
+ .next = NEXT(next_qia_create_attr,
+ NEXT_ENTRY(COMMON_BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
+ },
+ [QUEUE_INDIRECT_ACTION_SPEC] = {
+ .name = "action",
+ .help = "specify action to create indirect handle",
+ .next = NEXT(next_action),
+ },
+ /* Top-level command. */
+ [PUSH] = {
+ .name = "push",
+ .help = "push enqueued operations",
+ .next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_push,
+ },
+ /* Sub-level commands. */
+ [PUSH_QUEUE] = {
+ .name = "queue",
+ .help = "specify queue id",
+ .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
+ },
+ /* Top-level command. */
+ [PULL] = {
+ .name = "pull",
+ .help = "pull flow operations results",
+ .next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_pull,
+ },
+ /* Sub-level commands. */
+ [PULL_QUEUE] = {
+ .name = "queue",
+ .help = "specify queue id",
+ .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
+ },
/* Top-level command. */
[INDIRECT_ACTION] = {
.name = "indirect_action",
return len;
}
+/** Parse tokens for indirect action commands. */
+static int
+parse_qia(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != QUEUE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->args.vc.data = (uint8_t *)out + size;
+ return len;
+ }
+ switch (ctx->curr) {
+ case QUEUE_INDIRECT_ACTION:
+ return len;
+ case QUEUE_INDIRECT_ACTION_CREATE:
+ case QUEUE_INDIRECT_ACTION_UPDATE:
+ out->args.vc.actions =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ out->args.vc.attr.group = UINT32_MAX;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ case QUEUE_INDIRECT_ACTION_EGRESS:
+ out->args.vc.attr.egress = 1;
+ return len;
+ case QUEUE_INDIRECT_ACTION_INGRESS:
+ out->args.vc.attr.ingress = 1;
+ return len;
+ case QUEUE_INDIRECT_ACTION_TRANSFER:
+ out->args.vc.attr.transfer = 1;
+ return len;
+ case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
+ return len;
+ default:
+ return -1;
+ }
+}
+
+/** Parse tokens for indirect action destroy command. */
+static int
+parse_qia_destroy(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ uint32_t *action_id;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command || out->command == QUEUE) {
+ if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.ia_destroy.action_id =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ switch (ctx->curr) {
+ case QUEUE_INDIRECT_ACTION:
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ case QUEUE_INDIRECT_ACTION_DESTROY_ID:
+ action_id = out->args.ia_destroy.action_id
+ + out->args.ia_destroy.action_id_n++;
+ if ((uint8_t *)action_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = action_id;
+ ctx->objmask = NULL;
+ return len;
+ case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
+ return len;
+ default:
+ return -1;
+ }
+}
+
/** Parse tokens for meter policy action commands. */
static int
parse_mp(struct context *ctx, const struct token *token,
}
}
+/** Parse tokens for push queue command. */
+static int
+parse_push(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != PUSH)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.vc.data = (uint8_t *)out + size;
+ }
+ return len;
+}
+
+/** Parse tokens for pull command. */
+static int
+parse_pull(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != PULL)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.vc.data = (uint8_t *)out + size;
+ }
+ return len;
+}
+
static int
parse_flex(struct context *ctx, const struct token *token,
const char *str, unsigned int len,
in->args.destroy.rule_n,
in->args.destroy.rule);
break;
+ case PUSH:
+ port_queue_flow_push(in->port, in->queue);
+ break;
+ case PULL:
+ port_queue_flow_pull(in->port, in->queue);
+ break;
+ case QUEUE_INDIRECT_ACTION_CREATE:
+ port_queue_action_handle_create(
+ in->port, in->queue, in->postpone,
+ in->args.vc.attr.group,
+ &((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 QUEUE_INDIRECT_ACTION_DESTROY:
+ port_queue_action_handle_destroy(in->port,
+ in->queue, in->postpone,
+ in->args.ia_destroy.action_id_n,
+ in->args.ia_destroy.action_id);
+ break;
+ case QUEUE_INDIRECT_ACTION_UPDATE:
+ port_queue_action_handle_update(in->port,
+ in->queue, in->postpone,
+ in->args.vc.attr.group,
+ in->args.vc.actions);
+ break;
case INDIRECT_ACTION_CREATE:
port_action_handle_create(
in->port, in->args.vc.attr.group,