@@ -86,6 +86,7 @@ enum index {
PATTERN_TEMPLATE,
ACTIONS_TEMPLATE,
TABLE,
+ FLOW_GROUP,
INDIRECT_ACTION,
VALIDATE,
CREATE,
@@ -206,6 +207,13 @@ enum index {
TABLE_PATTERN_TEMPLATE,
TABLE_ACTIONS_TEMPLATE,
+ /* Group arguments */
+ GROUP_ID,
+ GROUP_INGRESS,
+ GROUP_EGRESS,
+ GROUP_TRANSFER,
+ GROUP_SET_MISS_ACTIONS,
+
/* Tunnel arguments. */
TUNNEL_CREATE,
TUNNEL_CREATE_TYPE,
@@ -1293,6 +1301,14 @@ static const enum index next_at_destroy_attr[] = {
ZERO,
};
+static const enum index next_group_attr[] = {
+ GROUP_INGRESS,
+ GROUP_EGRESS,
+ GROUP_TRANSFER,
+ GROUP_SET_MISS_ACTIONS,
+ ZERO,
+};
+
static const enum index next_table_subcmd[] = {
TABLE_CREATE,
TABLE_DESTROY,
@@ -2678,6 +2694,9 @@ static int parse_push(struct context *, const struct token *,
static int parse_pull(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
+static int parse_group(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);
@@ -3021,6 +3040,7 @@ static const struct token token_list[] = {
PATTERN_TEMPLATE,
ACTIONS_TEMPLATE,
TABLE,
+ FLOW_GROUP,
INDIRECT_ACTION,
VALIDATE,
CREATE,
@@ -3411,6 +3431,46 @@ static const struct token token_list[] = {
.call = parse_table,
},
/* Top-level command. */
+ [FLOW_GROUP] = {
+ .name = "group",
+ .help = "manage flow groups",
+ .next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_group,
+ },
+ /* Sub-level commands. */
+ [GROUP_SET_MISS_ACTIONS] = {
+ .name = "set_miss_actions",
+ .help = "set group miss actions",
+ .next = NEXT(next_action),
+ .call = parse_group,
+ },
+ /* Group arguments */
+ [GROUP_ID] = {
+ .name = "group_id",
+ .help = "group id",
+ .next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+ },
+ [GROUP_INGRESS] = {
+ .name = "ingress",
+ .help = "group ingress attr",
+ .next = NEXT(next_group_attr),
+ .call = parse_group,
+ },
+ [GROUP_EGRESS] = {
+ .name = "egress",
+ .help = "group egress attr",
+ .next = NEXT(next_group_attr),
+ .call = parse_group,
+ },
+ [GROUP_TRANSFER] = {
+ .name = "transfer",
+ .help = "group transfer attr",
+ .next = NEXT(next_group_attr),
+ .call = parse_group,
+ },
+ /* Top-level command. */
[QUEUE] = {
.name = "queue",
.help = "queue a flow rule operation",
@@ -10449,6 +10509,54 @@ parse_pull(struct context *ctx, const struct token *token,
return len;
}
+static int
+parse_group(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 != FLOW_GROUP)
+ 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;
+ }
+ switch (ctx->curr) {
+ case GROUP_INGRESS:
+ out->args.vc.attr.ingress = 1;
+ return len;
+ case GROUP_EGRESS:
+ out->args.vc.attr.egress = 1;
+ return len;
+ case GROUP_TRANSFER:
+ out->args.vc.attr.transfer = 1;
+ return len;
+ case GROUP_SET_MISS_ACTIONS:
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ default:
+ return -1;
+ }
+}
+
static int
parse_flex(struct context *ctx, const struct token *token,
const char *str, unsigned int len,
@@ -12329,6 +12437,10 @@ cmd_flow_parsed(const struct buffer *in)
in->args.table_destroy.table_id_n,
in->args.table_destroy.table_id);
break;
+ case GROUP_SET_MISS_ACTIONS:
+ port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
+ in->args.vc.actions);
+ break;
case QUEUE_CREATE:
port_queue_flow_create(in->port, in->queue, in->postpone,
in->args.vc.table_id, in->args.vc.rule_id,
@@ -3514,6 +3514,33 @@ port_queue_flow_pull(portid_t port_id, queueid_t queue_id)
return ret;
}
+/* Set group miss actions */
+int
+port_queue_group_set_miss_actions(portid_t port_id, const struct rte_flow_attr *attr,
+ const struct rte_flow_action *actions)
+{
+ struct rte_flow_group_attr gattr = {
+ .ingress = attr->ingress,
+ .egress = attr->egress,
+ .transfer = attr->transfer,
+ };
+ struct rte_flow_error error;
+ int ret = 0;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return -EINVAL;
+
+ memset(&error, 0x66, sizeof(error));
+ ret = rte_flow_group_set_miss_actions(port_id, attr->group, &gattr, actions, &error);
+
+ if (ret < 0)
+ return port_flow_complain(&error);
+
+ printf("Group #%u set miss actions succeeded\n", attr->group);
+ return ret;
+}
+
/** Create flow rule. */
int
port_flow_create(portid_t port_id,
@@ -979,6 +979,8 @@ int port_flow_template_table_create(portid_t port_id, uint32_t id,
int port_flow_template_table_destroy(portid_t port_id,
uint32_t n, const uint32_t *table);
int port_flow_template_table_flush(portid_t port_id);
+int port_queue_group_set_miss_actions(portid_t port_id, const struct rte_flow_attr *attr,
+ const struct rte_flow_action *actions);
int port_queue_flow_create(portid_t port_id, queueid_t queue_id,
bool postpone, uint32_t table_id, uint32_t rule_idx,
uint32_t pattern_idx, uint32_t actions_idx,