COMMON_POLICY_ID,
COMMON_FLEX_HANDLE,
COMMON_FLEX_TOKEN,
+ COMMON_PATTERN_TEMPLATE_ID,
+ COMMON_ACTIONS_TEMPLATE_ID,
+ COMMON_TABLE_ID,
+ COMMON_QUEUE_ID,
/* TOP-level command. */
ADD,
/* Top-level command. */
FLOW,
/* Sub-level commands. */
+ INFO,
+ CONFIGURE,
+ PATTERN_TEMPLATE,
+ ACTIONS_TEMPLATE,
+ TABLE,
INDIRECT_ACTION,
VALIDATE,
CREATE,
ISOLATE,
TUNNEL,
FLEX,
+ QUEUE,
+ PUSH,
+ PULL,
/* Flex arguments */
FLEX_ITEM_INIT,
FLEX_ITEM_CREATE,
FLEX_ITEM_DESTROY,
+ /* Pattern template arguments. */
+ PATTERN_TEMPLATE_CREATE,
+ PATTERN_TEMPLATE_DESTROY,
+ PATTERN_TEMPLATE_CREATE_ID,
+ PATTERN_TEMPLATE_DESTROY_ID,
+ PATTERN_TEMPLATE_RELAXED_MATCHING,
+ PATTERN_TEMPLATE_INGRESS,
+ PATTERN_TEMPLATE_EGRESS,
+ PATTERN_TEMPLATE_TRANSFER,
+ PATTERN_TEMPLATE_SPEC,
+
+ /* Actions template arguments. */
+ ACTIONS_TEMPLATE_CREATE,
+ ACTIONS_TEMPLATE_DESTROY,
+ ACTIONS_TEMPLATE_CREATE_ID,
+ ACTIONS_TEMPLATE_DESTROY_ID,
+ ACTIONS_TEMPLATE_INGRESS,
+ ACTIONS_TEMPLATE_EGRESS,
+ ACTIONS_TEMPLATE_TRANSFER,
+ ACTIONS_TEMPLATE_SPEC,
+ ACTIONS_TEMPLATE_MASK,
+
+ /* Queue arguments. */
+ QUEUE_CREATE,
+ QUEUE_DESTROY,
+ QUEUE_INDIRECT_ACTION,
+
+ /* Queue create arguments. */
+ QUEUE_CREATE_ID,
+ QUEUE_CREATE_POSTPONE,
+ QUEUE_TEMPLATE_TABLE,
+ QUEUE_PATTERN_TEMPLATE,
+ QUEUE_ACTIONS_TEMPLATE,
+ QUEUE_SPEC,
+
+ /* Queue destroy arguments. */
+ 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,
+ TABLE_CREATE_ID,
+ TABLE_DESTROY_ID,
+ TABLE_GROUP,
+ TABLE_PRIORITY,
+ TABLE_INGRESS,
+ TABLE_EGRESS,
+ TABLE_TRANSFER,
+ TABLE_RULES_NUMBER,
+ TABLE_PATTERN_TEMPLATE,
+ TABLE_ACTIONS_TEMPLATE,
+
/* Tunnel arguments. */
TUNNEL_CREATE,
TUNNEL_CREATE_TYPE,
DUMP_ALL,
DUMP_ONE,
+ /* Configure arguments */
+ CONFIG_QUEUES_NUMBER,
+ CONFIG_QUEUES_SIZE,
+ CONFIG_COUNTERS_NUMBER,
+ CONFIG_AGING_OBJECTS_NUMBER,
+ CONFIG_METERS_NUMBER,
+
/* Indirect action arguments */
INDIRECT_ACTION_CREATE,
INDIRECT_ACTION_UPDATE,
ITEM_RAW_OFFSET,
ITEM_RAW_LIMIT,
ITEM_RAW_PATTERN,
+ ITEM_RAW_PATTERN_HEX,
ITEM_ETH,
ITEM_ETH_DST,
ITEM_ETH_SRC,
ITEM_META_DATA,
ITEM_GRE_KEY,
ITEM_GRE_KEY_VALUE,
+ ITEM_GRE_OPTION,
+ ITEM_GRE_OPTION_CHECKSUM,
+ ITEM_GRE_OPTION_KEY,
+ ITEM_GRE_OPTION_SEQUENCE,
ITEM_GTP_PSC,
ITEM_GTP_PSC_QFI,
ITEM_GTP_PSC_PDU_T,
ITEM_FLEX_ITEM_HANDLE,
ITEM_FLEX_PATTERN_HANDLE,
ITEM_L2TPV2,
- ITEM_L2TPV2_COMMON,
- ITEM_L2TPV2_COMMON_TYPE,
- ITEM_L2TPV2_COMMON_TYPE_DATA_L,
- ITEM_L2TPV2_COMMON_TYPE_CTRL,
+ ITEM_L2TPV2_TYPE,
+ ITEM_L2TPV2_TYPE_DATA,
+ ITEM_L2TPV2_TYPE_DATA_L,
+ ITEM_L2TPV2_TYPE_DATA_S,
+ ITEM_L2TPV2_TYPE_DATA_O,
+ ITEM_L2TPV2_TYPE_DATA_L_S,
+ ITEM_L2TPV2_TYPE_CTRL,
+ ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_DATA_SESSION_ID,
ITEM_L2TPV2_MSG_DATA_L_LENGTH,
ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
+ ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
+ ITEM_L2TPV2_MSG_DATA_S_NS,
+ ITEM_L2TPV2_MSG_DATA_S_NR,
+ ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
+ ITEM_L2TPV2_MSG_DATA_O_OFFSET,
+ ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
+ ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
+ ITEM_L2TPV2_MSG_DATA_L_S_NS,
+ ITEM_L2TPV2_MSG_DATA_L_S_NR,
ITEM_L2TPV2_MSG_CTRL_LENGTH,
ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
};
/** Maximum size for pattern in struct rte_flow_item_raw. */
-#define ITEM_RAW_PATTERN_SIZE 40
+#define ITEM_RAW_PATTERN_SIZE 512
/** Maximum size for GENEVE option data pattern in bytes. */
#define ITEM_GENEVE_OPT_DATA_SIZE 124
struct buffer {
enum index command; /**< Flow command. */
portid_t port; /**< Affected port ID. */
+ queueid_t queue; /** Async queue ID. */
+ bool postpone; /** Postpone async operation */
union {
+ struct {
+ struct rte_flow_port_attr port_attr;
+ uint32_t nb_queue;
+ struct rte_flow_queue_attr queue_attr;
+ } configure; /**< Configuration arguments. */
+ struct {
+ uint32_t *template_id;
+ uint32_t template_id_n;
+ } templ_destroy; /**< Template destroy arguments. */
+ struct {
+ uint32_t id;
+ struct rte_flow_template_table_attr attr;
+ uint32_t *pat_templ_id;
+ uint32_t pat_templ_id_n;
+ uint32_t *act_templ_id;
+ uint32_t act_templ_id_n;
+ } table; /**< Table arguments. */
+ struct {
+ uint32_t *table_id;
+ uint32_t table_id_n;
+ } table_destroy; /**< Template destroy arguments. */
struct {
uint32_t *action_id;
uint32_t action_id_n;
uint32_t action_id;
} ia; /* Indirect action query arguments */
struct {
+ uint32_t table_id;
+ uint32_t pat_templ_id;
+ uint32_t act_templ_id;
struct rte_flow_attr attr;
struct tunnel_ops tunnel_ops;
struct rte_flow_item *pattern;
struct rte_flow_action *actions;
+ struct rte_flow_action *masks;
uint32_t pattern_n;
uint32_t actions_n;
uint8_t *data;
ZERO,
};
+static const enum index next_config_attr[] = {
+ CONFIG_QUEUES_NUMBER,
+ CONFIG_QUEUES_SIZE,
+ CONFIG_COUNTERS_NUMBER,
+ CONFIG_AGING_OBJECTS_NUMBER,
+ CONFIG_METERS_NUMBER,
+ END,
+ ZERO,
+};
+
+static const enum index next_pt_subcmd[] = {
+ PATTERN_TEMPLATE_CREATE,
+ PATTERN_TEMPLATE_DESTROY,
+ ZERO,
+};
+
+static const enum index next_pt_attr[] = {
+ PATTERN_TEMPLATE_CREATE_ID,
+ PATTERN_TEMPLATE_RELAXED_MATCHING,
+ PATTERN_TEMPLATE_INGRESS,
+ PATTERN_TEMPLATE_EGRESS,
+ PATTERN_TEMPLATE_TRANSFER,
+ PATTERN_TEMPLATE_SPEC,
+ ZERO,
+};
+
+static const enum index next_pt_destroy_attr[] = {
+ PATTERN_TEMPLATE_DESTROY_ID,
+ END,
+ ZERO,
+};
+
+static const enum index next_at_subcmd[] = {
+ ACTIONS_TEMPLATE_CREATE,
+ ACTIONS_TEMPLATE_DESTROY,
+ ZERO,
+};
+
+static const enum index next_at_attr[] = {
+ ACTIONS_TEMPLATE_CREATE_ID,
+ ACTIONS_TEMPLATE_INGRESS,
+ ACTIONS_TEMPLATE_EGRESS,
+ ACTIONS_TEMPLATE_TRANSFER,
+ ACTIONS_TEMPLATE_SPEC,
+ ZERO,
+};
+
+static const enum index next_at_destroy_attr[] = {
+ ACTIONS_TEMPLATE_DESTROY_ID,
+ END,
+ ZERO,
+};
+
+static const enum index next_table_subcmd[] = {
+ TABLE_CREATE,
+ TABLE_DESTROY,
+ ZERO,
+};
+
+static const enum index next_table_attr[] = {
+ TABLE_CREATE_ID,
+ TABLE_GROUP,
+ TABLE_PRIORITY,
+ TABLE_INGRESS,
+ TABLE_EGRESS,
+ TABLE_TRANSFER,
+ TABLE_RULES_NUMBER,
+ TABLE_PATTERN_TEMPLATE,
+ TABLE_ACTIONS_TEMPLATE,
+ END,
+ ZERO,
+};
+
+static const enum index next_table_destroy_attr[] = {
+ TABLE_DESTROY_ID,
+ END,
+ ZERO,
+};
+
+static const enum index next_queue_subcmd[] = {
+ QUEUE_CREATE,
+ QUEUE_DESTROY,
+ QUEUE_INDIRECT_ACTION,
+ ZERO,
+};
+
+static const enum index next_queue_destroy_attr[] = {
+ QUEUE_DESTROY_ID,
+ END,
+ 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,
ITEM_ICMP6_ND_OPT_TLA_ETH,
ITEM_META,
ITEM_GRE_KEY,
+ ITEM_GRE_OPTION,
ITEM_GTP_PSC,
ITEM_PPPOES,
ITEM_PPPOED,
ITEM_RAW_OFFSET,
ITEM_RAW_LIMIT,
ITEM_RAW_PATTERN,
+ ITEM_RAW_PATTERN_HEX,
ITEM_NEXT,
ZERO,
};
ZERO,
};
+static const enum index item_gre_option[] = {
+ ITEM_GRE_OPTION_CHECKSUM,
+ ITEM_GRE_OPTION_KEY,
+ ITEM_GRE_OPTION_SEQUENCE,
+ ITEM_NEXT,
+ ZERO,
+};
+
static const enum index item_gtp[] = {
ITEM_GTP_FLAGS,
ITEM_GTP_MSG_TYPE,
};
static const enum index item_l2tpv2[] = {
- ITEM_L2TPV2_COMMON,
+ ITEM_L2TPV2_TYPE,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_l2tpv2_type[] = {
+ ITEM_L2TPV2_TYPE_DATA,
+ ITEM_L2TPV2_TYPE_DATA_L,
+ ITEM_L2TPV2_TYPE_DATA_S,
+ ITEM_L2TPV2_TYPE_DATA_O,
+ ITEM_L2TPV2_TYPE_DATA_L_S,
+ ITEM_L2TPV2_TYPE_CTRL,
+ ZERO,
+};
+
+static const enum index item_l2tpv2_type_data[] = {
+ ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_DATA_SESSION_ID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_l2tpv2_type_data_l[] = {
+ ITEM_L2TPV2_MSG_DATA_L_LENGTH,
+ ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_l2tpv2_type_data_s[] = {
+ ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
+ ITEM_L2TPV2_MSG_DATA_S_NS,
+ ITEM_L2TPV2_MSG_DATA_S_NR,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_l2tpv2_type_data_o[] = {
+ ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
+ ITEM_L2TPV2_MSG_DATA_O_OFFSET,
ITEM_NEXT,
ZERO,
};
-static const enum index item_l2tpv2_common[] = {
- ITEM_L2TPV2_COMMON_TYPE,
+static const enum index item_l2tpv2_type_data_l_s[] = {
+ ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
+ ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
+ ITEM_L2TPV2_MSG_DATA_L_S_NS,
+ ITEM_L2TPV2_MSG_DATA_L_S_NR,
+ ITEM_NEXT,
ZERO,
};
-static const enum index item_l2tpv2_common_type[] = {
- ITEM_L2TPV2_COMMON_TYPE_DATA_L,
- ITEM_L2TPV2_COMMON_TYPE_CTRL,
+static const enum index item_l2tpv2_type_ctrl[] = {
+ ITEM_L2TPV2_MSG_CTRL_LENGTH,
+ ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
+ ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
+ ITEM_L2TPV2_MSG_CTRL_NS,
+ ITEM_L2TPV2_MSG_CTRL_NR,
+ ITEM_NEXT,
ZERO,
};
static int parse_isolate(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
+static int parse_configure(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_template(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_template_destroy(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_table(struct context *, const struct token *,
+ const char *, unsigned int, void *, unsigned int);
+static int parse_table_destroy(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_qo(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+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);
unsigned int, char *, unsigned int);
static int comp_set_modify_field_id(struct context *, const struct token *,
unsigned int, char *, unsigned int);
+static int comp_pattern_template_id(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_actions_template_id(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_table_id(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_queue_id(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
/** Token definitions. */
static const struct token token_list[] = {
},
[COMMON_POLICY_ID] = {
.name = "{policy_id}",
- .type = "POLCIY_ID",
+ .type = "POLICY_ID",
.help = "policy id",
.call = parse_int,
.comp = comp_none,
.call = parse_flex_handle,
.comp = comp_none,
},
+ [COMMON_PATTERN_TEMPLATE_ID] = {
+ .name = "{pattern_template_id}",
+ .type = "PATTERN_TEMPLATE_ID",
+ .help = "pattern template id",
+ .call = parse_int,
+ .comp = comp_pattern_template_id,
+ },
+ [COMMON_ACTIONS_TEMPLATE_ID] = {
+ .name = "{actions_template_id}",
+ .type = "ACTIONS_TEMPLATE_ID",
+ .help = "actions template id",
+ .call = parse_int,
+ .comp = comp_actions_template_id,
+ },
+ [COMMON_TABLE_ID] = {
+ .name = "{table_id}",
+ .type = "TABLE_ID",
+ .help = "table id",
+ .call = parse_int,
+ .comp = comp_table_id,
+ },
+ [COMMON_QUEUE_ID] = {
+ .name = "{queue_id}",
+ .type = "QUEUE_ID",
+ .help = "queue id",
+ .call = parse_int,
+ .comp = comp_queue_id,
+ },
/* Top-level command. */
[FLOW] = {
.name = "flow",
.type = "{command} {port_id} [{arg} [...]]",
.help = "manage ingress/egress flow rules",
.next = NEXT(NEXT_ENTRY
- (INDIRECT_ACTION,
+ (INFO,
+ CONFIGURE,
+ PATTERN_TEMPLATE,
+ ACTIONS_TEMPLATE,
+ TABLE,
+ INDIRECT_ACTION,
VALIDATE,
CREATE,
DESTROY,
QUERY,
ISOLATE,
TUNNEL,
- FLEX)),
+ FLEX,
+ QUEUE,
+ PUSH,
+ PULL)),
.call = parse_init,
},
/* Top-level command. */
- [INDIRECT_ACTION] = {
- .name = "indirect_action",
+ [INFO] = {
+ .name = "info",
+ .help = "get information about flow engine",
+ .next = NEXT(NEXT_ENTRY(END),
+ NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_configure,
+ },
+ /* Top-level command. */
+ [CONFIGURE] = {
+ .name = "configure",
+ .help = "configure flow engine",
+ .next = NEXT(next_config_attr,
+ NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_configure,
+ },
+ /* Configure arguments. */
+ [CONFIG_QUEUES_NUMBER] = {
+ .name = "queues_number",
+ .help = "number of queues",
+ .next = NEXT(next_config_attr,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.configure.nb_queue)),
+ },
+ [CONFIG_QUEUES_SIZE] = {
+ .name = "queues_size",
+ .help = "number of elements in queues",
+ .next = NEXT(next_config_attr,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.configure.queue_attr.size)),
+ },
+ [CONFIG_COUNTERS_NUMBER] = {
+ .name = "counters_number",
+ .help = "number of counters",
+ .next = NEXT(next_config_attr,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.configure.port_attr.nb_counters)),
+ },
+ [CONFIG_AGING_OBJECTS_NUMBER] = {
+ .name = "aging_counters_number",
+ .help = "number of aging objects",
+ .next = NEXT(next_config_attr,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.configure.port_attr.nb_aging_objects)),
+ },
+ [CONFIG_METERS_NUMBER] = {
+ .name = "meters_number",
+ .help = "number of meters",
+ .next = NEXT(next_config_attr,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.configure.port_attr.nb_meters)),
+ },
+ /* Top-level command. */
+ [PATTERN_TEMPLATE] = {
+ .name = "pattern_template",
.type = "{command} {port_id} [{arg} [...]]",
- .help = "manage indirect actions",
- .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
+ .help = "manage pattern templates",
+ .next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
.args = ARGS(ARGS_ENTRY(struct buffer, port)),
- .call = parse_ia,
+ .call = parse_template,
},
/* Sub-level commands. */
- [INDIRECT_ACTION_CREATE] = {
+ [PATTERN_TEMPLATE_CREATE] = {
.name = "create",
- .help = "create indirect action",
- .next = NEXT(next_ia_create_attr),
- .call = parse_ia,
+ .help = "create pattern template",
+ .next = NEXT(next_pt_attr),
+ .call = parse_template,
},
- [INDIRECT_ACTION_UPDATE] = {
- .name = "update",
- .help = "update indirect action",
- .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
- NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
- .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
- .call = parse_ia,
- },
- [INDIRECT_ACTION_DESTROY] = {
+ [PATTERN_TEMPLATE_DESTROY] = {
.name = "destroy",
- .help = "destroy indirect action",
- .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
+ .help = "destroy pattern template",
+ .next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
.args = ARGS(ARGS_ENTRY(struct buffer, port)),
- .call = parse_ia_destroy,
+ .call = parse_template_destroy,
+ },
+ /* Pattern template arguments. */
+ [PATTERN_TEMPLATE_CREATE_ID] = {
+ .name = "pattern_template_id",
+ .help = "specify a pattern template id to create",
+ .next = NEXT(next_pt_attr,
+ NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
+ },
+ [PATTERN_TEMPLATE_DESTROY_ID] = {
+ .name = "pattern_template",
+ .help = "specify a pattern template id to destroy",
+ .next = NEXT(next_pt_destroy_attr,
+ NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
+ args.templ_destroy.template_id)),
+ .call = parse_template_destroy,
+ },
+ [PATTERN_TEMPLATE_RELAXED_MATCHING] = {
+ .name = "relaxed",
+ .help = "is matching relaxed",
+ .next = NEXT(next_pt_attr,
+ NEXT_ENTRY(COMMON_BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY_BF(struct buffer,
+ args.vc.attr.reserved, 1)),
+ },
+ [PATTERN_TEMPLATE_INGRESS] = {
+ .name = "ingress",
+ .help = "attribute pattern to ingress",
+ .next = NEXT(next_pt_attr),
+ .call = parse_template,
},
- [INDIRECT_ACTION_QUERY] = {
- .name = "query",
- .help = "query indirect action",
- .next = NEXT(NEXT_ENTRY(END),
- NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
- .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
- .call = parse_ia,
+ [PATTERN_TEMPLATE_EGRESS] = {
+ .name = "egress",
+ .help = "attribute pattern to egress",
+ .next = NEXT(next_pt_attr),
+ .call = parse_template,
},
- [VALIDATE] = {
- .name = "validate",
- .help = "check whether a flow rule can be created",
- .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
+ [PATTERN_TEMPLATE_TRANSFER] = {
+ .name = "transfer",
+ .help = "attribute pattern to transfer",
+ .next = NEXT(next_pt_attr),
+ .call = parse_template,
+ },
+ [PATTERN_TEMPLATE_SPEC] = {
+ .name = "template",
+ .help = "specify item to create pattern template",
+ .next = NEXT(next_item),
+ },
+ /* Top-level command. */
+ [ACTIONS_TEMPLATE] = {
+ .name = "actions_template",
+ .type = "{command} {port_id} [{arg} [...]]",
+ .help = "manage actions templates",
+ .next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
.args = ARGS(ARGS_ENTRY(struct buffer, port)),
- .call = parse_vc,
+ .call = parse_template,
},
- [CREATE] = {
+ /* Sub-level commands. */
+ [ACTIONS_TEMPLATE_CREATE] = {
.name = "create",
- .help = "create a flow rule",
- .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
- .args = ARGS(ARGS_ENTRY(struct buffer, port)),
- .call = parse_vc,
+ .help = "create actions template",
+ .next = NEXT(next_at_attr),
+ .call = parse_template,
},
- [DESTROY] = {
+ [ACTIONS_TEMPLATE_DESTROY] = {
.name = "destroy",
- .help = "destroy specific flow rules",
- .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
- NEXT_ENTRY(COMMON_PORT_ID)),
+ .help = "destroy actions template",
+ .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
.args = ARGS(ARGS_ENTRY(struct buffer, port)),
- .call = parse_destroy,
+ .call = parse_template_destroy,
+ },
+ /* Actions template arguments. */
+ [ACTIONS_TEMPLATE_CREATE_ID] = {
+ .name = "actions_template_id",
+ .help = "specify an actions template id to create",
+ .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
+ NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
+ NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
+ },
+ [ACTIONS_TEMPLATE_DESTROY_ID] = {
+ .name = "actions_template",
+ .help = "specify an actions template id to destroy",
+ .next = NEXT(next_at_destroy_attr,
+ NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
+ args.templ_destroy.template_id)),
+ .call = parse_template_destroy,
},
- [FLUSH] = {
- .name = "flush",
- .help = "destroy all flow rules",
- .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
- .args = ARGS(ARGS_ENTRY(struct buffer, port)),
- .call = parse_flush,
+ [ACTIONS_TEMPLATE_INGRESS] = {
+ .name = "ingress",
+ .help = "attribute actions to ingress",
+ .next = NEXT(next_at_attr),
+ .call = parse_template,
},
- [DUMP] = {
- .name = "dump",
- .help = "dump single/all flow rules to file",
- .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
- .args = ARGS(ARGS_ENTRY(struct buffer, port)),
- .call = parse_dump,
+ [ACTIONS_TEMPLATE_EGRESS] = {
+ .name = "egress",
+ .help = "attribute actions to egress",
+ .next = NEXT(next_at_attr),
+ .call = parse_template,
},
- [QUERY] = {
- .name = "query",
- .help = "query an existing flow rule",
- .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
- NEXT_ENTRY(COMMON_RULE_ID),
- NEXT_ENTRY(COMMON_PORT_ID)),
- .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
- ARGS_ENTRY(struct buffer, args.query.rule),
- ARGS_ENTRY(struct buffer, port)),
- .call = parse_query,
+ [ACTIONS_TEMPLATE_TRANSFER] = {
+ .name = "transfer",
+ .help = "attribute actions to transfer",
+ .next = NEXT(next_at_attr),
+ .call = parse_template,
},
- [LIST] = {
- .name = "list",
- .help = "list existing flow rules",
- .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
+ [ACTIONS_TEMPLATE_SPEC] = {
+ .name = "template",
+ .help = "specify action to create actions template",
+ .next = NEXT(next_action),
+ .call = parse_template,
+ },
+ [ACTIONS_TEMPLATE_MASK] = {
+ .name = "mask",
+ .help = "specify action mask to create actions template",
+ .next = NEXT(next_action),
+ .call = parse_template,
+ },
+ /* Top-level command. */
+ [TABLE] = {
+ .name = "template_table",
+ .type = "{command} {port_id} [{arg} [...]]",
+ .help = "manage template tables",
+ .next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
.args = ARGS(ARGS_ENTRY(struct buffer, port)),
- .call = parse_list,
+ .call = parse_table,
},
- [AGED] = {
- .name = "aged",
- .help = "list and destroy aged flows",
- .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
+ /* Sub-level commands. */
+ [TABLE_CREATE] = {
+ .name = "create",
+ .help = "create template table",
+ .next = NEXT(next_table_attr),
+ .call = parse_table,
+ },
+ [TABLE_DESTROY] = {
+ .name = "destroy",
+ .help = "destroy template table",
+ .next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
.args = ARGS(ARGS_ENTRY(struct buffer, port)),
- .call = parse_aged,
+ .call = parse_table_destroy,
+ },
+ /* Table arguments. */
+ [TABLE_CREATE_ID] = {
+ .name = "table_id",
+ .help = "specify table id to create",
+ .next = NEXT(next_table_attr,
+ NEXT_ENTRY(COMMON_TABLE_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
+ },
+ [TABLE_DESTROY_ID] = {
+ .name = "table",
+ .help = "specify table id to destroy",
+ .next = NEXT(next_table_destroy_attr,
+ NEXT_ENTRY(COMMON_TABLE_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
+ args.table_destroy.table_id)),
+ .call = parse_table_destroy,
},
- [ISOLATE] = {
- .name = "isolate",
- .help = "restrict ingress traffic to the defined flow rules",
- .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
- NEXT_ENTRY(COMMON_PORT_ID)),
- .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
- ARGS_ENTRY(struct buffer, port)),
- .call = parse_isolate,
+ [TABLE_GROUP] = {
+ .name = "group",
+ .help = "specify a group",
+ .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.table.attr.flow_attr.group)),
},
- [FLEX] = {
- .name = "flex_item",
- .help = "flex item API",
- .next = NEXT(next_flex_item),
- .call = parse_flex,
+ [TABLE_PRIORITY] = {
+ .name = "priority",
+ .help = "specify a priority level",
+ .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.table.attr.flow_attr.priority)),
},
- [FLEX_ITEM_INIT] = {
- .name = "init",
- .help = "flex item init",
+ [TABLE_EGRESS] = {
+ .name = "egress",
+ .help = "affect rule to egress",
+ .next = NEXT(next_table_attr),
+ .call = parse_table,
+ },
+ [TABLE_INGRESS] = {
+ .name = "ingress",
+ .help = "affect rule to ingress",
+ .next = NEXT(next_table_attr),
+ .call = parse_table,
+ },
+ [TABLE_TRANSFER] = {
+ .name = "transfer",
+ .help = "affect rule to transfer",
+ .next = NEXT(next_table_attr),
+ .call = parse_table,
+ },
+ [TABLE_RULES_NUMBER] = {
+ .name = "rules_number",
+ .help = "number of rules in table",
+ .next = NEXT(next_table_attr,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.table.attr.nb_flows)),
+ },
+ [TABLE_PATTERN_TEMPLATE] = {
+ .name = "pattern_template",
+ .help = "specify pattern template id",
+ .next = NEXT(next_table_attr,
+ NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
+ args.table.pat_templ_id)),
+ .call = parse_table,
+ },
+ [TABLE_ACTIONS_TEMPLATE] = {
+ .name = "actions_template",
+ .help = "specify actions template id",
+ .next = NEXT(next_table_attr,
+ NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
+ args.table.act_templ_id)),
+ .call = parse_table,
+ },
+ /* Top-level command. */
+ [QUEUE] = {
+ .name = "queue",
+ .help = "queue a flow rule operation",
+ .next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_qo,
+ },
+ /* Sub-level commands. */
+ [QUEUE_CREATE] = {
+ .name = "create",
+ .help = "create a flow rule",
+ .next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
+ NEXT_ENTRY(COMMON_QUEUE_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
+ .call = parse_qo,
+ },
+ [QUEUE_DESTROY] = {
+ .name = "destroy",
+ .help = "destroy a flow rule",
+ .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
+ NEXT_ENTRY(COMMON_QUEUE_ID)),
+ .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",
+ .help = "specify table id",
+ .next = NEXT(NEXT_ENTRY(QUEUE_PATTERN_TEMPLATE),
+ NEXT_ENTRY(COMMON_TABLE_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.vc.table_id)),
+ .call = parse_qo,
+ },
+ [QUEUE_PATTERN_TEMPLATE] = {
+ .name = "pattern_template",
+ .help = "specify pattern template index",
+ .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.vc.pat_templ_id)),
+ .call = parse_qo,
+ },
+ [QUEUE_ACTIONS_TEMPLATE] = {
+ .name = "actions_template",
+ .help = "specify actions template index",
+ .next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.vc.act_templ_id)),
+ .call = parse_qo,
+ },
+ [QUEUE_CREATE_POSTPONE] = {
+ .name = "postpone",
+ .help = "postpone create operation",
+ .next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
+ NEXT_ENTRY(COMMON_BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
+ .call = parse_qo,
+ },
+ [QUEUE_DESTROY_POSTPONE] = {
+ .name = "postpone",
+ .help = "postpone destroy operation",
+ .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
+ NEXT_ENTRY(COMMON_BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
+ .call = parse_qo_destroy,
+ },
+ [QUEUE_DESTROY_ID] = {
+ .name = "rule",
+ .help = "specify rule id to destroy",
+ .next = NEXT(next_queue_destroy_attr,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
+ 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",
+ .type = "{command} {port_id} [{arg} [...]]",
+ .help = "manage indirect actions",
+ .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_ia,
+ },
+ /* Sub-level commands. */
+ [INDIRECT_ACTION_CREATE] = {
+ .name = "create",
+ .help = "create indirect action",
+ .next = NEXT(next_ia_create_attr),
+ .call = parse_ia,
+ },
+ [INDIRECT_ACTION_UPDATE] = {
+ .name = "update",
+ .help = "update indirect action",
+ .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
+ NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+ .call = parse_ia,
+ },
+ [INDIRECT_ACTION_DESTROY] = {
+ .name = "destroy",
+ .help = "destroy indirect action",
+ .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_ia_destroy,
+ },
+ [INDIRECT_ACTION_QUERY] = {
+ .name = "query",
+ .help = "query indirect action",
+ .next = NEXT(NEXT_ENTRY(END),
+ NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
+ .call = parse_ia,
+ },
+ [VALIDATE] = {
+ .name = "validate",
+ .help = "check whether a flow rule can be created",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_vc,
+ },
+ [CREATE] = {
+ .name = "create",
+ .help = "create a flow rule",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_vc,
+ },
+ [DESTROY] = {
+ .name = "destroy",
+ .help = "destroy specific flow rules",
+ .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
+ NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_destroy,
+ },
+ [FLUSH] = {
+ .name = "flush",
+ .help = "destroy all flow rules",
+ .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_flush,
+ },
+ [DUMP] = {
+ .name = "dump",
+ .help = "dump single/all flow rules to file",
+ .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_dump,
+ },
+ [QUERY] = {
+ .name = "query",
+ .help = "query an existing flow rule",
+ .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
+ NEXT_ENTRY(COMMON_RULE_ID),
+ NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
+ ARGS_ENTRY(struct buffer, args.query.rule),
+ ARGS_ENTRY(struct buffer, port)),
+ .call = parse_query,
+ },
+ [LIST] = {
+ .name = "list",
+ .help = "list existing flow rules",
+ .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_list,
+ },
+ [AGED] = {
+ .name = "aged",
+ .help = "list and destroy aged flows",
+ .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_aged,
+ },
+ [ISOLATE] = {
+ .name = "isolate",
+ .help = "restrict ingress traffic to the defined flow rules",
+ .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
+ NEXT_ENTRY(COMMON_PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
+ ARGS_ENTRY(struct buffer, port)),
+ .call = parse_isolate,
+ },
+ [FLEX] = {
+ .name = "flex_item",
+ .help = "flex item API",
+ .next = NEXT(next_flex_item),
+ .call = parse_flex,
+ },
+ [FLEX_ITEM_INIT] = {
+ .name = "init",
+ .help = "flex item init",
.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
ARGS_ENTRY(struct buffer, port)),
.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
},
[TUNNEL_DESTROY] = {
.name = "destroy",
- .help = "destroy tunel",
+ .help = "destroy tunnel",
.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
NEXT_ENTRY(COMMON_PORT_ID)),
.args = ARGS(ARGS_ENTRY(struct buffer, port)),
},
[TUNNEL_DESTROY_ID] = {
.name = "id",
- .help = "tunnel identifier to testroy",
+ .help = "tunnel identifier to destroy",
.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
.call = parse_tunnel,
.name = "end",
.help = "end list of pattern items",
.priv = PRIV_ITEM(END, 0),
- .next = NEXT(NEXT_ENTRY(ACTIONS)),
+ .next = NEXT(NEXT_ENTRY(ACTIONS, END)),
.call = parse_vc,
},
[ITEM_VOID] = {
ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
ITEM_RAW_PATTERN_SIZE)),
},
+ [ITEM_RAW_PATTERN_HEX] = {
+ .name = "pattern_hex",
+ .help = "hex string to look for",
+ .next = NEXT(item_raw,
+ NEXT_ENTRY(COMMON_HEX),
+ NEXT_ENTRY(ITEM_PARAM_IS,
+ ITEM_PARAM_SPEC,
+ ITEM_PARAM_MASK)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
+ ARGS_ENTRY(struct rte_flow_item_raw, length),
+ ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
+ ITEM_RAW_PATTERN_SIZE)),
+ },
[ITEM_ETH] = {
.name = "eth",
.help = "match Ethernet header",
item_param),
.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
},
+ [ITEM_GRE_OPTION] = {
+ .name = "gre_option",
+ .help = "match GRE optional fields",
+ .priv = PRIV_ITEM(GRE_OPTION,
+ sizeof(struct rte_flow_item_gre_opt)),
+ .next = NEXT(item_gre_option),
+ .call = parse_vc,
+ },
+ [ITEM_GRE_OPTION_CHECKSUM] = {
+ .name = "checksum",
+ .help = "match GRE checksum",
+ .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
+ checksum_rsvd.checksum)),
+ },
+ [ITEM_GRE_OPTION_KEY] = {
+ .name = "key",
+ .help = "match GRE key",
+ .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
+ key.key)),
+ },
+ [ITEM_GRE_OPTION_SEQUENCE] = {
+ .name = "sequence",
+ .help = "match GRE sequence",
+ .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
+ sequence.sequence)),
+ },
[ITEM_GTP_PSC] = {
.name = "gtp_psc",
.help = "match GTP extension header with type 0x85",
.next = NEXT(item_l2tpv2),
.call = parse_vc,
},
- [ITEM_L2TPV2_COMMON] = {
- .name = "common",
- .help = "L2TPv2 common header",
- .next = NEXT(item_l2tpv2_common),
- },
- [ITEM_L2TPV2_COMMON_TYPE] = {
+ [ITEM_L2TPV2_TYPE] = {
.name = "type",
- .help = "type of common header",
- .next = NEXT(item_l2tpv2_common_type),
+ .help = "type of l2tpv2",
+ .next = NEXT(item_l2tpv2_type),
.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
},
- [ITEM_L2TPV2_COMMON_TYPE_DATA_L] = {
+ [ITEM_L2TPV2_TYPE_DATA] = {
+ .name = "data",
+ .help = "Type #7: data message without any options",
+ .next = NEXT(item_l2tpv2_type_data),
+ .call = parse_vc_item_l2tpv2_type,
+ },
+ [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
+ .name = "tunnel_id",
+ .help = "tunnel identifier",
+ .next = NEXT(item_l2tpv2_type_data,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type7.tunnel_id)),
+ },
+ [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
+ .name = "session_id",
+ .help = "session identifier",
+ .next = NEXT(item_l2tpv2_type_data,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type7.session_id)),
+ },
+ [ITEM_L2TPV2_TYPE_DATA_L] = {
.name = "data_l",
.help = "Type #6: data message with length option",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_DATA_L_LENGTH,
- ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
- ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
- ITEM_NEXT)),
+ .next = NEXT(item_l2tpv2_type_data_l),
.call = parse_vc_item_l2tpv2_type,
},
[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
.name = "length",
.help = "message length",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_DATA_L_LENGTH,
- ITEM_L2TPV2_COMMON, ITEM_NEXT),
+ .next = NEXT(item_l2tpv2_type_data_l,
NEXT_ENTRY(COMMON_UNSIGNED),
item_param),
.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
.name = "tunnel_id",
.help = "tunnel identifier",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
- ITEM_L2TPV2_COMMON, ITEM_NEXT),
+ .next = NEXT(item_l2tpv2_type_data_l,
NEXT_ENTRY(COMMON_UNSIGNED),
item_param),
.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
.name = "session_id",
.help = "session identifier",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
- ITEM_L2TPV2_COMMON, ITEM_NEXT),
+ .next = NEXT(item_l2tpv2_type_data_l,
NEXT_ENTRY(COMMON_UNSIGNED),
item_param),
.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
hdr.type6.session_id)),
},
- [ITEM_L2TPV2_COMMON_TYPE_CTRL] = {
- .name = "control",
- .help = "Type #3: conrtol message contains length, ns, nr options",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_LENGTH,
- ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
- ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
- ITEM_L2TPV2_MSG_CTRL_NS,
- ITEM_L2TPV2_MSG_CTRL_NR,
- ITEM_NEXT)),
+ [ITEM_L2TPV2_TYPE_DATA_S] = {
+ .name = "data_s",
+ .help = "Type #5: data message with ns, nr option",
+ .next = NEXT(item_l2tpv2_type_data_s),
.call = parse_vc_item_l2tpv2_type,
},
- [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
- .name = "length",
- .help = "message length",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_LENGTH,
- ITEM_L2TPV2_COMMON, ITEM_NEXT),
- NEXT_ENTRY(COMMON_UNSIGNED),
- item_param),
- .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
- hdr.type3.length)),
- },
- [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
+ [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
.name = "tunnel_id",
.help = "tunnel identifier",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
- ITEM_L2TPV2_COMMON, ITEM_NEXT),
+ .next = NEXT(item_l2tpv2_type_data_s,
NEXT_ENTRY(COMMON_UNSIGNED),
item_param),
.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
- hdr.type3.tunnel_id)),
+ hdr.type5.tunnel_id)),
},
- [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
+ [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
.name = "session_id",
.help = "session identifier",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
- ITEM_L2TPV2_COMMON, ITEM_NEXT),
+ .next = NEXT(item_l2tpv2_type_data_s,
NEXT_ENTRY(COMMON_UNSIGNED),
item_param),
.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
- hdr.type3.session_id)),
+ hdr.type5.session_id)),
},
- [ITEM_L2TPV2_MSG_CTRL_NS] = {
+ [ITEM_L2TPV2_MSG_DATA_S_NS] = {
.name = "ns",
.help = "sequence number for message",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_NS,
- ITEM_L2TPV2_COMMON, ITEM_NEXT),
+ .next = NEXT(item_l2tpv2_type_data_s,
NEXT_ENTRY(COMMON_UNSIGNED),
item_param),
.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
- hdr.type3.ns)),
+ hdr.type5.ns)),
},
- [ITEM_L2TPV2_MSG_CTRL_NR] = {
+ [ITEM_L2TPV2_MSG_DATA_S_NR] = {
.name = "nr",
.help = "sequence number for next receive message",
- .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_NS,
- ITEM_L2TPV2_COMMON, ITEM_NEXT),
+ .next = NEXT(item_l2tpv2_type_data_s,
NEXT_ENTRY(COMMON_UNSIGNED),
item_param),
.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
- hdr.type3.nr)),
+ hdr.type5.nr)),
},
- [ITEM_PPP] = {
+ [ITEM_L2TPV2_TYPE_DATA_O] = {
+ .name = "data_o",
+ .help = "Type #4: data message with offset option",
+ .next = NEXT(item_l2tpv2_type_data_o),
+ .call = parse_vc_item_l2tpv2_type,
+ },
+ [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
+ .name = "tunnel_id",
+ .help = "tunnel identifier",
+ .next = NEXT(item_l2tpv2_type_data_o,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type4.tunnel_id)),
+ },
+ [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
+ .name = "session_id",
+ .help = "session identifier",
+ .next = NEXT(item_l2tpv2_type_data_o,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type5.session_id)),
+ },
+ [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
+ .name = "offset_size",
+ .help = "the size of offset padding",
+ .next = NEXT(item_l2tpv2_type_data_o,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type4.offset_size)),
+ },
+ [ITEM_L2TPV2_TYPE_DATA_L_S] = {
+ .name = "data_l_s",
+ .help = "Type #3: data message contains length, ns, nr "
+ "options",
+ .next = NEXT(item_l2tpv2_type_data_l_s),
+ .call = parse_vc_item_l2tpv2_type,
+ },
+ [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
+ .name = "length",
+ .help = "message length",
+ .next = NEXT(item_l2tpv2_type_data_l_s,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.length)),
+ },
+ [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
+ .name = "tunnel_id",
+ .help = "tunnel identifier",
+ .next = NEXT(item_l2tpv2_type_data_l_s,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.tunnel_id)),
+ },
+ [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
+ .name = "session_id",
+ .help = "session identifier",
+ .next = NEXT(item_l2tpv2_type_data_l_s,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.session_id)),
+ },
+ [ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
+ .name = "ns",
+ .help = "sequence number for message",
+ .next = NEXT(item_l2tpv2_type_data_l_s,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.ns)),
+ },
+ [ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
+ .name = "nr",
+ .help = "sequence number for next receive message",
+ .next = NEXT(item_l2tpv2_type_data_l_s,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.nr)),
+ },
+ [ITEM_L2TPV2_TYPE_CTRL] = {
+ .name = "control",
+ .help = "Type #3: conrtol message contains length, ns, nr "
+ "options",
+ .next = NEXT(item_l2tpv2_type_ctrl),
+ .call = parse_vc_item_l2tpv2_type,
+ },
+ [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
+ .name = "length",
+ .help = "message length",
+ .next = NEXT(item_l2tpv2_type_ctrl,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.length)),
+ },
+ [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
+ .name = "tunnel_id",
+ .help = "tunnel identifier",
+ .next = NEXT(item_l2tpv2_type_ctrl,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.tunnel_id)),
+ },
+ [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
+ .name = "session_id",
+ .help = "session identifier",
+ .next = NEXT(item_l2tpv2_type_ctrl,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.session_id)),
+ },
+ [ITEM_L2TPV2_MSG_CTRL_NS] = {
+ .name = "ns",
+ .help = "sequence number for message",
+ .next = NEXT(item_l2tpv2_type_ctrl,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.ns)),
+ },
+ [ITEM_L2TPV2_MSG_CTRL_NR] = {
+ .name = "nr",
+ .help = "sequence number for next receive message",
+ .next = NEXT(item_l2tpv2_type_ctrl,
+ NEXT_ENTRY(COMMON_UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
+ hdr.type3.nr)),
+ },
+ [ITEM_PPP] = {
.name = "ppp",
.help = "match PPP header",
.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
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,
if (!out)
return len;
if (!out->command) {
- if (ctx->curr != VALIDATE && ctx->curr != CREATE)
+ if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
+ ctx->curr != PATTERN_TEMPLATE_CREATE &&
+ ctx->curr != ACTIONS_TEMPLATE_CREATE)
return -1;
if (sizeof(*out) > size)
return -1;
if (parse_default(ctx, token, str, len, NULL, 0) < 0)
return -1;
switch (ctx->curr) {
- case ITEM_L2TPV2_COMMON_TYPE_DATA_L:
- msg_type |= 0x4000;
+ case ITEM_L2TPV2_TYPE_DATA:
+ msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
+ break;
+ case ITEM_L2TPV2_TYPE_DATA_L:
+ msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
break;
- case ITEM_L2TPV2_COMMON_TYPE_CTRL:
- msg_type |= 0xC800;
+ case ITEM_L2TPV2_TYPE_DATA_S:
+ msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
+ break;
+ case ITEM_L2TPV2_TYPE_DATA_O:
+ msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
+ break;
+ case ITEM_L2TPV2_TYPE_DATA_L_S:
+ msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
+ break;
+ case ITEM_L2TPV2_TYPE_CTRL:
+ msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
break;
default:
return -1;
return len;
}
-/** Parse tokens for dump command. */
+/** Parse tokens for dump command. */
+static int
+parse_dump(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 != DUMP)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ }
+ switch (ctx->curr) {
+ case DUMP_ALL:
+ case DUMP_ONE:
+ out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ default:
+ return -1;
+ }
+}
+
+/** Parse tokens for query command. */
+static int
+parse_query(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 != QUERY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse action names. */
+static int
+parse_action(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ const struct arg *arg = pop_args(ctx);
+ unsigned int i;
+
+ (void)size;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ /* Parse action name. */
+ for (i = 0; next_action[i]; ++i) {
+ const struct parse_action_priv *priv;
+
+ token = &token_list[next_action[i]];
+ if (strcmp_partial(token->name, str, len))
+ continue;
+ priv = token->priv;
+ if (!priv)
+ goto error;
+ if (out)
+ memcpy((uint8_t *)ctx->object + arg->offset,
+ &priv->type,
+ arg->size);
+ return len;
+ }
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/** Parse tokens for list command. */
+static int
+parse_list(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 != LIST)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.list.group =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
+ sizeof(*out->args.list.group)) > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = out->args.list.group + out->args.list.group_n++;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for list all aged flows command. */
+static int
+parse_aged(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 != AGED)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ if (ctx->curr == AGED_DESTROY)
+ out->args.aged.destroy = 1;
+ return len;
+}
+
+/** Parse tokens for isolate command. */
+static int
+parse_isolate(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 != ISOLATE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse tokens for info/configure command. */
+static int
+parse_configure(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 != INFO && ctx->curr != CONFIGURE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse tokens for template create command. */
+static int
+parse_template(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 != PATTERN_TEMPLATE &&
+ ctx->curr != ACTIONS_TEMPLATE)
+ 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 PATTERN_TEMPLATE_CREATE:
+ out->args.vc.pattern =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ out->args.vc.pat_templ_id = UINT32_MAX;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ case PATTERN_TEMPLATE_EGRESS:
+ out->args.vc.attr.egress = 1;
+ return len;
+ case PATTERN_TEMPLATE_INGRESS:
+ out->args.vc.attr.ingress = 1;
+ return len;
+ case PATTERN_TEMPLATE_TRANSFER:
+ out->args.vc.attr.transfer = 1;
+ return len;
+ case ACTIONS_TEMPLATE_CREATE:
+ out->args.vc.act_templ_id = UINT32_MAX;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ case ACTIONS_TEMPLATE_SPEC:
+ out->args.vc.actions =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ ctx->object = out->args.vc.actions;
+ ctx->objmask = NULL;
+ return len;
+ case ACTIONS_TEMPLATE_MASK:
+ out->args.vc.masks =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)
+ (out->args.vc.actions +
+ out->args.vc.actions_n),
+ sizeof(double));
+ ctx->object = out->args.vc.masks;
+ ctx->objmask = NULL;
+ return len;
+ case ACTIONS_TEMPLATE_EGRESS:
+ out->args.vc.attr.egress = 1;
+ return len;
+ case ACTIONS_TEMPLATE_INGRESS:
+ out->args.vc.attr.ingress = 1;
+ return len;
+ case ACTIONS_TEMPLATE_TRANSFER:
+ out->args.vc.attr.transfer = 1;
+ return len;
+ default:
+ return -1;
+ }
+}
+
+/** Parse tokens for template destroy command. */
+static int
+parse_template_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 *template_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 == PATTERN_TEMPLATE ||
+ out->command == ACTIONS_TEMPLATE) {
+ if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
+ ctx->curr != ACTIONS_TEMPLATE_DESTROY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.templ_destroy.template_id =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ template_id = out->args.templ_destroy.template_id
+ + out->args.templ_destroy.template_id_n++;
+ if ((uint8_t *)template_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = template_id;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for table create command. */
static int
-parse_dump(struct context *ctx, const struct token *token,
+parse_table(struct context *ctx, const struct token *token,
const char *str, unsigned int len,
void *buf, unsigned int size)
{
struct buffer *out = buf;
+ uint32_t *template_id;
/* Token name must match. */
if (parse_default(ctx, token, str, len, NULL, 0) < 0)
if (!out)
return len;
if (!out->command) {
- if (ctx->curr != DUMP)
+ if (ctx->curr != TABLE)
return -1;
if (sizeof(*out) > size)
return -1;
return len;
}
switch (ctx->curr) {
- case DUMP_ALL:
- case DUMP_ONE:
- out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
+ case TABLE_CREATE:
out->command = ctx->curr;
ctx->objdata = 0;
ctx->object = out;
ctx->objmask = NULL;
+ out->args.table.id = UINT32_MAX;
+ return len;
+ case TABLE_PATTERN_TEMPLATE:
+ out->args.table.pat_templ_id =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ template_id = out->args.table.pat_templ_id
+ + out->args.table.pat_templ_id_n++;
+ if ((uint8_t *)template_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = template_id;
+ ctx->objmask = NULL;
+ return len;
+ case TABLE_ACTIONS_TEMPLATE:
+ out->args.table.act_templ_id =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)
+ (out->args.table.pat_templ_id +
+ out->args.table.pat_templ_id_n),
+ sizeof(double));
+ template_id = out->args.table.act_templ_id
+ + out->args.table.act_templ_id_n++;
+ if ((uint8_t *)template_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = template_id;
+ ctx->objmask = NULL;
+ return len;
+ case TABLE_INGRESS:
+ out->args.table.attr.flow_attr.ingress = 1;
+ return len;
+ case TABLE_EGRESS:
+ out->args.table.attr.flow_attr.egress = 1;
+ return len;
+ case TABLE_TRANSFER:
+ out->args.table.attr.flow_attr.transfer = 1;
return len;
default:
return -1;
}
}
-/** Parse tokens for query command. */
+/** Parse tokens for table destroy command. */
static int
-parse_query(struct context *ctx, const struct token *token,
- const char *str, unsigned int len,
- void *buf, unsigned int size)
+parse_table_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 *table_id;
/* Token name must match. */
if (parse_default(ctx, token, str, len, NULL, 0) < 0)
/* Nothing else to do if there is no buffer. */
if (!out)
return len;
- if (!out->command) {
- if (ctx->curr != QUERY)
+ if (!out->command || out->command == TABLE) {
+ if (ctx->curr != TABLE_DESTROY)
return -1;
if (sizeof(*out) > size)
return -1;
ctx->objdata = 0;
ctx->object = out;
ctx->objmask = NULL;
+ out->args.table_destroy.table_id =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
}
+ table_id = out->args.table_destroy.table_id
+ + out->args.table_destroy.table_id_n++;
+ if ((uint8_t *)table_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = table_id;
+ ctx->objmask = NULL;
return len;
}
-/** Parse action names. */
+/** Parse tokens for queue create commands. */
static int
-parse_action(struct context *ctx, const struct token *token,
- const char *str, unsigned int len,
- void *buf, unsigned int size)
+parse_qo(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
{
struct buffer *out = buf;
- const struct arg *arg = pop_args(ctx);
- unsigned int i;
- (void)size;
- /* Argument is expected. */
- if (!arg)
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
return -1;
- /* Parse action name. */
- for (i = 0; next_action[i]; ++i) {
- const struct parse_action_priv *priv;
-
- token = &token_list[next_action[i]];
- if (strcmp_partial(token->name, str, len))
- continue;
- priv = token->priv;
- if (!priv)
- goto error;
- if (out)
- memcpy((uint8_t *)ctx->object + arg->offset,
- &priv->type,
- arg->size);
+ /* 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->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.vc.data = (uint8_t *)out + size;
return len;
}
-error:
- push_args(ctx, arg);
- return -1;
+ switch (ctx->curr) {
+ case QUEUE_CREATE:
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ case QUEUE_TEMPLATE_TABLE:
+ case QUEUE_PATTERN_TEMPLATE:
+ case QUEUE_ACTIONS_TEMPLATE:
+ case QUEUE_CREATE_POSTPONE:
+ return len;
+ case ITEM_PATTERN:
+ out->args.vc.pattern =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ ctx->object = out->args.vc.pattern;
+ ctx->objmask = NULL;
+ return len;
+ case ACTIONS:
+ out->args.vc.actions =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)
+ (out->args.vc.pattern +
+ out->args.vc.pattern_n),
+ sizeof(double));
+ ctx->object = out->args.vc.actions;
+ ctx->objmask = NULL;
+ return len;
+ default:
+ return -1;
+ }
}
-/** Parse tokens for list command. */
+/** Parse tokens for queue destroy command. */
static int
-parse_list(struct context *ctx, const struct token *token,
- const char *str, unsigned int len,
- void *buf, unsigned int size)
+parse_qo_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 *flow_id;
/* Token name must match. */
if (parse_default(ctx, token, str, len, NULL, 0) < 0)
/* Nothing else to do if there is no buffer. */
if (!out)
return len;
- if (!out->command) {
- if (ctx->curr != LIST)
+ if (!out->command || out->command == QUEUE) {
+ if (ctx->curr != QUEUE_DESTROY)
return -1;
if (sizeof(*out) > size)
return -1;
ctx->objdata = 0;
ctx->object = out;
ctx->objmask = NULL;
- out->args.list.group =
+ out->args.destroy.rule =
(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
sizeof(double));
return len;
}
- if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
- sizeof(*out->args.list.group)) > (uint8_t *)out + size)
+ switch (ctx->curr) {
+ case QUEUE_DESTROY_ID:
+ flow_id = out->args.destroy.rule
+ + out->args.destroy.rule_n++;
+ if ((uint8_t *)flow_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = flow_id;
+ ctx->objmask = NULL;
+ return len;
+ case QUEUE_DESTROY_POSTPONE:
+ return len;
+ default:
return -1;
- ctx->objdata = 0;
- ctx->object = out->args.list.group + out->args.list.group_n++;
- ctx->objmask = NULL;
- return len;
+ }
}
-/** Parse tokens for list all aged flows command. */
+/** Parse tokens for push queue command. */
static int
-parse_aged(struct context *ctx, const struct token *token,
+parse_push(struct context *ctx, const struct token *token,
const char *str, unsigned int len,
void *buf, unsigned int size)
{
if (!out)
return len;
if (!out->command) {
- if (ctx->curr != AGED)
+ if (ctx->curr != PUSH)
return -1;
if (sizeof(*out) > size)
return -1;
ctx->objdata = 0;
ctx->object = out;
ctx->objmask = NULL;
+ out->args.vc.data = (uint8_t *)out + size;
}
- if (ctx->curr == AGED_DESTROY)
- out->args.aged.destroy = 1;
return len;
}
-/** Parse tokens for isolate command. */
+/** Parse tokens for pull command. */
static int
-parse_isolate(struct context *ctx, const struct token *token,
- const char *str, unsigned int len,
- void *buf, unsigned int size)
+parse_pull(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
{
struct buffer *out = buf;
if (!out)
return len;
if (!out->command) {
- if (ctx->curr != ISOLATE)
+ if (ctx->curr != PULL)
return -1;
if (sizeof(*out) > size)
return -1;
ctx->objdata = 0;
ctx->object = out;
ctx->objmask = NULL;
+ out->args.vc.data = (uint8_t *)out + size;
}
return len;
}
static int
parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
{
- char *c = NULL;
- uint32_t i, len;
- char tmp[3];
+ const uint8_t *head = dst;
+ uint32_t left;
/* Check input parameters */
if ((src == NULL) ||
(*size == 0))
return -1;
+ left = *size;
+
/* Convert chars to bytes */
- for (i = 0, len = 0; i < *size; i += 2) {
- snprintf(tmp, 3, "%s", src + i);
- dst[len++] = strtoul(tmp, &c, 16);
- if (*c != 0) {
- len--;
- dst[len] = 0;
- *size = len;
+ while (left) {
+ char tmp[3], *end = tmp;
+ uint32_t read_lim = left & 1 ? 1 : 2;
+
+ snprintf(tmp, read_lim + 1, "%s", src);
+ *dst = strtoul(tmp, &end, 16);
+ if (*end) {
+ *dst = 0;
+ *size = (uint32_t)(dst - head);
return -1;
}
+ left -= read_lim;
+ src += read_lim;
+ dst++;
}
- dst[len] = 0;
- *size = len;
-
+ *dst = 0;
+ *size = (uint32_t)(dst - head);
return 0;
}
return -1;
}
+/** Complete available pattern template IDs. */
+static int
+comp_pattern_template_id(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i = 0;
+ struct rte_port *port;
+ struct port_template *pt;
+
+ (void)token;
+ if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
+ ctx->port == (portid_t)RTE_PORT_ALL)
+ return -1;
+ port = &ports[ctx->port];
+ for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
+ if (buf && i == ent)
+ return snprintf(buf, size, "%u", pt->id);
+ ++i;
+ }
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete available actions template IDs. */
+static int
+comp_actions_template_id(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i = 0;
+ struct rte_port *port;
+ struct port_template *pt;
+
+ (void)token;
+ if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
+ ctx->port == (portid_t)RTE_PORT_ALL)
+ return -1;
+ port = &ports[ctx->port];
+ for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
+ if (buf && i == ent)
+ return snprintf(buf, size, "%u", pt->id);
+ ++i;
+ }
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete available table IDs. */
+static int
+comp_table_id(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i = 0;
+ struct rte_port *port;
+ struct port_table *pt;
+
+ (void)token;
+ if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
+ ctx->port == (portid_t)RTE_PORT_ALL)
+ return -1;
+ port = &ports[ctx->port];
+ for (pt = port->table_list; pt != NULL; pt = pt->next) {
+ if (buf && i == ent)
+ return snprintf(buf, size, "%u", pt->id);
+ ++i;
+ }
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete available queue IDs. */
+static int
+comp_queue_id(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i = 0;
+ struct rte_port *port;
+
+ (void)token;
+ if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
+ ctx->port == (portid_t)RTE_PORT_ALL)
+ return -1;
+ port = &ports[ctx->port];
+ for (i = 0; i < port->queue_nb; i++) {
+ if (buf && i == ent)
+ return snprintf(buf, size, "%u", i);
+ }
+ if (buf)
+ return -1;
+ return i;
+}
+
/** Internal context. */
static struct context cmd_flow_context;
cmd_flow_parsed(const struct buffer *in)
{
switch (in->command) {
+ case INFO:
+ port_flow_get_info(in->port);
+ break;
+ case CONFIGURE:
+ port_flow_configure(in->port,
+ &in->args.configure.port_attr,
+ in->args.configure.nb_queue,
+ &in->args.configure.queue_attr);
+ break;
+ case PATTERN_TEMPLATE_CREATE:
+ port_flow_pattern_template_create(in->port,
+ in->args.vc.pat_templ_id,
+ &((const struct rte_flow_pattern_template_attr) {
+ .relaxed_matching = in->args.vc.attr.reserved,
+ .ingress = in->args.vc.attr.ingress,
+ .egress = in->args.vc.attr.egress,
+ .transfer = in->args.vc.attr.transfer,
+ }),
+ in->args.vc.pattern);
+ break;
+ case PATTERN_TEMPLATE_DESTROY:
+ port_flow_pattern_template_destroy(in->port,
+ in->args.templ_destroy.template_id_n,
+ in->args.templ_destroy.template_id);
+ break;
+ case ACTIONS_TEMPLATE_CREATE:
+ port_flow_actions_template_create(in->port,
+ in->args.vc.act_templ_id,
+ &((const struct rte_flow_actions_template_attr) {
+ .ingress = in->args.vc.attr.ingress,
+ .egress = in->args.vc.attr.egress,
+ .transfer = in->args.vc.attr.transfer,
+ }),
+ in->args.vc.actions,
+ in->args.vc.masks);
+ break;
+ case ACTIONS_TEMPLATE_DESTROY:
+ port_flow_actions_template_destroy(in->port,
+ in->args.templ_destroy.template_id_n,
+ in->args.templ_destroy.template_id);
+ break;
+ case TABLE_CREATE:
+ port_flow_template_table_create(in->port, in->args.table.id,
+ &in->args.table.attr, in->args.table.pat_templ_id_n,
+ in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
+ in->args.table.act_templ_id);
+ break;
+ case TABLE_DESTROY:
+ port_flow_template_table_destroy(in->port,
+ in->args.table_destroy.table_id_n,
+ in->args.table_destroy.table_id);
+ break;
+ case QUEUE_CREATE:
+ port_queue_flow_create(in->port, in->queue, in->postpone,
+ in->args.vc.table_id, in->args.vc.pat_templ_id,
+ in->args.vc.act_templ_id, in->args.vc.pattern,
+ in->args.vc.actions);
+ break;
+ case QUEUE_DESTROY:
+ port_queue_flow_destroy(in->port, in->queue, in->postpone,
+ 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,
uint8_t qfi:6;
uint8_t next;
} psc;
- psc.len = sizeof(psc);
+ psc.len = sizeof(psc) / 4;
psc.pdu_type = opt->hdr.type;
psc.qfi = opt->hdr.qfi;
psc.next = 0;
((const struct rte_flow_item_flex *)
item->spec)->length : 0;
break;
+ case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
+ size = 0;
+ if (item->spec) {
+ const struct rte_flow_item_gre_opt
+ *opt = item->spec;
+ if (opt->checksum_rsvd.checksum) {
+ *total_size +=
+ sizeof(opt->checksum_rsvd);
+ rte_memcpy(data_tail - (*total_size),
+ &opt->checksum_rsvd,
+ sizeof(opt->checksum_rsvd));
+ }
+ if (opt->key.key) {
+ *total_size += sizeof(opt->key.key);
+ rte_memcpy(data_tail - (*total_size),
+ &opt->key.key,
+ sizeof(opt->key.key));
+ }
+ if (opt->sequence.sequence) {
+ *total_size += sizeof(opt->sequence.sequence);
+ rte_memcpy(data_tail - (*total_size),
+ &opt->sequence.sequence,
+ sizeof(opt->sequence.sequence));
+ }
+ }
+ proto = 0x2F;
+ break;
default:
fprintf(stderr, "Error - Not supported item\n");
goto error;