1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016 6WIND S.A.
3 * Copyright 2016 Mellanox Technologies, Ltd
13 #include <arpa/inet.h>
14 #include <sys/socket.h>
16 #include <rte_common.h>
17 #include <rte_eth_ctrl.h>
18 #include <rte_ethdev.h>
19 #include <rte_byteorder.h>
20 #include <cmdline_parse.h>
21 #include <cmdline_parse_etheraddr.h>
26 /** Parser token indices. */
46 /* Top-level command. */
49 /* Sub-level commands. */
58 /* Destroy arguments. */
61 /* Query arguments. */
67 /* Validate/create arguments. */
74 /* Validate/create pattern. */
111 ITEM_VLAN_INNER_TYPE,
143 ITEM_E_TAG_GRP_ECID_B,
162 ITEM_ARP_ETH_IPV4_SHA,
163 ITEM_ARP_ETH_IPV4_SPA,
164 ITEM_ARP_ETH_IPV4_THA,
165 ITEM_ARP_ETH_IPV4_TPA,
167 ITEM_IPV6_EXT_NEXT_HDR,
172 ITEM_ICMP6_ND_NS_TARGET_ADDR,
174 ITEM_ICMP6_ND_NA_TARGET_ADDR,
176 ITEM_ICMP6_ND_OPT_TYPE,
177 ITEM_ICMP6_ND_OPT_SLA_ETH,
178 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
179 ITEM_ICMP6_ND_OPT_TLA_ETH,
180 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
184 /* Validate/create actions. */
204 ACTION_RSS_FUNC_DEFAULT,
205 ACTION_RSS_FUNC_TOEPLITZ,
206 ACTION_RSS_FUNC_SIMPLE_XOR,
218 ACTION_PHY_PORT_ORIGINAL,
219 ACTION_PHY_PORT_INDEX,
221 ACTION_PORT_ID_ORIGINAL,
225 ACTION_OF_SET_MPLS_TTL,
226 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
227 ACTION_OF_DEC_MPLS_TTL,
228 ACTION_OF_SET_NW_TTL,
229 ACTION_OF_SET_NW_TTL_NW_TTL,
230 ACTION_OF_DEC_NW_TTL,
231 ACTION_OF_COPY_TTL_OUT,
232 ACTION_OF_COPY_TTL_IN,
235 ACTION_OF_PUSH_VLAN_ETHERTYPE,
236 ACTION_OF_SET_VLAN_VID,
237 ACTION_OF_SET_VLAN_VID_VLAN_VID,
238 ACTION_OF_SET_VLAN_PCP,
239 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
241 ACTION_OF_POP_MPLS_ETHERTYPE,
243 ACTION_OF_PUSH_MPLS_ETHERTYPE,
249 ACTION_SET_IPV4_SRC_IPV4_SRC,
251 ACTION_SET_IPV4_DST_IPV4_DST,
253 ACTION_SET_IPV6_SRC_IPV6_SRC,
255 ACTION_SET_IPV6_DST_IPV6_DST,
257 ACTION_SET_TP_SRC_TP_SRC,
259 ACTION_SET_TP_DST_TP_DST,
265 ACTION_SET_MAC_SRC_MAC_SRC,
267 ACTION_SET_MAC_DST_MAC_DST,
270 /** Maximum size for pattern in struct rte_flow_item_raw. */
271 #define ITEM_RAW_PATTERN_SIZE 40
273 /** Storage size for struct rte_flow_item_raw including pattern. */
274 #define ITEM_RAW_SIZE \
275 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
277 /** Maximum number of queue indices in struct rte_flow_action_rss. */
278 #define ACTION_RSS_QUEUE_NUM 32
280 /** Storage for struct rte_flow_action_rss including external data. */
281 struct action_rss_data {
282 struct rte_flow_action_rss conf;
283 uint8_t key[RSS_HASH_KEY_LENGTH];
284 uint16_t queue[ACTION_RSS_QUEUE_NUM];
287 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
288 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
290 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
291 struct action_vxlan_encap_data {
292 struct rte_flow_action_vxlan_encap conf;
293 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
294 struct rte_flow_item_eth item_eth;
295 struct rte_flow_item_vlan item_vlan;
297 struct rte_flow_item_ipv4 item_ipv4;
298 struct rte_flow_item_ipv6 item_ipv6;
300 struct rte_flow_item_udp item_udp;
301 struct rte_flow_item_vxlan item_vxlan;
304 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
305 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
307 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
308 struct action_nvgre_encap_data {
309 struct rte_flow_action_nvgre_encap conf;
310 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
311 struct rte_flow_item_eth item_eth;
312 struct rte_flow_item_vlan item_vlan;
314 struct rte_flow_item_ipv4 item_ipv4;
315 struct rte_flow_item_ipv6 item_ipv6;
317 struct rte_flow_item_nvgre item_nvgre;
320 /** Maximum number of subsequent tokens and arguments on the stack. */
321 #define CTX_STACK_SIZE 16
323 /** Parser context. */
325 /** Stack of subsequent token lists to process. */
326 const enum index *next[CTX_STACK_SIZE];
327 /** Arguments for stacked tokens. */
328 const void *args[CTX_STACK_SIZE];
329 enum index curr; /**< Current token index. */
330 enum index prev; /**< Index of the last token seen. */
331 int next_num; /**< Number of entries in next[]. */
332 int args_num; /**< Number of entries in args[]. */
333 uint32_t eol:1; /**< EOL has been detected. */
334 uint32_t last:1; /**< No more arguments. */
335 portid_t port; /**< Current port ID (for completions). */
336 uint32_t objdata; /**< Object-specific data. */
337 void *object; /**< Address of current object for relative offsets. */
338 void *objmask; /**< Object a full mask must be written to. */
341 /** Token argument. */
343 uint32_t hton:1; /**< Use network byte ordering. */
344 uint32_t sign:1; /**< Value is signed. */
345 uint32_t bounded:1; /**< Value is bounded. */
346 uintmax_t min; /**< Minimum value if bounded. */
347 uintmax_t max; /**< Maximum value if bounded. */
348 uint32_t offset; /**< Relative offset from ctx->object. */
349 uint32_t size; /**< Field size. */
350 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
353 /** Parser token definition. */
355 /** Type displayed during completion (defaults to "TOKEN"). */
357 /** Help displayed during completion (defaults to token name). */
359 /** Private data used by parser functions. */
362 * Lists of subsequent tokens to push on the stack. Each call to the
363 * parser consumes the last entry of that stack.
365 const enum index *const *next;
366 /** Arguments stack for subsequent tokens that need them. */
367 const struct arg *const *args;
369 * Token-processing callback, returns -1 in case of error, the
370 * length of the matched string otherwise. If NULL, attempts to
371 * match the token name.
373 * If buf is not NULL, the result should be stored in it according
374 * to context. An error is returned if not large enough.
376 int (*call)(struct context *ctx, const struct token *token,
377 const char *str, unsigned int len,
378 void *buf, unsigned int size);
380 * Callback that provides possible values for this token, used for
381 * completion. Returns -1 in case of error, the number of possible
382 * values otherwise. If NULL, the token name is used.
384 * If buf is not NULL, entry index ent is written to buf and the
385 * full length of the entry is returned (same behavior as
388 int (*comp)(struct context *ctx, const struct token *token,
389 unsigned int ent, char *buf, unsigned int size);
390 /** Mandatory token name, no default value. */
394 /** Static initializer for the next field. */
395 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
397 /** Static initializer for a NEXT() entry. */
398 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
400 /** Static initializer for the args field. */
401 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
403 /** Static initializer for ARGS() to target a field. */
404 #define ARGS_ENTRY(s, f) \
405 (&(const struct arg){ \
406 .offset = offsetof(s, f), \
407 .size = sizeof(((s *)0)->f), \
410 /** Static initializer for ARGS() to target a bit-field. */
411 #define ARGS_ENTRY_BF(s, f, b) \
412 (&(const struct arg){ \
414 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
417 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
418 #define ARGS_ENTRY_MASK(s, f, m) \
419 (&(const struct arg){ \
420 .offset = offsetof(s, f), \
421 .size = sizeof(((s *)0)->f), \
422 .mask = (const void *)(m), \
425 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
426 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
427 (&(const struct arg){ \
429 .offset = offsetof(s, f), \
430 .size = sizeof(((s *)0)->f), \
431 .mask = (const void *)(m), \
434 /** Static initializer for ARGS() to target a pointer. */
435 #define ARGS_ENTRY_PTR(s, f) \
436 (&(const struct arg){ \
437 .size = sizeof(*((s *)0)->f), \
440 /** Static initializer for ARGS() with arbitrary offset and size. */
441 #define ARGS_ENTRY_ARB(o, s) \
442 (&(const struct arg){ \
447 /** Same as ARGS_ENTRY_ARB() with bounded values. */
448 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
449 (&(const struct arg){ \
457 /** Same as ARGS_ENTRY() using network byte ordering. */
458 #define ARGS_ENTRY_HTON(s, f) \
459 (&(const struct arg){ \
461 .offset = offsetof(s, f), \
462 .size = sizeof(((s *)0)->f), \
465 /** Parser output buffer layout expected by cmd_flow_parsed(). */
467 enum index command; /**< Flow command. */
468 portid_t port; /**< Affected port ID. */
471 struct rte_flow_attr attr;
472 struct rte_flow_item *pattern;
473 struct rte_flow_action *actions;
477 } vc; /**< Validate/create arguments. */
481 } destroy; /**< Destroy arguments. */
484 struct rte_flow_action action;
485 } query; /**< Query arguments. */
489 } list; /**< List arguments. */
492 } isolate; /**< Isolated mode arguments. */
493 } args; /**< Command arguments. */
496 /** Private data for pattern items. */
497 struct parse_item_priv {
498 enum rte_flow_item_type type; /**< Item type. */
499 uint32_t size; /**< Size of item specification structure. */
502 #define PRIV_ITEM(t, s) \
503 (&(const struct parse_item_priv){ \
504 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
508 /** Private data for actions. */
509 struct parse_action_priv {
510 enum rte_flow_action_type type; /**< Action type. */
511 uint32_t size; /**< Size of action configuration structure. */
514 #define PRIV_ACTION(t, s) \
515 (&(const struct parse_action_priv){ \
516 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
520 static const enum index next_vc_attr[] = {
530 static const enum index next_destroy_attr[] = {
536 static const enum index next_list_attr[] = {
542 static const enum index item_param[] = {
551 static const enum index item_param_is[] = {
556 static const enum index next_item[] = {
592 ITEM_ICMP6_ND_OPT_SLA_ETH,
593 ITEM_ICMP6_ND_OPT_TLA_ETH,
598 static const enum index item_fuzzy[] = {
604 static const enum index item_any[] = {
610 static const enum index item_vf[] = {
616 static const enum index item_phy_port[] = {
622 static const enum index item_port_id[] = {
628 static const enum index item_mark[] = {
634 static const enum index item_raw[] = {
644 static const enum index item_eth[] = {
652 static const enum index item_vlan[] = {
657 ITEM_VLAN_INNER_TYPE,
662 static const enum index item_ipv4[] = {
672 static const enum index item_ipv6[] = {
683 static const enum index item_icmp[] = {
690 static const enum index item_udp[] = {
697 static const enum index item_tcp[] = {
705 static const enum index item_sctp[] = {
714 static const enum index item_vxlan[] = {
720 static const enum index item_e_tag[] = {
721 ITEM_E_TAG_GRP_ECID_B,
726 static const enum index item_nvgre[] = {
732 static const enum index item_mpls[] = {
738 static const enum index item_gre[] = {
744 static const enum index item_gtp[] = {
750 static const enum index item_geneve[] = {
757 static const enum index item_vxlan_gpe[] = {
763 static const enum index item_arp_eth_ipv4[] = {
764 ITEM_ARP_ETH_IPV4_SHA,
765 ITEM_ARP_ETH_IPV4_SPA,
766 ITEM_ARP_ETH_IPV4_THA,
767 ITEM_ARP_ETH_IPV4_TPA,
772 static const enum index item_ipv6_ext[] = {
773 ITEM_IPV6_EXT_NEXT_HDR,
778 static const enum index item_icmp6[] = {
785 static const enum index item_icmp6_nd_ns[] = {
786 ITEM_ICMP6_ND_NS_TARGET_ADDR,
791 static const enum index item_icmp6_nd_na[] = {
792 ITEM_ICMP6_ND_NA_TARGET_ADDR,
797 static const enum index item_icmp6_nd_opt[] = {
798 ITEM_ICMP6_ND_OPT_TYPE,
803 static const enum index item_icmp6_nd_opt_sla_eth[] = {
804 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
809 static const enum index item_icmp6_nd_opt_tla_eth[] = {
810 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
815 static const enum index item_meta[] = {
821 static const enum index next_action[] = {
837 ACTION_OF_SET_MPLS_TTL,
838 ACTION_OF_DEC_MPLS_TTL,
839 ACTION_OF_SET_NW_TTL,
840 ACTION_OF_DEC_NW_TTL,
841 ACTION_OF_COPY_TTL_OUT,
842 ACTION_OF_COPY_TTL_IN,
845 ACTION_OF_SET_VLAN_VID,
846 ACTION_OF_SET_VLAN_PCP,
867 static const enum index action_mark[] = {
873 static const enum index action_queue[] = {
879 static const enum index action_count[] = {
886 static const enum index action_rss[] = {
897 static const enum index action_vf[] = {
904 static const enum index action_phy_port[] = {
905 ACTION_PHY_PORT_ORIGINAL,
906 ACTION_PHY_PORT_INDEX,
911 static const enum index action_port_id[] = {
912 ACTION_PORT_ID_ORIGINAL,
918 static const enum index action_meter[] = {
924 static const enum index action_of_set_mpls_ttl[] = {
925 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
930 static const enum index action_of_set_nw_ttl[] = {
931 ACTION_OF_SET_NW_TTL_NW_TTL,
936 static const enum index action_of_push_vlan[] = {
937 ACTION_OF_PUSH_VLAN_ETHERTYPE,
942 static const enum index action_of_set_vlan_vid[] = {
943 ACTION_OF_SET_VLAN_VID_VLAN_VID,
948 static const enum index action_of_set_vlan_pcp[] = {
949 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
954 static const enum index action_of_pop_mpls[] = {
955 ACTION_OF_POP_MPLS_ETHERTYPE,
960 static const enum index action_of_push_mpls[] = {
961 ACTION_OF_PUSH_MPLS_ETHERTYPE,
966 static const enum index action_set_ipv4_src[] = {
967 ACTION_SET_IPV4_SRC_IPV4_SRC,
972 static const enum index action_set_mac_src[] = {
973 ACTION_SET_MAC_SRC_MAC_SRC,
978 static const enum index action_set_ipv4_dst[] = {
979 ACTION_SET_IPV4_DST_IPV4_DST,
984 static const enum index action_set_ipv6_src[] = {
985 ACTION_SET_IPV6_SRC_IPV6_SRC,
990 static const enum index action_set_ipv6_dst[] = {
991 ACTION_SET_IPV6_DST_IPV6_DST,
996 static const enum index action_set_tp_src[] = {
997 ACTION_SET_TP_SRC_TP_SRC,
1002 static const enum index action_set_tp_dst[] = {
1003 ACTION_SET_TP_DST_TP_DST,
1008 static const enum index action_set_ttl[] = {
1014 static const enum index action_jump[] = {
1020 static const enum index action_set_mac_dst[] = {
1021 ACTION_SET_MAC_DST_MAC_DST,
1026 static int parse_init(struct context *, const struct token *,
1027 const char *, unsigned int,
1028 void *, unsigned int);
1029 static int parse_vc(struct context *, const struct token *,
1030 const char *, unsigned int,
1031 void *, unsigned int);
1032 static int parse_vc_spec(struct context *, const struct token *,
1033 const char *, unsigned int, void *, unsigned int);
1034 static int parse_vc_conf(struct context *, const struct token *,
1035 const char *, unsigned int, void *, unsigned int);
1036 static int parse_vc_action_rss(struct context *, const struct token *,
1037 const char *, unsigned int, void *,
1039 static int parse_vc_action_rss_func(struct context *, const struct token *,
1040 const char *, unsigned int, void *,
1042 static int parse_vc_action_rss_type(struct context *, const struct token *,
1043 const char *, unsigned int, void *,
1045 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1046 const char *, unsigned int, void *,
1048 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1049 const char *, unsigned int, void *,
1051 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1052 const char *, unsigned int, void *,
1054 static int parse_destroy(struct context *, const struct token *,
1055 const char *, unsigned int,
1056 void *, unsigned int);
1057 static int parse_flush(struct context *, const struct token *,
1058 const char *, unsigned int,
1059 void *, unsigned int);
1060 static int parse_query(struct context *, const struct token *,
1061 const char *, unsigned int,
1062 void *, unsigned int);
1063 static int parse_action(struct context *, const struct token *,
1064 const char *, unsigned int,
1065 void *, unsigned int);
1066 static int parse_list(struct context *, const struct token *,
1067 const char *, unsigned int,
1068 void *, unsigned int);
1069 static int parse_isolate(struct context *, const struct token *,
1070 const char *, unsigned int,
1071 void *, unsigned int);
1072 static int parse_int(struct context *, const struct token *,
1073 const char *, unsigned int,
1074 void *, unsigned int);
1075 static int parse_prefix(struct context *, const struct token *,
1076 const char *, unsigned int,
1077 void *, unsigned int);
1078 static int parse_boolean(struct context *, const struct token *,
1079 const char *, unsigned int,
1080 void *, unsigned int);
1081 static int parse_string(struct context *, const struct token *,
1082 const char *, unsigned int,
1083 void *, unsigned int);
1084 static int parse_mac_addr(struct context *, const struct token *,
1085 const char *, unsigned int,
1086 void *, unsigned int);
1087 static int parse_ipv4_addr(struct context *, const struct token *,
1088 const char *, unsigned int,
1089 void *, unsigned int);
1090 static int parse_ipv6_addr(struct context *, const struct token *,
1091 const char *, unsigned int,
1092 void *, unsigned int);
1093 static int parse_port(struct context *, const struct token *,
1094 const char *, unsigned int,
1095 void *, unsigned int);
1096 static int comp_none(struct context *, const struct token *,
1097 unsigned int, char *, unsigned int);
1098 static int comp_boolean(struct context *, const struct token *,
1099 unsigned int, char *, unsigned int);
1100 static int comp_action(struct context *, const struct token *,
1101 unsigned int, char *, unsigned int);
1102 static int comp_port(struct context *, const struct token *,
1103 unsigned int, char *, unsigned int);
1104 static int comp_rule_id(struct context *, const struct token *,
1105 unsigned int, char *, unsigned int);
1106 static int comp_vc_action_rss_type(struct context *, const struct token *,
1107 unsigned int, char *, unsigned int);
1108 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1109 unsigned int, char *, unsigned int);
1111 /** Token definitions. */
1112 static const struct token token_list[] = {
1113 /* Special tokens. */
1116 .help = "null entry, abused as the entry point",
1117 .next = NEXT(NEXT_ENTRY(FLOW)),
1122 .help = "command may end here",
1124 /* Common tokens. */
1128 .help = "integer value",
1133 .name = "{unsigned}",
1135 .help = "unsigned integer value",
1142 .help = "prefix length for bit-mask",
1143 .call = parse_prefix,
1147 .name = "{boolean}",
1149 .help = "any boolean value",
1150 .call = parse_boolean,
1151 .comp = comp_boolean,
1156 .help = "fixed string",
1157 .call = parse_string,
1161 .name = "{MAC address}",
1163 .help = "standard MAC address notation",
1164 .call = parse_mac_addr,
1168 .name = "{IPv4 address}",
1169 .type = "IPV4 ADDRESS",
1170 .help = "standard IPv4 address notation",
1171 .call = parse_ipv4_addr,
1175 .name = "{IPv6 address}",
1176 .type = "IPV6 ADDRESS",
1177 .help = "standard IPv6 address notation",
1178 .call = parse_ipv6_addr,
1182 .name = "{rule id}",
1184 .help = "rule identifier",
1186 .comp = comp_rule_id,
1189 .name = "{port_id}",
1191 .help = "port identifier",
1196 .name = "{group_id}",
1198 .help = "group identifier",
1202 [PRIORITY_LEVEL] = {
1205 .help = "priority level",
1209 /* Top-level command. */
1212 .type = "{command} {port_id} [{arg} [...]]",
1213 .help = "manage ingress/egress flow rules",
1214 .next = NEXT(NEXT_ENTRY
1224 /* Sub-level commands. */
1227 .help = "check whether a flow rule can be created",
1228 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1229 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1234 .help = "create a flow rule",
1235 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1236 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1241 .help = "destroy specific flow rules",
1242 .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
1243 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1244 .call = parse_destroy,
1248 .help = "destroy all flow rules",
1249 .next = NEXT(NEXT_ENTRY(PORT_ID)),
1250 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1251 .call = parse_flush,
1255 .help = "query an existing flow rule",
1256 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
1257 NEXT_ENTRY(RULE_ID),
1258 NEXT_ENTRY(PORT_ID)),
1259 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
1260 ARGS_ENTRY(struct buffer, args.query.rule),
1261 ARGS_ENTRY(struct buffer, port)),
1262 .call = parse_query,
1266 .help = "list existing flow rules",
1267 .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
1268 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1273 .help = "restrict ingress traffic to the defined flow rules",
1274 .next = NEXT(NEXT_ENTRY(BOOLEAN),
1275 NEXT_ENTRY(PORT_ID)),
1276 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
1277 ARGS_ENTRY(struct buffer, port)),
1278 .call = parse_isolate,
1280 /* Destroy arguments. */
1283 .help = "specify a rule identifier",
1284 .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
1285 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
1286 .call = parse_destroy,
1288 /* Query arguments. */
1292 .help = "action to query, must be part of the rule",
1293 .call = parse_action,
1294 .comp = comp_action,
1296 /* List arguments. */
1299 .help = "specify a group",
1300 .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
1301 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
1304 /* Validate/create attributes. */
1307 .help = "specify a group",
1308 .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
1309 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
1314 .help = "specify a priority level",
1315 .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
1316 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
1321 .help = "affect rule to ingress",
1322 .next = NEXT(next_vc_attr),
1327 .help = "affect rule to egress",
1328 .next = NEXT(next_vc_attr),
1333 .help = "apply rule directly to endpoints found in pattern",
1334 .next = NEXT(next_vc_attr),
1337 /* Validate/create pattern. */
1340 .help = "submit a list of pattern items",
1341 .next = NEXT(next_item),
1346 .help = "match value perfectly (with full bit-mask)",
1347 .call = parse_vc_spec,
1349 [ITEM_PARAM_SPEC] = {
1351 .help = "match value according to configured bit-mask",
1352 .call = parse_vc_spec,
1354 [ITEM_PARAM_LAST] = {
1356 .help = "specify upper bound to establish a range",
1357 .call = parse_vc_spec,
1359 [ITEM_PARAM_MASK] = {
1361 .help = "specify bit-mask with relevant bits set to one",
1362 .call = parse_vc_spec,
1364 [ITEM_PARAM_PREFIX] = {
1366 .help = "generate bit-mask from a prefix length",
1367 .call = parse_vc_spec,
1371 .help = "specify next pattern item",
1372 .next = NEXT(next_item),
1376 .help = "end list of pattern items",
1377 .priv = PRIV_ITEM(END, 0),
1378 .next = NEXT(NEXT_ENTRY(ACTIONS)),
1383 .help = "no-op pattern item",
1384 .priv = PRIV_ITEM(VOID, 0),
1385 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1390 .help = "perform actions when pattern does not match",
1391 .priv = PRIV_ITEM(INVERT, 0),
1392 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1397 .help = "match any protocol for the current layer",
1398 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
1399 .next = NEXT(item_any),
1404 .help = "number of layers covered",
1405 .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
1406 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
1410 .help = "match traffic from/to the physical function",
1411 .priv = PRIV_ITEM(PF, 0),
1412 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1417 .help = "match traffic from/to a virtual function ID",
1418 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
1419 .next = NEXT(item_vf),
1425 .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
1426 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
1430 .help = "match traffic from/to a specific physical port",
1431 .priv = PRIV_ITEM(PHY_PORT,
1432 sizeof(struct rte_flow_item_phy_port)),
1433 .next = NEXT(item_phy_port),
1436 [ITEM_PHY_PORT_INDEX] = {
1438 .help = "physical port index",
1439 .next = NEXT(item_phy_port, NEXT_ENTRY(UNSIGNED), item_param),
1440 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
1444 .help = "match traffic from/to a given DPDK port ID",
1445 .priv = PRIV_ITEM(PORT_ID,
1446 sizeof(struct rte_flow_item_port_id)),
1447 .next = NEXT(item_port_id),
1450 [ITEM_PORT_ID_ID] = {
1452 .help = "DPDK port ID",
1453 .next = NEXT(item_port_id, NEXT_ENTRY(UNSIGNED), item_param),
1454 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
1458 .help = "match traffic against value set in previously matched rule",
1459 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
1460 .next = NEXT(item_mark),
1465 .help = "Integer value to match against",
1466 .next = NEXT(item_mark, NEXT_ENTRY(UNSIGNED), item_param),
1467 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
1471 .help = "match an arbitrary byte string",
1472 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
1473 .next = NEXT(item_raw),
1476 [ITEM_RAW_RELATIVE] = {
1478 .help = "look for pattern after the previous item",
1479 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1480 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1483 [ITEM_RAW_SEARCH] = {
1485 .help = "search pattern from offset (see also limit)",
1486 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1487 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1490 [ITEM_RAW_OFFSET] = {
1492 .help = "absolute or relative offset for pattern",
1493 .next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
1494 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
1496 [ITEM_RAW_LIMIT] = {
1498 .help = "search area limit for start of pattern",
1499 .next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
1500 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
1502 [ITEM_RAW_PATTERN] = {
1504 .help = "byte string to look for",
1505 .next = NEXT(item_raw,
1507 NEXT_ENTRY(ITEM_PARAM_IS,
1510 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
1511 ARGS_ENTRY(struct rte_flow_item_raw, length),
1512 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
1513 ITEM_RAW_PATTERN_SIZE)),
1517 .help = "match Ethernet header",
1518 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
1519 .next = NEXT(item_eth),
1524 .help = "destination MAC",
1525 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1526 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
1530 .help = "source MAC",
1531 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1532 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
1536 .help = "EtherType",
1537 .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
1538 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
1542 .help = "match 802.1Q/ad VLAN tag",
1543 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
1544 .next = NEXT(item_vlan),
1549 .help = "tag control information",
1550 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1551 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
1555 .help = "priority code point",
1556 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1557 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1562 .help = "drop eligible indicator",
1563 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1564 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1569 .help = "VLAN identifier",
1570 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1571 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1574 [ITEM_VLAN_INNER_TYPE] = {
1575 .name = "inner_type",
1576 .help = "inner EtherType",
1577 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1578 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
1583 .help = "match IPv4 header",
1584 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
1585 .next = NEXT(item_ipv4),
1590 .help = "type of service",
1591 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1592 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1593 hdr.type_of_service)),
1597 .help = "time to live",
1598 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1599 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1602 [ITEM_IPV4_PROTO] = {
1604 .help = "next protocol ID",
1605 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1606 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1607 hdr.next_proto_id)),
1611 .help = "source address",
1612 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1613 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1618 .help = "destination address",
1619 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1620 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1625 .help = "match IPv6 header",
1626 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
1627 .next = NEXT(item_ipv6),
1632 .help = "traffic class",
1633 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1634 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
1636 "\x0f\xf0\x00\x00")),
1638 [ITEM_IPV6_FLOW] = {
1640 .help = "flow label",
1641 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1642 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
1644 "\x00\x0f\xff\xff")),
1646 [ITEM_IPV6_PROTO] = {
1648 .help = "protocol (next header)",
1649 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1650 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1655 .help = "hop limit",
1656 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1657 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1662 .help = "source address",
1663 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1664 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1669 .help = "destination address",
1670 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1671 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1676 .help = "match ICMP header",
1677 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
1678 .next = NEXT(item_icmp),
1681 [ITEM_ICMP_TYPE] = {
1683 .help = "ICMP packet type",
1684 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1685 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1688 [ITEM_ICMP_CODE] = {
1690 .help = "ICMP packet code",
1691 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1692 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1697 .help = "match UDP header",
1698 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
1699 .next = NEXT(item_udp),
1704 .help = "UDP source port",
1705 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1706 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1711 .help = "UDP destination port",
1712 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1713 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1718 .help = "match TCP header",
1719 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
1720 .next = NEXT(item_tcp),
1725 .help = "TCP source port",
1726 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1727 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1732 .help = "TCP destination port",
1733 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1734 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1737 [ITEM_TCP_FLAGS] = {
1739 .help = "TCP flags",
1740 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1741 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1746 .help = "match SCTP header",
1747 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
1748 .next = NEXT(item_sctp),
1753 .help = "SCTP source port",
1754 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1755 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1760 .help = "SCTP destination port",
1761 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1762 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1767 .help = "validation tag",
1768 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1769 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1772 [ITEM_SCTP_CKSUM] = {
1775 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1776 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1781 .help = "match VXLAN header",
1782 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
1783 .next = NEXT(item_vxlan),
1786 [ITEM_VXLAN_VNI] = {
1788 .help = "VXLAN identifier",
1789 .next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
1790 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
1794 .help = "match E-Tag header",
1795 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
1796 .next = NEXT(item_e_tag),
1799 [ITEM_E_TAG_GRP_ECID_B] = {
1800 .name = "grp_ecid_b",
1801 .help = "GRP and E-CID base",
1802 .next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
1803 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
1809 .help = "match NVGRE header",
1810 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
1811 .next = NEXT(item_nvgre),
1814 [ITEM_NVGRE_TNI] = {
1816 .help = "virtual subnet ID",
1817 .next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
1818 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
1822 .help = "match MPLS header",
1823 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
1824 .next = NEXT(item_mpls),
1827 [ITEM_MPLS_LABEL] = {
1829 .help = "MPLS label",
1830 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
1831 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
1837 .help = "match GRE header",
1838 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
1839 .next = NEXT(item_gre),
1842 [ITEM_GRE_PROTO] = {
1844 .help = "GRE protocol type",
1845 .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
1846 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
1851 .help = "fuzzy pattern match, expect faster than default",
1852 .priv = PRIV_ITEM(FUZZY,
1853 sizeof(struct rte_flow_item_fuzzy)),
1854 .next = NEXT(item_fuzzy),
1857 [ITEM_FUZZY_THRESH] = {
1859 .help = "match accuracy threshold",
1860 .next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param),
1861 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
1866 .help = "match GTP header",
1867 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
1868 .next = NEXT(item_gtp),
1873 .help = "tunnel endpoint identifier",
1874 .next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
1875 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
1879 .help = "match GTP header",
1880 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
1881 .next = NEXT(item_gtp),
1886 .help = "match GTP header",
1887 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
1888 .next = NEXT(item_gtp),
1893 .help = "match GENEVE header",
1894 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
1895 .next = NEXT(item_geneve),
1898 [ITEM_GENEVE_VNI] = {
1900 .help = "virtual network identifier",
1901 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
1902 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
1904 [ITEM_GENEVE_PROTO] = {
1906 .help = "GENEVE protocol type",
1907 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
1908 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
1911 [ITEM_VXLAN_GPE] = {
1912 .name = "vxlan-gpe",
1913 .help = "match VXLAN-GPE header",
1914 .priv = PRIV_ITEM(VXLAN_GPE,
1915 sizeof(struct rte_flow_item_vxlan_gpe)),
1916 .next = NEXT(item_vxlan_gpe),
1919 [ITEM_VXLAN_GPE_VNI] = {
1921 .help = "VXLAN-GPE identifier",
1922 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(UNSIGNED), item_param),
1923 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
1926 [ITEM_ARP_ETH_IPV4] = {
1927 .name = "arp_eth_ipv4",
1928 .help = "match ARP header for Ethernet/IPv4",
1929 .priv = PRIV_ITEM(ARP_ETH_IPV4,
1930 sizeof(struct rte_flow_item_arp_eth_ipv4)),
1931 .next = NEXT(item_arp_eth_ipv4),
1934 [ITEM_ARP_ETH_IPV4_SHA] = {
1936 .help = "sender hardware address",
1937 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
1939 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1942 [ITEM_ARP_ETH_IPV4_SPA] = {
1944 .help = "sender IPv4 address",
1945 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
1947 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1950 [ITEM_ARP_ETH_IPV4_THA] = {
1952 .help = "target hardware address",
1953 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
1955 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1958 [ITEM_ARP_ETH_IPV4_TPA] = {
1960 .help = "target IPv4 address",
1961 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
1963 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1968 .help = "match presence of any IPv6 extension header",
1969 .priv = PRIV_ITEM(IPV6_EXT,
1970 sizeof(struct rte_flow_item_ipv6_ext)),
1971 .next = NEXT(item_ipv6_ext),
1974 [ITEM_IPV6_EXT_NEXT_HDR] = {
1976 .help = "next header",
1977 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
1978 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
1983 .help = "match any ICMPv6 header",
1984 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
1985 .next = NEXT(item_icmp6),
1988 [ITEM_ICMP6_TYPE] = {
1990 .help = "ICMPv6 type",
1991 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
1992 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
1995 [ITEM_ICMP6_CODE] = {
1997 .help = "ICMPv6 code",
1998 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
1999 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2002 [ITEM_ICMP6_ND_NS] = {
2003 .name = "icmp6_nd_ns",
2004 .help = "match ICMPv6 neighbor discovery solicitation",
2005 .priv = PRIV_ITEM(ICMP6_ND_NS,
2006 sizeof(struct rte_flow_item_icmp6_nd_ns)),
2007 .next = NEXT(item_icmp6_nd_ns),
2010 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
2011 .name = "target_addr",
2012 .help = "target address",
2013 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR),
2015 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
2018 [ITEM_ICMP6_ND_NA] = {
2019 .name = "icmp6_nd_na",
2020 .help = "match ICMPv6 neighbor discovery advertisement",
2021 .priv = PRIV_ITEM(ICMP6_ND_NA,
2022 sizeof(struct rte_flow_item_icmp6_nd_na)),
2023 .next = NEXT(item_icmp6_nd_na),
2026 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
2027 .name = "target_addr",
2028 .help = "target address",
2029 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR),
2031 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
2034 [ITEM_ICMP6_ND_OPT] = {
2035 .name = "icmp6_nd_opt",
2036 .help = "match presence of any ICMPv6 neighbor discovery"
2038 .priv = PRIV_ITEM(ICMP6_ND_OPT,
2039 sizeof(struct rte_flow_item_icmp6_nd_opt)),
2040 .next = NEXT(item_icmp6_nd_opt),
2043 [ITEM_ICMP6_ND_OPT_TYPE] = {
2045 .help = "ND option type",
2046 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED),
2048 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
2051 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
2052 .name = "icmp6_nd_opt_sla_eth",
2053 .help = "match ICMPv6 neighbor discovery source Ethernet"
2054 " link-layer address option",
2056 (ICMP6_ND_OPT_SLA_ETH,
2057 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
2058 .next = NEXT(item_icmp6_nd_opt_sla_eth),
2061 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
2063 .help = "source Ethernet LLA",
2064 .next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR),
2066 .args = ARGS(ARGS_ENTRY_HTON
2067 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
2069 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
2070 .name = "icmp6_nd_opt_tla_eth",
2071 .help = "match ICMPv6 neighbor discovery target Ethernet"
2072 " link-layer address option",
2074 (ICMP6_ND_OPT_TLA_ETH,
2075 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
2076 .next = NEXT(item_icmp6_nd_opt_tla_eth),
2079 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
2081 .help = "target Ethernet LLA",
2082 .next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR),
2084 .args = ARGS(ARGS_ENTRY_HTON
2085 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
2089 .help = "match metadata header",
2090 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
2091 .next = NEXT(item_meta),
2094 [ITEM_META_DATA] = {
2096 .help = "metadata value",
2097 .next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param_is),
2098 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_meta,
2099 data, "\xff\xff\xff\xff")),
2102 /* Validate/create actions. */
2105 .help = "submit a list of associated actions",
2106 .next = NEXT(next_action),
2111 .help = "specify next action",
2112 .next = NEXT(next_action),
2116 .help = "end list of actions",
2117 .priv = PRIV_ACTION(END, 0),
2122 .help = "no-op action",
2123 .priv = PRIV_ACTION(VOID, 0),
2124 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2127 [ACTION_PASSTHRU] = {
2129 .help = "let subsequent rule process matched packets",
2130 .priv = PRIV_ACTION(PASSTHRU, 0),
2131 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2136 .help = "redirect traffic to a given group",
2137 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
2138 .next = NEXT(action_jump),
2141 [ACTION_JUMP_GROUP] = {
2143 .help = "group to redirect traffic to",
2144 .next = NEXT(action_jump, NEXT_ENTRY(UNSIGNED)),
2145 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
2146 .call = parse_vc_conf,
2150 .help = "attach 32 bit value to packets",
2151 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
2152 .next = NEXT(action_mark),
2155 [ACTION_MARK_ID] = {
2157 .help = "32 bit value to return with packets",
2158 .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
2159 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
2160 .call = parse_vc_conf,
2164 .help = "flag packets",
2165 .priv = PRIV_ACTION(FLAG, 0),
2166 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2171 .help = "assign packets to a given queue index",
2172 .priv = PRIV_ACTION(QUEUE,
2173 sizeof(struct rte_flow_action_queue)),
2174 .next = NEXT(action_queue),
2177 [ACTION_QUEUE_INDEX] = {
2179 .help = "queue index to use",
2180 .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
2181 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
2182 .call = parse_vc_conf,
2186 .help = "drop packets (note: passthru has priority)",
2187 .priv = PRIV_ACTION(DROP, 0),
2188 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2193 .help = "enable counters for this rule",
2194 .priv = PRIV_ACTION(COUNT,
2195 sizeof(struct rte_flow_action_count)),
2196 .next = NEXT(action_count),
2199 [ACTION_COUNT_ID] = {
2200 .name = "identifier",
2201 .help = "counter identifier to use",
2202 .next = NEXT(action_count, NEXT_ENTRY(UNSIGNED)),
2203 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
2204 .call = parse_vc_conf,
2206 [ACTION_COUNT_SHARED] = {
2208 .help = "shared counter",
2209 .next = NEXT(action_count, NEXT_ENTRY(BOOLEAN)),
2210 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
2212 .call = parse_vc_conf,
2216 .help = "spread packets among several queues",
2217 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
2218 .next = NEXT(action_rss),
2219 .call = parse_vc_action_rss,
2221 [ACTION_RSS_FUNC] = {
2223 .help = "RSS hash function to apply",
2224 .next = NEXT(action_rss,
2225 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
2226 ACTION_RSS_FUNC_TOEPLITZ,
2227 ACTION_RSS_FUNC_SIMPLE_XOR)),
2229 [ACTION_RSS_FUNC_DEFAULT] = {
2231 .help = "default hash function",
2232 .call = parse_vc_action_rss_func,
2234 [ACTION_RSS_FUNC_TOEPLITZ] = {
2236 .help = "Toeplitz hash function",
2237 .call = parse_vc_action_rss_func,
2239 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
2240 .name = "simple_xor",
2241 .help = "simple XOR hash function",
2242 .call = parse_vc_action_rss_func,
2244 [ACTION_RSS_LEVEL] = {
2246 .help = "encapsulation level for \"types\"",
2247 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2248 .args = ARGS(ARGS_ENTRY_ARB
2249 (offsetof(struct action_rss_data, conf) +
2250 offsetof(struct rte_flow_action_rss, level),
2251 sizeof(((struct rte_flow_action_rss *)0)->
2254 [ACTION_RSS_TYPES] = {
2256 .help = "specific RSS hash types",
2257 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
2259 [ACTION_RSS_TYPE] = {
2261 .help = "RSS hash type",
2262 .call = parse_vc_action_rss_type,
2263 .comp = comp_vc_action_rss_type,
2265 [ACTION_RSS_KEY] = {
2267 .help = "RSS hash key",
2268 .next = NEXT(action_rss, NEXT_ENTRY(STRING)),
2269 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
2271 (offsetof(struct action_rss_data, conf) +
2272 offsetof(struct rte_flow_action_rss, key_len),
2273 sizeof(((struct rte_flow_action_rss *)0)->
2275 ARGS_ENTRY(struct action_rss_data, key)),
2277 [ACTION_RSS_KEY_LEN] = {
2279 .help = "RSS hash key length in bytes",
2280 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2281 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
2282 (offsetof(struct action_rss_data, conf) +
2283 offsetof(struct rte_flow_action_rss, key_len),
2284 sizeof(((struct rte_flow_action_rss *)0)->
2287 RSS_HASH_KEY_LENGTH)),
2289 [ACTION_RSS_QUEUES] = {
2291 .help = "queue indices to use",
2292 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
2293 .call = parse_vc_conf,
2295 [ACTION_RSS_QUEUE] = {
2297 .help = "queue index",
2298 .call = parse_vc_action_rss_queue,
2299 .comp = comp_vc_action_rss_queue,
2303 .help = "direct traffic to physical function",
2304 .priv = PRIV_ACTION(PF, 0),
2305 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2310 .help = "direct traffic to a virtual function ID",
2311 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
2312 .next = NEXT(action_vf),
2315 [ACTION_VF_ORIGINAL] = {
2317 .help = "use original VF ID if possible",
2318 .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
2319 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
2321 .call = parse_vc_conf,
2326 .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
2327 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
2328 .call = parse_vc_conf,
2330 [ACTION_PHY_PORT] = {
2332 .help = "direct packets to physical port index",
2333 .priv = PRIV_ACTION(PHY_PORT,
2334 sizeof(struct rte_flow_action_phy_port)),
2335 .next = NEXT(action_phy_port),
2338 [ACTION_PHY_PORT_ORIGINAL] = {
2340 .help = "use original port index if possible",
2341 .next = NEXT(action_phy_port, NEXT_ENTRY(BOOLEAN)),
2342 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
2344 .call = parse_vc_conf,
2346 [ACTION_PHY_PORT_INDEX] = {
2348 .help = "physical port index",
2349 .next = NEXT(action_phy_port, NEXT_ENTRY(UNSIGNED)),
2350 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
2352 .call = parse_vc_conf,
2354 [ACTION_PORT_ID] = {
2356 .help = "direct matching traffic to a given DPDK port ID",
2357 .priv = PRIV_ACTION(PORT_ID,
2358 sizeof(struct rte_flow_action_port_id)),
2359 .next = NEXT(action_port_id),
2362 [ACTION_PORT_ID_ORIGINAL] = {
2364 .help = "use original DPDK port ID if possible",
2365 .next = NEXT(action_port_id, NEXT_ENTRY(BOOLEAN)),
2366 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
2368 .call = parse_vc_conf,
2370 [ACTION_PORT_ID_ID] = {
2372 .help = "DPDK port ID",
2373 .next = NEXT(action_port_id, NEXT_ENTRY(UNSIGNED)),
2374 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
2375 .call = parse_vc_conf,
2379 .help = "meter the directed packets at given id",
2380 .priv = PRIV_ACTION(METER,
2381 sizeof(struct rte_flow_action_meter)),
2382 .next = NEXT(action_meter),
2385 [ACTION_METER_ID] = {
2387 .help = "meter id to use",
2388 .next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
2389 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
2390 .call = parse_vc_conf,
2392 [ACTION_OF_SET_MPLS_TTL] = {
2393 .name = "of_set_mpls_ttl",
2394 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
2397 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
2398 .next = NEXT(action_of_set_mpls_ttl),
2401 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
2404 .next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)),
2405 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
2407 .call = parse_vc_conf,
2409 [ACTION_OF_DEC_MPLS_TTL] = {
2410 .name = "of_dec_mpls_ttl",
2411 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
2412 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
2413 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2416 [ACTION_OF_SET_NW_TTL] = {
2417 .name = "of_set_nw_ttl",
2418 .help = "OpenFlow's OFPAT_SET_NW_TTL",
2421 sizeof(struct rte_flow_action_of_set_nw_ttl)),
2422 .next = NEXT(action_of_set_nw_ttl),
2425 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
2428 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)),
2429 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
2431 .call = parse_vc_conf,
2433 [ACTION_OF_DEC_NW_TTL] = {
2434 .name = "of_dec_nw_ttl",
2435 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
2436 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
2437 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2440 [ACTION_OF_COPY_TTL_OUT] = {
2441 .name = "of_copy_ttl_out",
2442 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
2443 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
2444 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2447 [ACTION_OF_COPY_TTL_IN] = {
2448 .name = "of_copy_ttl_in",
2449 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
2450 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
2451 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2454 [ACTION_OF_POP_VLAN] = {
2455 .name = "of_pop_vlan",
2456 .help = "OpenFlow's OFPAT_POP_VLAN",
2457 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
2458 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2461 [ACTION_OF_PUSH_VLAN] = {
2462 .name = "of_push_vlan",
2463 .help = "OpenFlow's OFPAT_PUSH_VLAN",
2466 sizeof(struct rte_flow_action_of_push_vlan)),
2467 .next = NEXT(action_of_push_vlan),
2470 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
2471 .name = "ethertype",
2472 .help = "EtherType",
2473 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)),
2474 .args = ARGS(ARGS_ENTRY_HTON
2475 (struct rte_flow_action_of_push_vlan,
2477 .call = parse_vc_conf,
2479 [ACTION_OF_SET_VLAN_VID] = {
2480 .name = "of_set_vlan_vid",
2481 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
2484 sizeof(struct rte_flow_action_of_set_vlan_vid)),
2485 .next = NEXT(action_of_set_vlan_vid),
2488 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
2491 .next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)),
2492 .args = ARGS(ARGS_ENTRY_HTON
2493 (struct rte_flow_action_of_set_vlan_vid,
2495 .call = parse_vc_conf,
2497 [ACTION_OF_SET_VLAN_PCP] = {
2498 .name = "of_set_vlan_pcp",
2499 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
2502 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
2503 .next = NEXT(action_of_set_vlan_pcp),
2506 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
2508 .help = "VLAN priority",
2509 .next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)),
2510 .args = ARGS(ARGS_ENTRY_HTON
2511 (struct rte_flow_action_of_set_vlan_pcp,
2513 .call = parse_vc_conf,
2515 [ACTION_OF_POP_MPLS] = {
2516 .name = "of_pop_mpls",
2517 .help = "OpenFlow's OFPAT_POP_MPLS",
2518 .priv = PRIV_ACTION(OF_POP_MPLS,
2519 sizeof(struct rte_flow_action_of_pop_mpls)),
2520 .next = NEXT(action_of_pop_mpls),
2523 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
2524 .name = "ethertype",
2525 .help = "EtherType",
2526 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)),
2527 .args = ARGS(ARGS_ENTRY_HTON
2528 (struct rte_flow_action_of_pop_mpls,
2530 .call = parse_vc_conf,
2532 [ACTION_OF_PUSH_MPLS] = {
2533 .name = "of_push_mpls",
2534 .help = "OpenFlow's OFPAT_PUSH_MPLS",
2537 sizeof(struct rte_flow_action_of_push_mpls)),
2538 .next = NEXT(action_of_push_mpls),
2541 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
2542 .name = "ethertype",
2543 .help = "EtherType",
2544 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)),
2545 .args = ARGS(ARGS_ENTRY_HTON
2546 (struct rte_flow_action_of_push_mpls,
2548 .call = parse_vc_conf,
2550 [ACTION_VXLAN_ENCAP] = {
2551 .name = "vxlan_encap",
2552 .help = "VXLAN encapsulation, uses configuration set by \"set"
2554 .priv = PRIV_ACTION(VXLAN_ENCAP,
2555 sizeof(struct action_vxlan_encap_data)),
2556 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2557 .call = parse_vc_action_vxlan_encap,
2559 [ACTION_VXLAN_DECAP] = {
2560 .name = "vxlan_decap",
2561 .help = "Performs a decapsulation action by stripping all"
2562 " headers of the VXLAN tunnel network overlay from the"
2564 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
2565 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2568 [ACTION_NVGRE_ENCAP] = {
2569 .name = "nvgre_encap",
2570 .help = "NVGRE encapsulation, uses configuration set by \"set"
2572 .priv = PRIV_ACTION(NVGRE_ENCAP,
2573 sizeof(struct action_nvgre_encap_data)),
2574 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2575 .call = parse_vc_action_nvgre_encap,
2577 [ACTION_NVGRE_DECAP] = {
2578 .name = "nvgre_decap",
2579 .help = "Performs a decapsulation action by stripping all"
2580 " headers of the NVGRE tunnel network overlay from the"
2582 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
2583 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2586 [ACTION_SET_IPV4_SRC] = {
2587 .name = "set_ipv4_src",
2588 .help = "Set a new IPv4 source address in the outermost"
2590 .priv = PRIV_ACTION(SET_IPV4_SRC,
2591 sizeof(struct rte_flow_action_set_ipv4)),
2592 .next = NEXT(action_set_ipv4_src),
2595 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
2596 .name = "ipv4_addr",
2597 .help = "new IPv4 source address to set",
2598 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(IPV4_ADDR)),
2599 .args = ARGS(ARGS_ENTRY_HTON
2600 (struct rte_flow_action_set_ipv4, ipv4_addr)),
2601 .call = parse_vc_conf,
2603 [ACTION_SET_IPV4_DST] = {
2604 .name = "set_ipv4_dst",
2605 .help = "Set a new IPv4 destination address in the outermost"
2607 .priv = PRIV_ACTION(SET_IPV4_DST,
2608 sizeof(struct rte_flow_action_set_ipv4)),
2609 .next = NEXT(action_set_ipv4_dst),
2612 [ACTION_SET_IPV4_DST_IPV4_DST] = {
2613 .name = "ipv4_addr",
2614 .help = "new IPv4 destination address to set",
2615 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(IPV4_ADDR)),
2616 .args = ARGS(ARGS_ENTRY_HTON
2617 (struct rte_flow_action_set_ipv4, ipv4_addr)),
2618 .call = parse_vc_conf,
2620 [ACTION_SET_IPV6_SRC] = {
2621 .name = "set_ipv6_src",
2622 .help = "Set a new IPv6 source address in the outermost"
2624 .priv = PRIV_ACTION(SET_IPV6_SRC,
2625 sizeof(struct rte_flow_action_set_ipv6)),
2626 .next = NEXT(action_set_ipv6_src),
2629 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
2630 .name = "ipv6_addr",
2631 .help = "new IPv6 source address to set",
2632 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(IPV6_ADDR)),
2633 .args = ARGS(ARGS_ENTRY_HTON
2634 (struct rte_flow_action_set_ipv6, ipv6_addr)),
2635 .call = parse_vc_conf,
2637 [ACTION_SET_IPV6_DST] = {
2638 .name = "set_ipv6_dst",
2639 .help = "Set a new IPv6 destination address in the outermost"
2641 .priv = PRIV_ACTION(SET_IPV6_DST,
2642 sizeof(struct rte_flow_action_set_ipv6)),
2643 .next = NEXT(action_set_ipv6_dst),
2646 [ACTION_SET_IPV6_DST_IPV6_DST] = {
2647 .name = "ipv6_addr",
2648 .help = "new IPv6 destination address to set",
2649 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(IPV6_ADDR)),
2650 .args = ARGS(ARGS_ENTRY_HTON
2651 (struct rte_flow_action_set_ipv6, ipv6_addr)),
2652 .call = parse_vc_conf,
2654 [ACTION_SET_TP_SRC] = {
2655 .name = "set_tp_src",
2656 .help = "set a new source port number in the outermost"
2658 .priv = PRIV_ACTION(SET_TP_SRC,
2659 sizeof(struct rte_flow_action_set_tp)),
2660 .next = NEXT(action_set_tp_src),
2663 [ACTION_SET_TP_SRC_TP_SRC] = {
2665 .help = "new source port number to set",
2666 .next = NEXT(action_set_tp_src, NEXT_ENTRY(UNSIGNED)),
2667 .args = ARGS(ARGS_ENTRY_HTON
2668 (struct rte_flow_action_set_tp, port)),
2669 .call = parse_vc_conf,
2671 [ACTION_SET_TP_DST] = {
2672 .name = "set_tp_dst",
2673 .help = "set a new destination port number in the outermost"
2675 .priv = PRIV_ACTION(SET_TP_DST,
2676 sizeof(struct rte_flow_action_set_tp)),
2677 .next = NEXT(action_set_tp_dst),
2680 [ACTION_SET_TP_DST_TP_DST] = {
2682 .help = "new destination port number to set",
2683 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(UNSIGNED)),
2684 .args = ARGS(ARGS_ENTRY_HTON
2685 (struct rte_flow_action_set_tp, port)),
2686 .call = parse_vc_conf,
2688 [ACTION_MAC_SWAP] = {
2690 .help = "Swap the source and destination MAC addresses"
2691 " in the outermost Ethernet header",
2692 .priv = PRIV_ACTION(MAC_SWAP, 0),
2693 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2696 [ACTION_DEC_TTL] = {
2698 .help = "decrease network TTL if available",
2699 .priv = PRIV_ACTION(DEC_TTL, 0),
2700 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2703 [ACTION_SET_TTL] = {
2705 .help = "set ttl value",
2706 .priv = PRIV_ACTION(SET_TTL,
2707 sizeof(struct rte_flow_action_set_ttl)),
2708 .next = NEXT(action_set_ttl),
2711 [ACTION_SET_TTL_TTL] = {
2712 .name = "ttl_value",
2713 .help = "new ttl value to set",
2714 .next = NEXT(action_set_ttl, NEXT_ENTRY(UNSIGNED)),
2715 .args = ARGS(ARGS_ENTRY_HTON
2716 (struct rte_flow_action_set_ttl, ttl_value)),
2717 .call = parse_vc_conf,
2719 [ACTION_SET_MAC_SRC] = {
2720 .name = "set_mac_src",
2721 .help = "set source mac address",
2722 .priv = PRIV_ACTION(SET_MAC_SRC,
2723 sizeof(struct rte_flow_action_set_mac)),
2724 .next = NEXT(action_set_mac_src),
2727 [ACTION_SET_MAC_SRC_MAC_SRC] = {
2729 .help = "new source mac address",
2730 .next = NEXT(action_set_mac_src, NEXT_ENTRY(MAC_ADDR)),
2731 .args = ARGS(ARGS_ENTRY_HTON
2732 (struct rte_flow_action_set_mac, mac_addr)),
2733 .call = parse_vc_conf,
2735 [ACTION_SET_MAC_DST] = {
2736 .name = "set_mac_dst",
2737 .help = "set destination mac address",
2738 .priv = PRIV_ACTION(SET_MAC_DST,
2739 sizeof(struct rte_flow_action_set_mac)),
2740 .next = NEXT(action_set_mac_dst),
2743 [ACTION_SET_MAC_DST_MAC_DST] = {
2745 .help = "new destination mac address to set",
2746 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(MAC_ADDR)),
2747 .args = ARGS(ARGS_ENTRY_HTON
2748 (struct rte_flow_action_set_mac, mac_addr)),
2749 .call = parse_vc_conf,
2753 /** Remove and return last entry from argument stack. */
2754 static const struct arg *
2755 pop_args(struct context *ctx)
2757 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
2760 /** Add entry on top of the argument stack. */
2762 push_args(struct context *ctx, const struct arg *arg)
2764 if (ctx->args_num == CTX_STACK_SIZE)
2766 ctx->args[ctx->args_num++] = arg;
2770 /** Spread value into buffer according to bit-mask. */
2772 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
2774 uint32_t i = arg->size;
2782 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2791 unsigned int shift = 0;
2792 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
2794 for (shift = 0; arg->mask[i] >> shift; ++shift) {
2795 if (!(arg->mask[i] & (1 << shift)))
2800 *buf &= ~(1 << shift);
2801 *buf |= (val & 1) << shift;
2809 /** Compare a string with a partial one of a given length. */
2811 strcmp_partial(const char *full, const char *partial, size_t partial_len)
2813 int r = strncmp(full, partial, partial_len);
2817 if (strlen(full) <= partial_len)
2819 return full[partial_len];
2823 * Parse a prefix length and generate a bit-mask.
2825 * Last argument (ctx->args) is retrieved to determine mask size, storage
2826 * location and whether the result must use network byte ordering.
2829 parse_prefix(struct context *ctx, const struct token *token,
2830 const char *str, unsigned int len,
2831 void *buf, unsigned int size)
2833 const struct arg *arg = pop_args(ctx);
2834 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
2841 /* Argument is expected. */
2845 u = strtoumax(str, &end, 0);
2846 if (errno || (size_t)(end - str) != len)
2851 extra = arg_entry_bf_fill(NULL, 0, arg);
2860 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
2861 !arg_entry_bf_fill(ctx->objmask, -1, arg))
2868 if (bytes > size || bytes + !!extra > size)
2872 buf = (uint8_t *)ctx->object + arg->offset;
2873 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2875 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
2876 memset(buf, 0x00, size - bytes);
2878 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
2882 memset(buf, 0xff, bytes);
2883 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
2885 ((uint8_t *)buf)[bytes] = conv[extra];
2888 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2891 push_args(ctx, arg);
2895 /** Default parsing function for token name matching. */
2897 parse_default(struct context *ctx, const struct token *token,
2898 const char *str, unsigned int len,
2899 void *buf, unsigned int size)
2904 if (strcmp_partial(token->name, str, len))
2909 /** Parse flow command, initialize output buffer for subsequent tokens. */
2911 parse_init(struct context *ctx, const struct token *token,
2912 const char *str, unsigned int len,
2913 void *buf, unsigned int size)
2915 struct buffer *out = buf;
2917 /* Token name must match. */
2918 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2920 /* Nothing else to do if there is no buffer. */
2923 /* Make sure buffer is large enough. */
2924 if (size < sizeof(*out))
2926 /* Initialize buffer. */
2927 memset(out, 0x00, sizeof(*out));
2928 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
2931 ctx->objmask = NULL;
2935 /** Parse tokens for validate/create commands. */
2937 parse_vc(struct context *ctx, const struct token *token,
2938 const char *str, unsigned int len,
2939 void *buf, unsigned int size)
2941 struct buffer *out = buf;
2945 /* Token name must match. */
2946 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2948 /* Nothing else to do if there is no buffer. */
2951 if (!out->command) {
2952 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
2954 if (sizeof(*out) > size)
2956 out->command = ctx->curr;
2959 ctx->objmask = NULL;
2960 out->args.vc.data = (uint8_t *)out + size;
2964 ctx->object = &out->args.vc.attr;
2965 ctx->objmask = NULL;
2966 switch (ctx->curr) {
2971 out->args.vc.attr.ingress = 1;
2974 out->args.vc.attr.egress = 1;
2977 out->args.vc.attr.transfer = 1;
2980 out->args.vc.pattern =
2981 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
2983 ctx->object = out->args.vc.pattern;
2984 ctx->objmask = NULL;
2987 out->args.vc.actions =
2988 (void *)RTE_ALIGN_CEIL((uintptr_t)
2989 (out->args.vc.pattern +
2990 out->args.vc.pattern_n),
2992 ctx->object = out->args.vc.actions;
2993 ctx->objmask = NULL;
3000 if (!out->args.vc.actions) {
3001 const struct parse_item_priv *priv = token->priv;
3002 struct rte_flow_item *item =
3003 out->args.vc.pattern + out->args.vc.pattern_n;
3005 data_size = priv->size * 3; /* spec, last, mask */
3006 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3007 (out->args.vc.data - data_size),
3009 if ((uint8_t *)item + sizeof(*item) > data)
3011 *item = (struct rte_flow_item){
3014 ++out->args.vc.pattern_n;
3016 ctx->objmask = NULL;
3018 const struct parse_action_priv *priv = token->priv;
3019 struct rte_flow_action *action =
3020 out->args.vc.actions + out->args.vc.actions_n;
3022 data_size = priv->size; /* configuration */
3023 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3024 (out->args.vc.data - data_size),
3026 if ((uint8_t *)action + sizeof(*action) > data)
3028 *action = (struct rte_flow_action){
3030 .conf = data_size ? data : NULL,
3032 ++out->args.vc.actions_n;
3033 ctx->object = action;
3034 ctx->objmask = NULL;
3036 memset(data, 0, data_size);
3037 out->args.vc.data = data;
3038 ctx->objdata = data_size;
3042 /** Parse pattern item parameter type. */
3044 parse_vc_spec(struct context *ctx, const struct token *token,
3045 const char *str, unsigned int len,
3046 void *buf, unsigned int size)
3048 struct buffer *out = buf;
3049 struct rte_flow_item *item;
3055 /* Token name must match. */
3056 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3058 /* Parse parameter types. */
3059 switch (ctx->curr) {
3060 static const enum index prefix[] = NEXT_ENTRY(PREFIX);
3066 case ITEM_PARAM_SPEC:
3069 case ITEM_PARAM_LAST:
3072 case ITEM_PARAM_PREFIX:
3073 /* Modify next token to expect a prefix. */
3074 if (ctx->next_num < 2)
3076 ctx->next[ctx->next_num - 2] = prefix;
3078 case ITEM_PARAM_MASK:
3084 /* Nothing else to do if there is no buffer. */
3087 if (!out->args.vc.pattern_n)
3089 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
3090 data_size = ctx->objdata / 3; /* spec, last, mask */
3091 /* Point to selected object. */
3092 ctx->object = out->args.vc.data + (data_size * index);
3094 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
3095 item->mask = ctx->objmask;
3097 ctx->objmask = NULL;
3098 /* Update relevant item pointer. */
3099 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
3104 /** Parse action configuration field. */
3106 parse_vc_conf(struct context *ctx, const struct token *token,
3107 const char *str, unsigned int len,
3108 void *buf, unsigned int size)
3110 struct buffer *out = buf;
3113 /* Token name must match. */
3114 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3116 /* Nothing else to do if there is no buffer. */
3119 /* Point to selected object. */
3120 ctx->object = out->args.vc.data;
3121 ctx->objmask = NULL;
3125 /** Parse RSS action. */
3127 parse_vc_action_rss(struct context *ctx, const struct token *token,
3128 const char *str, unsigned int len,
3129 void *buf, unsigned int size)
3131 struct buffer *out = buf;
3132 struct rte_flow_action *action;
3133 struct action_rss_data *action_rss_data;
3137 ret = parse_vc(ctx, token, str, len, buf, size);
3140 /* Nothing else to do if there is no buffer. */
3143 if (!out->args.vc.actions_n)
3145 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3146 /* Point to selected object. */
3147 ctx->object = out->args.vc.data;
3148 ctx->objmask = NULL;
3149 /* Set up default configuration. */
3150 action_rss_data = ctx->object;
3151 *action_rss_data = (struct action_rss_data){
3152 .conf = (struct rte_flow_action_rss){
3153 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
3156 .key_len = sizeof(action_rss_data->key),
3157 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
3158 .key = action_rss_data->key,
3159 .queue = action_rss_data->queue,
3161 .key = "testpmd's default RSS hash key, "
3162 "override it for better balancing",
3165 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
3166 action_rss_data->queue[i] = i;
3167 if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
3168 ctx->port != (portid_t)RTE_PORT_ALL) {
3169 struct rte_eth_dev_info info;
3171 rte_eth_dev_info_get(ctx->port, &info);
3172 action_rss_data->conf.key_len =
3173 RTE_MIN(sizeof(action_rss_data->key),
3174 info.hash_key_size);
3176 action->conf = &action_rss_data->conf;
3181 * Parse func field for RSS action.
3183 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
3184 * ACTION_RSS_FUNC_* index that called this function.
3187 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
3188 const char *str, unsigned int len,
3189 void *buf, unsigned int size)
3191 struct action_rss_data *action_rss_data;
3192 enum rte_eth_hash_function func;
3196 /* Token name must match. */
3197 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3199 switch (ctx->curr) {
3200 case ACTION_RSS_FUNC_DEFAULT:
3201 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
3203 case ACTION_RSS_FUNC_TOEPLITZ:
3204 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
3206 case ACTION_RSS_FUNC_SIMPLE_XOR:
3207 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
3214 action_rss_data = ctx->object;
3215 action_rss_data->conf.func = func;
3220 * Parse type field for RSS action.
3222 * Valid tokens are type field names and the "end" token.
3225 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
3226 const char *str, unsigned int len,
3227 void *buf, unsigned int size)
3229 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
3230 struct action_rss_data *action_rss_data;
3236 if (ctx->curr != ACTION_RSS_TYPE)
3238 if (!(ctx->objdata >> 16) && ctx->object) {
3239 action_rss_data = ctx->object;
3240 action_rss_data->conf.types = 0;
3242 if (!strcmp_partial("end", str, len)) {
3243 ctx->objdata &= 0xffff;
3246 for (i = 0; rss_type_table[i].str; ++i)
3247 if (!strcmp_partial(rss_type_table[i].str, str, len))
3249 if (!rss_type_table[i].str)
3251 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
3253 if (ctx->next_num == RTE_DIM(ctx->next))
3255 ctx->next[ctx->next_num++] = next;
3258 action_rss_data = ctx->object;
3259 action_rss_data->conf.types |= rss_type_table[i].rss_type;
3264 * Parse queue field for RSS action.
3266 * Valid tokens are queue indices and the "end" token.
3269 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
3270 const char *str, unsigned int len,
3271 void *buf, unsigned int size)
3273 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
3274 struct action_rss_data *action_rss_data;
3281 if (ctx->curr != ACTION_RSS_QUEUE)
3283 i = ctx->objdata >> 16;
3284 if (!strcmp_partial("end", str, len)) {
3285 ctx->objdata &= 0xffff;
3288 if (i >= ACTION_RSS_QUEUE_NUM)
3291 ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
3292 i * sizeof(action_rss_data->queue[i]),
3293 sizeof(action_rss_data->queue[i]))))
3295 ret = parse_int(ctx, token, str, len, NULL, 0);
3301 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
3303 if (ctx->next_num == RTE_DIM(ctx->next))
3305 ctx->next[ctx->next_num++] = next;
3309 action_rss_data = ctx->object;
3310 action_rss_data->conf.queue_num = i;
3311 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
3315 /** Parse VXLAN encap action. */
3317 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
3318 const char *str, unsigned int len,
3319 void *buf, unsigned int size)
3321 struct buffer *out = buf;
3322 struct rte_flow_action *action;
3323 struct action_vxlan_encap_data *action_vxlan_encap_data;
3326 ret = parse_vc(ctx, token, str, len, buf, size);
3329 /* Nothing else to do if there is no buffer. */
3332 if (!out->args.vc.actions_n)
3334 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3335 /* Point to selected object. */
3336 ctx->object = out->args.vc.data;
3337 ctx->objmask = NULL;
3338 /* Set up default configuration. */
3339 action_vxlan_encap_data = ctx->object;
3340 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
3341 .conf = (struct rte_flow_action_vxlan_encap){
3342 .definition = action_vxlan_encap_data->items,
3346 .type = RTE_FLOW_ITEM_TYPE_ETH,
3347 .spec = &action_vxlan_encap_data->item_eth,
3348 .mask = &rte_flow_item_eth_mask,
3351 .type = RTE_FLOW_ITEM_TYPE_VLAN,
3352 .spec = &action_vxlan_encap_data->item_vlan,
3353 .mask = &rte_flow_item_vlan_mask,
3356 .type = RTE_FLOW_ITEM_TYPE_IPV4,
3357 .spec = &action_vxlan_encap_data->item_ipv4,
3358 .mask = &rte_flow_item_ipv4_mask,
3361 .type = RTE_FLOW_ITEM_TYPE_UDP,
3362 .spec = &action_vxlan_encap_data->item_udp,
3363 .mask = &rte_flow_item_udp_mask,
3366 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
3367 .spec = &action_vxlan_encap_data->item_vxlan,
3368 .mask = &rte_flow_item_vxlan_mask,
3371 .type = RTE_FLOW_ITEM_TYPE_END,
3376 .tci = vxlan_encap_conf.vlan_tci,
3380 .src_addr = vxlan_encap_conf.ipv4_src,
3381 .dst_addr = vxlan_encap_conf.ipv4_dst,
3384 .src_port = vxlan_encap_conf.udp_src,
3385 .dst_port = vxlan_encap_conf.udp_dst,
3387 .item_vxlan.flags = 0,
3389 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
3390 vxlan_encap_conf.eth_dst, ETHER_ADDR_LEN);
3391 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
3392 vxlan_encap_conf.eth_src, ETHER_ADDR_LEN);
3393 if (!vxlan_encap_conf.select_ipv4) {
3394 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
3395 &vxlan_encap_conf.ipv6_src,
3396 sizeof(vxlan_encap_conf.ipv6_src));
3397 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
3398 &vxlan_encap_conf.ipv6_dst,
3399 sizeof(vxlan_encap_conf.ipv6_dst));
3400 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
3401 .type = RTE_FLOW_ITEM_TYPE_IPV6,
3402 .spec = &action_vxlan_encap_data->item_ipv6,
3403 .mask = &rte_flow_item_ipv6_mask,
3406 if (!vxlan_encap_conf.select_vlan)
3407 action_vxlan_encap_data->items[1].type =
3408 RTE_FLOW_ITEM_TYPE_VOID;
3409 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
3410 RTE_DIM(vxlan_encap_conf.vni));
3411 action->conf = &action_vxlan_encap_data->conf;
3415 /** Parse NVGRE encap action. */
3417 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
3418 const char *str, unsigned int len,
3419 void *buf, unsigned int size)
3421 struct buffer *out = buf;
3422 struct rte_flow_action *action;
3423 struct action_nvgre_encap_data *action_nvgre_encap_data;
3426 ret = parse_vc(ctx, token, str, len, buf, size);
3429 /* Nothing else to do if there is no buffer. */
3432 if (!out->args.vc.actions_n)
3434 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3435 /* Point to selected object. */
3436 ctx->object = out->args.vc.data;
3437 ctx->objmask = NULL;
3438 /* Set up default configuration. */
3439 action_nvgre_encap_data = ctx->object;
3440 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
3441 .conf = (struct rte_flow_action_nvgre_encap){
3442 .definition = action_nvgre_encap_data->items,
3446 .type = RTE_FLOW_ITEM_TYPE_ETH,
3447 .spec = &action_nvgre_encap_data->item_eth,
3448 .mask = &rte_flow_item_eth_mask,
3451 .type = RTE_FLOW_ITEM_TYPE_VLAN,
3452 .spec = &action_nvgre_encap_data->item_vlan,
3453 .mask = &rte_flow_item_vlan_mask,
3456 .type = RTE_FLOW_ITEM_TYPE_IPV4,
3457 .spec = &action_nvgre_encap_data->item_ipv4,
3458 .mask = &rte_flow_item_ipv4_mask,
3461 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
3462 .spec = &action_nvgre_encap_data->item_nvgre,
3463 .mask = &rte_flow_item_nvgre_mask,
3466 .type = RTE_FLOW_ITEM_TYPE_END,
3471 .tci = nvgre_encap_conf.vlan_tci,
3475 .src_addr = nvgre_encap_conf.ipv4_src,
3476 .dst_addr = nvgre_encap_conf.ipv4_dst,
3478 .item_nvgre.flow_id = 0,
3480 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
3481 nvgre_encap_conf.eth_dst, ETHER_ADDR_LEN);
3482 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
3483 nvgre_encap_conf.eth_src, ETHER_ADDR_LEN);
3484 if (!nvgre_encap_conf.select_ipv4) {
3485 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
3486 &nvgre_encap_conf.ipv6_src,
3487 sizeof(nvgre_encap_conf.ipv6_src));
3488 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
3489 &nvgre_encap_conf.ipv6_dst,
3490 sizeof(nvgre_encap_conf.ipv6_dst));
3491 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
3492 .type = RTE_FLOW_ITEM_TYPE_IPV6,
3493 .spec = &action_nvgre_encap_data->item_ipv6,
3494 .mask = &rte_flow_item_ipv6_mask,
3497 if (!nvgre_encap_conf.select_vlan)
3498 action_nvgre_encap_data->items[1].type =
3499 RTE_FLOW_ITEM_TYPE_VOID;
3500 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
3501 RTE_DIM(nvgre_encap_conf.tni));
3502 action->conf = &action_nvgre_encap_data->conf;
3506 /** Parse tokens for destroy command. */
3508 parse_destroy(struct context *ctx, const struct token *token,
3509 const char *str, unsigned int len,
3510 void *buf, unsigned int size)
3512 struct buffer *out = buf;
3514 /* Token name must match. */
3515 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3517 /* Nothing else to do if there is no buffer. */
3520 if (!out->command) {
3521 if (ctx->curr != DESTROY)
3523 if (sizeof(*out) > size)
3525 out->command = ctx->curr;
3528 ctx->objmask = NULL;
3529 out->args.destroy.rule =
3530 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
3534 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
3535 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
3538 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
3539 ctx->objmask = NULL;
3543 /** Parse tokens for flush command. */
3545 parse_flush(struct context *ctx, const struct token *token,
3546 const char *str, unsigned int len,
3547 void *buf, unsigned int size)
3549 struct buffer *out = buf;
3551 /* Token name must match. */
3552 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3554 /* Nothing else to do if there is no buffer. */
3557 if (!out->command) {
3558 if (ctx->curr != FLUSH)
3560 if (sizeof(*out) > size)
3562 out->command = ctx->curr;
3565 ctx->objmask = NULL;
3570 /** Parse tokens for query command. */
3572 parse_query(struct context *ctx, const struct token *token,
3573 const char *str, unsigned int len,
3574 void *buf, unsigned int size)
3576 struct buffer *out = buf;
3578 /* Token name must match. */
3579 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3581 /* Nothing else to do if there is no buffer. */
3584 if (!out->command) {
3585 if (ctx->curr != QUERY)
3587 if (sizeof(*out) > size)
3589 out->command = ctx->curr;
3592 ctx->objmask = NULL;
3597 /** Parse action names. */
3599 parse_action(struct context *ctx, const struct token *token,
3600 const char *str, unsigned int len,
3601 void *buf, unsigned int size)
3603 struct buffer *out = buf;
3604 const struct arg *arg = pop_args(ctx);
3608 /* Argument is expected. */
3611 /* Parse action name. */
3612 for (i = 0; next_action[i]; ++i) {
3613 const struct parse_action_priv *priv;
3615 token = &token_list[next_action[i]];
3616 if (strcmp_partial(token->name, str, len))
3622 memcpy((uint8_t *)ctx->object + arg->offset,
3628 push_args(ctx, arg);
3632 /** Parse tokens for list command. */
3634 parse_list(struct context *ctx, const struct token *token,
3635 const char *str, unsigned int len,
3636 void *buf, unsigned int size)
3638 struct buffer *out = buf;
3640 /* Token name must match. */
3641 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3643 /* Nothing else to do if there is no buffer. */
3646 if (!out->command) {
3647 if (ctx->curr != LIST)
3649 if (sizeof(*out) > size)
3651 out->command = ctx->curr;
3654 ctx->objmask = NULL;
3655 out->args.list.group =
3656 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
3660 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
3661 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
3664 ctx->object = out->args.list.group + out->args.list.group_n++;
3665 ctx->objmask = NULL;
3669 /** Parse tokens for isolate command. */
3671 parse_isolate(struct context *ctx, const struct token *token,
3672 const char *str, unsigned int len,
3673 void *buf, unsigned int size)
3675 struct buffer *out = buf;
3677 /* Token name must match. */
3678 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3680 /* Nothing else to do if there is no buffer. */
3683 if (!out->command) {
3684 if (ctx->curr != ISOLATE)
3686 if (sizeof(*out) > size)
3688 out->command = ctx->curr;
3691 ctx->objmask = NULL;
3697 * Parse signed/unsigned integers 8 to 64-bit long.
3699 * Last argument (ctx->args) is retrieved to determine integer type and
3703 parse_int(struct context *ctx, const struct token *token,
3704 const char *str, unsigned int len,
3705 void *buf, unsigned int size)
3707 const struct arg *arg = pop_args(ctx);
3712 /* Argument is expected. */
3717 (uintmax_t)strtoimax(str, &end, 0) :
3718 strtoumax(str, &end, 0);
3719 if (errno || (size_t)(end - str) != len)
3722 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
3723 (intmax_t)u > (intmax_t)arg->max)) ||
3724 (!arg->sign && (u < arg->min || u > arg->max))))
3729 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
3730 !arg_entry_bf_fill(ctx->objmask, -1, arg))
3734 buf = (uint8_t *)ctx->object + arg->offset;
3738 case sizeof(uint8_t):
3739 *(uint8_t *)buf = u;
3741 case sizeof(uint16_t):
3742 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
3744 case sizeof(uint8_t [3]):
3745 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3747 ((uint8_t *)buf)[0] = u;
3748 ((uint8_t *)buf)[1] = u >> 8;
3749 ((uint8_t *)buf)[2] = u >> 16;
3753 ((uint8_t *)buf)[0] = u >> 16;
3754 ((uint8_t *)buf)[1] = u >> 8;
3755 ((uint8_t *)buf)[2] = u;
3757 case sizeof(uint32_t):
3758 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
3760 case sizeof(uint64_t):
3761 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
3766 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
3768 buf = (uint8_t *)ctx->objmask + arg->offset;
3773 push_args(ctx, arg);
3780 * Three arguments (ctx->args) are retrieved from the stack to store data,
3781 * its actual length and address (in that order).
3784 parse_string(struct context *ctx, const struct token *token,
3785 const char *str, unsigned int len,
3786 void *buf, unsigned int size)
3788 const struct arg *arg_data = pop_args(ctx);
3789 const struct arg *arg_len = pop_args(ctx);
3790 const struct arg *arg_addr = pop_args(ctx);
3791 char tmp[16]; /* Ought to be enough. */
3794 /* Arguments are expected. */
3798 push_args(ctx, arg_data);
3802 push_args(ctx, arg_len);
3803 push_args(ctx, arg_data);
3806 size = arg_data->size;
3807 /* Bit-mask fill is not supported. */
3808 if (arg_data->mask || size < len)
3812 /* Let parse_int() fill length information first. */
3813 ret = snprintf(tmp, sizeof(tmp), "%u", len);
3816 push_args(ctx, arg_len);
3817 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
3822 buf = (uint8_t *)ctx->object + arg_data->offset;
3823 /* Output buffer is not necessarily NUL-terminated. */
3824 memcpy(buf, str, len);
3825 memset((uint8_t *)buf + len, 0x00, size - len);
3827 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
3828 /* Save address if requested. */
3829 if (arg_addr->size) {
3830 memcpy((uint8_t *)ctx->object + arg_addr->offset,
3832 (uint8_t *)ctx->object + arg_data->offset
3836 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
3838 (uint8_t *)ctx->objmask + arg_data->offset
3844 push_args(ctx, arg_addr);
3845 push_args(ctx, arg_len);
3846 push_args(ctx, arg_data);
3851 * Parse a MAC address.
3853 * Last argument (ctx->args) is retrieved to determine storage size and
3857 parse_mac_addr(struct context *ctx, const struct token *token,
3858 const char *str, unsigned int len,
3859 void *buf, unsigned int size)
3861 const struct arg *arg = pop_args(ctx);
3862 struct ether_addr tmp;
3866 /* Argument is expected. */
3870 /* Bit-mask fill is not supported. */
3871 if (arg->mask || size != sizeof(tmp))
3873 /* Only network endian is supported. */
3876 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
3877 if (ret < 0 || (unsigned int)ret != len)
3881 buf = (uint8_t *)ctx->object + arg->offset;
3882 memcpy(buf, &tmp, size);
3884 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
3887 push_args(ctx, arg);
3892 * Parse an IPv4 address.
3894 * Last argument (ctx->args) is retrieved to determine storage size and
3898 parse_ipv4_addr(struct context *ctx, const struct token *token,
3899 const char *str, unsigned int len,
3900 void *buf, unsigned int size)
3902 const struct arg *arg = pop_args(ctx);
3907 /* Argument is expected. */
3911 /* Bit-mask fill is not supported. */
3912 if (arg->mask || size != sizeof(tmp))
3914 /* Only network endian is supported. */
3917 memcpy(str2, str, len);
3919 ret = inet_pton(AF_INET, str2, &tmp);
3921 /* Attempt integer parsing. */
3922 push_args(ctx, arg);
3923 return parse_int(ctx, token, str, len, buf, size);
3927 buf = (uint8_t *)ctx->object + arg->offset;
3928 memcpy(buf, &tmp, size);
3930 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
3933 push_args(ctx, arg);
3938 * Parse an IPv6 address.
3940 * Last argument (ctx->args) is retrieved to determine storage size and
3944 parse_ipv6_addr(struct context *ctx, const struct token *token,
3945 const char *str, unsigned int len,
3946 void *buf, unsigned int size)
3948 const struct arg *arg = pop_args(ctx);
3950 struct in6_addr tmp;
3954 /* Argument is expected. */
3958 /* Bit-mask fill is not supported. */
3959 if (arg->mask || size != sizeof(tmp))
3961 /* Only network endian is supported. */
3964 memcpy(str2, str, len);
3966 ret = inet_pton(AF_INET6, str2, &tmp);
3971 buf = (uint8_t *)ctx->object + arg->offset;
3972 memcpy(buf, &tmp, size);
3974 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
3977 push_args(ctx, arg);
3981 /** Boolean values (even indices stand for false). */
3982 static const char *const boolean_name[] = {
3992 * Parse a boolean value.
3994 * Last argument (ctx->args) is retrieved to determine storage size and
3998 parse_boolean(struct context *ctx, const struct token *token,
3999 const char *str, unsigned int len,
4000 void *buf, unsigned int size)
4002 const struct arg *arg = pop_args(ctx);
4006 /* Argument is expected. */
4009 for (i = 0; boolean_name[i]; ++i)
4010 if (!strcmp_partial(boolean_name[i], str, len))
4012 /* Process token as integer. */
4013 if (boolean_name[i])
4014 str = i & 1 ? "1" : "0";
4015 push_args(ctx, arg);
4016 ret = parse_int(ctx, token, str, strlen(str), buf, size);
4017 return ret > 0 ? (int)len : ret;
4020 /** Parse port and update context. */
4022 parse_port(struct context *ctx, const struct token *token,
4023 const char *str, unsigned int len,
4024 void *buf, unsigned int size)
4026 struct buffer *out = &(struct buffer){ .port = 0 };
4034 ctx->objmask = NULL;
4035 size = sizeof(*out);
4037 ret = parse_int(ctx, token, str, len, out, size);
4039 ctx->port = out->port;
4045 /** No completion. */
4047 comp_none(struct context *ctx, const struct token *token,
4048 unsigned int ent, char *buf, unsigned int size)
4058 /** Complete boolean values. */
4060 comp_boolean(struct context *ctx, const struct token *token,
4061 unsigned int ent, char *buf, unsigned int size)
4067 for (i = 0; boolean_name[i]; ++i)
4068 if (buf && i == ent)
4069 return snprintf(buf, size, "%s", boolean_name[i]);
4075 /** Complete action names. */
4077 comp_action(struct context *ctx, const struct token *token,
4078 unsigned int ent, char *buf, unsigned int size)
4084 for (i = 0; next_action[i]; ++i)
4085 if (buf && i == ent)
4086 return snprintf(buf, size, "%s",
4087 token_list[next_action[i]].name);
4093 /** Complete available ports. */
4095 comp_port(struct context *ctx, const struct token *token,
4096 unsigned int ent, char *buf, unsigned int size)
4103 RTE_ETH_FOREACH_DEV(p) {
4104 if (buf && i == ent)
4105 return snprintf(buf, size, "%u", p);
4113 /** Complete available rule IDs. */
4115 comp_rule_id(struct context *ctx, const struct token *token,
4116 unsigned int ent, char *buf, unsigned int size)
4119 struct rte_port *port;
4120 struct port_flow *pf;
4123 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
4124 ctx->port == (portid_t)RTE_PORT_ALL)
4126 port = &ports[ctx->port];
4127 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
4128 if (buf && i == ent)
4129 return snprintf(buf, size, "%u", pf->id);
4137 /** Complete type field for RSS action. */
4139 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
4140 unsigned int ent, char *buf, unsigned int size)
4146 for (i = 0; rss_type_table[i].str; ++i)
4151 return snprintf(buf, size, "%s", rss_type_table[ent].str);
4153 return snprintf(buf, size, "end");
4157 /** Complete queue field for RSS action. */
4159 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
4160 unsigned int ent, char *buf, unsigned int size)
4167 return snprintf(buf, size, "%u", ent);
4169 return snprintf(buf, size, "end");
4173 /** Internal context. */
4174 static struct context cmd_flow_context;
4176 /** Global parser instance (cmdline API). */
4177 cmdline_parse_inst_t cmd_flow;
4179 /** Initialize context. */
4181 cmd_flow_context_init(struct context *ctx)
4183 /* A full memset() is not necessary. */
4193 ctx->objmask = NULL;
4196 /** Parse a token (cmdline API). */
4198 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
4201 struct context *ctx = &cmd_flow_context;
4202 const struct token *token;
4203 const enum index *list;
4208 token = &token_list[ctx->curr];
4209 /* Check argument length. */
4212 for (len = 0; src[len]; ++len)
4213 if (src[len] == '#' || isspace(src[len]))
4217 /* Last argument and EOL detection. */
4218 for (i = len; src[i]; ++i)
4219 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
4221 else if (!isspace(src[i])) {
4226 if (src[i] == '\r' || src[i] == '\n') {
4230 /* Initialize context if necessary. */
4231 if (!ctx->next_num) {
4234 ctx->next[ctx->next_num++] = token->next[0];
4236 /* Process argument through candidates. */
4237 ctx->prev = ctx->curr;
4238 list = ctx->next[ctx->next_num - 1];
4239 for (i = 0; list[i]; ++i) {
4240 const struct token *next = &token_list[list[i]];
4243 ctx->curr = list[i];
4245 tmp = next->call(ctx, next, src, len, result, size);
4247 tmp = parse_default(ctx, next, src, len, result, size);
4248 if (tmp == -1 || tmp != len)
4256 /* Push subsequent tokens if any. */
4258 for (i = 0; token->next[i]; ++i) {
4259 if (ctx->next_num == RTE_DIM(ctx->next))
4261 ctx->next[ctx->next_num++] = token->next[i];
4263 /* Push arguments if any. */
4265 for (i = 0; token->args[i]; ++i) {
4266 if (ctx->args_num == RTE_DIM(ctx->args))
4268 ctx->args[ctx->args_num++] = token->args[i];
4273 /** Return number of completion entries (cmdline API). */
4275 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
4277 struct context *ctx = &cmd_flow_context;
4278 const struct token *token = &token_list[ctx->curr];
4279 const enum index *list;
4283 /* Count number of tokens in current list. */
4285 list = ctx->next[ctx->next_num - 1];
4287 list = token->next[0];
4288 for (i = 0; list[i]; ++i)
4293 * If there is a single token, use its completion callback, otherwise
4294 * return the number of entries.
4296 token = &token_list[list[0]];
4297 if (i == 1 && token->comp) {
4298 /* Save index for cmd_flow_get_help(). */
4299 ctx->prev = list[0];
4300 return token->comp(ctx, token, 0, NULL, 0);
4305 /** Return a completion entry (cmdline API). */
4307 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
4308 char *dst, unsigned int size)
4310 struct context *ctx = &cmd_flow_context;
4311 const struct token *token = &token_list[ctx->curr];
4312 const enum index *list;
4316 /* Count number of tokens in current list. */
4318 list = ctx->next[ctx->next_num - 1];
4320 list = token->next[0];
4321 for (i = 0; list[i]; ++i)
4325 /* If there is a single token, use its completion callback. */
4326 token = &token_list[list[0]];
4327 if (i == 1 && token->comp) {
4328 /* Save index for cmd_flow_get_help(). */
4329 ctx->prev = list[0];
4330 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
4332 /* Otherwise make sure the index is valid and use defaults. */
4335 token = &token_list[list[index]];
4336 snprintf(dst, size, "%s", token->name);
4337 /* Save index for cmd_flow_get_help(). */
4338 ctx->prev = list[index];
4342 /** Populate help strings for current token (cmdline API). */
4344 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
4346 struct context *ctx = &cmd_flow_context;
4347 const struct token *token = &token_list[ctx->prev];
4352 /* Set token type and update global help with details. */
4353 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
4355 cmd_flow.help_str = token->help;
4357 cmd_flow.help_str = token->name;
4361 /** Token definition template (cmdline API). */
4362 static struct cmdline_token_hdr cmd_flow_token_hdr = {
4363 .ops = &(struct cmdline_token_ops){
4364 .parse = cmd_flow_parse,
4365 .complete_get_nb = cmd_flow_complete_get_nb,
4366 .complete_get_elt = cmd_flow_complete_get_elt,
4367 .get_help = cmd_flow_get_help,
4372 /** Populate the next dynamic token. */
4374 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
4375 cmdline_parse_token_hdr_t **hdr_inst)
4377 struct context *ctx = &cmd_flow_context;
4379 /* Always reinitialize context before requesting the first token. */
4380 if (!(hdr_inst - cmd_flow.tokens))
4381 cmd_flow_context_init(ctx);
4382 /* Return NULL when no more tokens are expected. */
4383 if (!ctx->next_num && ctx->curr) {
4387 /* Determine if command should end here. */
4388 if (ctx->eol && ctx->last && ctx->next_num) {
4389 const enum index *list = ctx->next[ctx->next_num - 1];
4392 for (i = 0; list[i]; ++i) {
4399 *hdr = &cmd_flow_token_hdr;
4402 /** Dispatch parsed buffer to function calls. */
4404 cmd_flow_parsed(const struct buffer *in)
4406 switch (in->command) {
4408 port_flow_validate(in->port, &in->args.vc.attr,
4409 in->args.vc.pattern, in->args.vc.actions);
4412 port_flow_create(in->port, &in->args.vc.attr,
4413 in->args.vc.pattern, in->args.vc.actions);
4416 port_flow_destroy(in->port, in->args.destroy.rule_n,
4417 in->args.destroy.rule);
4420 port_flow_flush(in->port);
4423 port_flow_query(in->port, in->args.query.rule,
4424 &in->args.query.action);
4427 port_flow_list(in->port, in->args.list.group_n,
4428 in->args.list.group);
4431 port_flow_isolate(in->port, in->args.isolate.set);
4438 /** Token generator and output processing callback (cmdline API). */
4440 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
4443 cmd_flow_tok(arg0, arg2);
4445 cmd_flow_parsed(arg0);
4448 /** Global parser instance (cmdline API). */
4449 cmdline_parse_inst_t cmd_flow = {
4451 .data = NULL, /**< Unused. */
4452 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
4455 }, /**< Tokens are returned by cmd_flow_tok(). */