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_string_fns.h>
17 #include <rte_common.h>
18 #include <rte_ethdev.h>
19 #include <rte_byteorder.h>
20 #include <cmdline_parse.h>
21 #include <cmdline_parse_etheraddr.h>
22 #include <cmdline_parse_string.h>
23 #include <cmdline_parse_num.h>
25 #include <rte_hexdump.h>
29 /** Parser token indices. */
52 /* Top-level command. */
54 /* Sub-leve commands. */
59 /* Top-level command. */
61 /* Sub-level commands. */
70 /* Destroy arguments. */
73 /* Query arguments. */
79 /* Validate/create arguments. */
86 /* Validate/create pattern. */
123 ITEM_VLAN_INNER_TYPE,
155 ITEM_E_TAG_GRP_ECID_B,
164 ITEM_GRE_C_RSVD0_VER,
180 ITEM_ARP_ETH_IPV4_SHA,
181 ITEM_ARP_ETH_IPV4_SPA,
182 ITEM_ARP_ETH_IPV4_THA,
183 ITEM_ARP_ETH_IPV4_TPA,
185 ITEM_IPV6_EXT_NEXT_HDR,
190 ITEM_ICMP6_ND_NS_TARGET_ADDR,
192 ITEM_ICMP6_ND_NA_TARGET_ADDR,
194 ITEM_ICMP6_ND_OPT_TYPE,
195 ITEM_ICMP6_ND_OPT_SLA_ETH,
196 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
197 ITEM_ICMP6_ND_OPT_TLA_ETH,
198 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
211 ITEM_HIGIG2_CLASSIFICATION,
217 ITEM_L2TPV3OIP_SESSION_ID,
221 /* Validate/create actions. */
241 ACTION_RSS_FUNC_DEFAULT,
242 ACTION_RSS_FUNC_TOEPLITZ,
243 ACTION_RSS_FUNC_SIMPLE_XOR,
244 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
256 ACTION_PHY_PORT_ORIGINAL,
257 ACTION_PHY_PORT_INDEX,
259 ACTION_PORT_ID_ORIGINAL,
263 ACTION_OF_SET_MPLS_TTL,
264 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
265 ACTION_OF_DEC_MPLS_TTL,
266 ACTION_OF_SET_NW_TTL,
267 ACTION_OF_SET_NW_TTL_NW_TTL,
268 ACTION_OF_DEC_NW_TTL,
269 ACTION_OF_COPY_TTL_OUT,
270 ACTION_OF_COPY_TTL_IN,
273 ACTION_OF_PUSH_VLAN_ETHERTYPE,
274 ACTION_OF_SET_VLAN_VID,
275 ACTION_OF_SET_VLAN_VID_VLAN_VID,
276 ACTION_OF_SET_VLAN_PCP,
277 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
279 ACTION_OF_POP_MPLS_ETHERTYPE,
281 ACTION_OF_PUSH_MPLS_ETHERTYPE,
288 ACTION_MPLSOGRE_ENCAP,
289 ACTION_MPLSOGRE_DECAP,
290 ACTION_MPLSOUDP_ENCAP,
291 ACTION_MPLSOUDP_DECAP,
293 ACTION_SET_IPV4_SRC_IPV4_SRC,
295 ACTION_SET_IPV4_DST_IPV4_DST,
297 ACTION_SET_IPV6_SRC_IPV6_SRC,
299 ACTION_SET_IPV6_DST_IPV6_DST,
301 ACTION_SET_TP_SRC_TP_SRC,
303 ACTION_SET_TP_DST_TP_DST,
309 ACTION_SET_MAC_SRC_MAC_SRC,
311 ACTION_SET_MAC_DST_MAC_DST,
313 ACTION_INC_TCP_SEQ_VALUE,
315 ACTION_DEC_TCP_SEQ_VALUE,
317 ACTION_INC_TCP_ACK_VALUE,
319 ACTION_DEC_TCP_ACK_VALUE,
322 ACTION_RAW_ENCAP_INDEX,
323 ACTION_RAW_ENCAP_INDEX_VALUE,
324 ACTION_RAW_DECAP_INDEX,
325 ACTION_RAW_DECAP_INDEX_VALUE,
328 ACTION_SET_TAG_INDEX,
331 ACTION_SET_META_DATA,
332 ACTION_SET_META_MASK,
333 ACTION_SET_IPV4_DSCP,
334 ACTION_SET_IPV4_DSCP_VALUE,
335 ACTION_SET_IPV6_DSCP,
336 ACTION_SET_IPV6_DSCP_VALUE,
339 /** Maximum size for pattern in struct rte_flow_item_raw. */
340 #define ITEM_RAW_PATTERN_SIZE 40
342 /** Storage size for struct rte_flow_item_raw including pattern. */
343 #define ITEM_RAW_SIZE \
344 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
346 /** Maximum number of queue indices in struct rte_flow_action_rss. */
347 #define ACTION_RSS_QUEUE_NUM 128
349 /** Storage for struct rte_flow_action_rss including external data. */
350 struct action_rss_data {
351 struct rte_flow_action_rss conf;
352 uint8_t key[RSS_HASH_KEY_LENGTH];
353 uint16_t queue[ACTION_RSS_QUEUE_NUM];
356 /** Maximum data size in struct rte_flow_action_raw_encap. */
357 #define ACTION_RAW_ENCAP_MAX_DATA 128
358 #define RAW_ENCAP_CONFS_MAX_NUM 8
360 /** Storage for struct rte_flow_action_raw_encap. */
361 struct raw_encap_conf {
362 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
363 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
367 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
369 /** Storage for struct rte_flow_action_raw_encap including external data. */
370 struct action_raw_encap_data {
371 struct rte_flow_action_raw_encap conf;
372 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
373 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
377 /** Storage for struct rte_flow_action_raw_decap. */
378 struct raw_decap_conf {
379 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
383 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
385 /** Storage for struct rte_flow_action_raw_decap including external data. */
386 struct action_raw_decap_data {
387 struct rte_flow_action_raw_decap conf;
388 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
392 struct vxlan_encap_conf vxlan_encap_conf = {
396 .vni = "\x00\x00\x00",
398 .udp_dst = RTE_BE16(4789),
399 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
400 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
401 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
402 "\x00\x00\x00\x00\x00\x00\x00\x01",
403 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
404 "\x00\x00\x00\x00\x00\x00\x11\x11",
408 .eth_src = "\x00\x00\x00\x00\x00\x00",
409 .eth_dst = "\xff\xff\xff\xff\xff\xff",
412 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
413 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
415 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
416 struct action_vxlan_encap_data {
417 struct rte_flow_action_vxlan_encap conf;
418 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
419 struct rte_flow_item_eth item_eth;
420 struct rte_flow_item_vlan item_vlan;
422 struct rte_flow_item_ipv4 item_ipv4;
423 struct rte_flow_item_ipv6 item_ipv6;
425 struct rte_flow_item_udp item_udp;
426 struct rte_flow_item_vxlan item_vxlan;
429 struct nvgre_encap_conf nvgre_encap_conf = {
432 .tni = "\x00\x00\x00",
433 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
434 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
435 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
436 "\x00\x00\x00\x00\x00\x00\x00\x01",
437 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
438 "\x00\x00\x00\x00\x00\x00\x11\x11",
440 .eth_src = "\x00\x00\x00\x00\x00\x00",
441 .eth_dst = "\xff\xff\xff\xff\xff\xff",
444 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
445 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
447 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
448 struct action_nvgre_encap_data {
449 struct rte_flow_action_nvgre_encap conf;
450 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
451 struct rte_flow_item_eth item_eth;
452 struct rte_flow_item_vlan item_vlan;
454 struct rte_flow_item_ipv4 item_ipv4;
455 struct rte_flow_item_ipv6 item_ipv6;
457 struct rte_flow_item_nvgre item_nvgre;
460 struct l2_encap_conf l2_encap_conf;
462 struct l2_decap_conf l2_decap_conf;
464 struct mplsogre_encap_conf mplsogre_encap_conf;
466 struct mplsogre_decap_conf mplsogre_decap_conf;
468 struct mplsoudp_encap_conf mplsoudp_encap_conf;
470 struct mplsoudp_decap_conf mplsoudp_decap_conf;
472 /** Maximum number of subsequent tokens and arguments on the stack. */
473 #define CTX_STACK_SIZE 16
475 /** Parser context. */
477 /** Stack of subsequent token lists to process. */
478 const enum index *next[CTX_STACK_SIZE];
479 /** Arguments for stacked tokens. */
480 const void *args[CTX_STACK_SIZE];
481 enum index curr; /**< Current token index. */
482 enum index prev; /**< Index of the last token seen. */
483 int next_num; /**< Number of entries in next[]. */
484 int args_num; /**< Number of entries in args[]. */
485 uint32_t eol:1; /**< EOL has been detected. */
486 uint32_t last:1; /**< No more arguments. */
487 portid_t port; /**< Current port ID (for completions). */
488 uint32_t objdata; /**< Object-specific data. */
489 void *object; /**< Address of current object for relative offsets. */
490 void *objmask; /**< Object a full mask must be written to. */
493 /** Token argument. */
495 uint32_t hton:1; /**< Use network byte ordering. */
496 uint32_t sign:1; /**< Value is signed. */
497 uint32_t bounded:1; /**< Value is bounded. */
498 uintmax_t min; /**< Minimum value if bounded. */
499 uintmax_t max; /**< Maximum value if bounded. */
500 uint32_t offset; /**< Relative offset from ctx->object. */
501 uint32_t size; /**< Field size. */
502 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
505 /** Parser token definition. */
507 /** Type displayed during completion (defaults to "TOKEN"). */
509 /** Help displayed during completion (defaults to token name). */
511 /** Private data used by parser functions. */
514 * Lists of subsequent tokens to push on the stack. Each call to the
515 * parser consumes the last entry of that stack.
517 const enum index *const *next;
518 /** Arguments stack for subsequent tokens that need them. */
519 const struct arg *const *args;
521 * Token-processing callback, returns -1 in case of error, the
522 * length of the matched string otherwise. If NULL, attempts to
523 * match the token name.
525 * If buf is not NULL, the result should be stored in it according
526 * to context. An error is returned if not large enough.
528 int (*call)(struct context *ctx, const struct token *token,
529 const char *str, unsigned int len,
530 void *buf, unsigned int size);
532 * Callback that provides possible values for this token, used for
533 * completion. Returns -1 in case of error, the number of possible
534 * values otherwise. If NULL, the token name is used.
536 * If buf is not NULL, entry index ent is written to buf and the
537 * full length of the entry is returned (same behavior as
540 int (*comp)(struct context *ctx, const struct token *token,
541 unsigned int ent, char *buf, unsigned int size);
542 /** Mandatory token name, no default value. */
546 /** Static initializer for the next field. */
547 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
549 /** Static initializer for a NEXT() entry. */
550 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
552 /** Static initializer for the args field. */
553 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
555 /** Static initializer for ARGS() to target a field. */
556 #define ARGS_ENTRY(s, f) \
557 (&(const struct arg){ \
558 .offset = offsetof(s, f), \
559 .size = sizeof(((s *)0)->f), \
562 /** Static initializer for ARGS() to target a bit-field. */
563 #define ARGS_ENTRY_BF(s, f, b) \
564 (&(const struct arg){ \
566 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
569 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
570 #define ARGS_ENTRY_MASK(s, f, m) \
571 (&(const struct arg){ \
572 .offset = offsetof(s, f), \
573 .size = sizeof(((s *)0)->f), \
574 .mask = (const void *)(m), \
577 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
578 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
579 (&(const struct arg){ \
581 .offset = offsetof(s, f), \
582 .size = sizeof(((s *)0)->f), \
583 .mask = (const void *)(m), \
586 /** Static initializer for ARGS() to target a pointer. */
587 #define ARGS_ENTRY_PTR(s, f) \
588 (&(const struct arg){ \
589 .size = sizeof(*((s *)0)->f), \
592 /** Static initializer for ARGS() with arbitrary offset and size. */
593 #define ARGS_ENTRY_ARB(o, s) \
594 (&(const struct arg){ \
599 /** Same as ARGS_ENTRY_ARB() with bounded values. */
600 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
601 (&(const struct arg){ \
609 /** Same as ARGS_ENTRY() using network byte ordering. */
610 #define ARGS_ENTRY_HTON(s, f) \
611 (&(const struct arg){ \
613 .offset = offsetof(s, f), \
614 .size = sizeof(((s *)0)->f), \
617 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
618 #define ARG_ENTRY_HTON(s) \
619 (&(const struct arg){ \
625 /** Parser output buffer layout expected by cmd_flow_parsed(). */
627 enum index command; /**< Flow command. */
628 portid_t port; /**< Affected port ID. */
631 struct rte_flow_attr attr;
632 struct rte_flow_item *pattern;
633 struct rte_flow_action *actions;
637 } vc; /**< Validate/create arguments. */
641 } destroy; /**< Destroy arguments. */
644 struct rte_flow_action action;
645 } query; /**< Query arguments. */
649 } list; /**< List arguments. */
652 } isolate; /**< Isolated mode arguments. */
653 } args; /**< Command arguments. */
656 /** Private data for pattern items. */
657 struct parse_item_priv {
658 enum rte_flow_item_type type; /**< Item type. */
659 uint32_t size; /**< Size of item specification structure. */
662 #define PRIV_ITEM(t, s) \
663 (&(const struct parse_item_priv){ \
664 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
668 /** Private data for actions. */
669 struct parse_action_priv {
670 enum rte_flow_action_type type; /**< Action type. */
671 uint32_t size; /**< Size of action configuration structure. */
674 #define PRIV_ACTION(t, s) \
675 (&(const struct parse_action_priv){ \
676 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
680 static const enum index next_vc_attr[] = {
690 static const enum index next_destroy_attr[] = {
696 static const enum index next_list_attr[] = {
702 static const enum index item_param[] = {
711 static const enum index next_item[] = {
747 ITEM_ICMP6_ND_OPT_SLA_ETH,
748 ITEM_ICMP6_ND_OPT_TLA_ETH,
763 static const enum index item_fuzzy[] = {
769 static const enum index item_any[] = {
775 static const enum index item_vf[] = {
781 static const enum index item_phy_port[] = {
787 static const enum index item_port_id[] = {
793 static const enum index item_mark[] = {
799 static const enum index item_raw[] = {
809 static const enum index item_eth[] = {
817 static const enum index item_vlan[] = {
822 ITEM_VLAN_INNER_TYPE,
827 static const enum index item_ipv4[] = {
837 static const enum index item_ipv6[] = {
848 static const enum index item_icmp[] = {
855 static const enum index item_udp[] = {
862 static const enum index item_tcp[] = {
870 static const enum index item_sctp[] = {
879 static const enum index item_vxlan[] = {
885 static const enum index item_e_tag[] = {
886 ITEM_E_TAG_GRP_ECID_B,
891 static const enum index item_nvgre[] = {
897 static const enum index item_mpls[] = {
905 static const enum index item_gre[] = {
907 ITEM_GRE_C_RSVD0_VER,
915 static const enum index item_gre_key[] = {
921 static const enum index item_gtp[] = {
927 static const enum index item_geneve[] = {
934 static const enum index item_vxlan_gpe[] = {
940 static const enum index item_arp_eth_ipv4[] = {
941 ITEM_ARP_ETH_IPV4_SHA,
942 ITEM_ARP_ETH_IPV4_SPA,
943 ITEM_ARP_ETH_IPV4_THA,
944 ITEM_ARP_ETH_IPV4_TPA,
949 static const enum index item_ipv6_ext[] = {
950 ITEM_IPV6_EXT_NEXT_HDR,
955 static const enum index item_icmp6[] = {
962 static const enum index item_icmp6_nd_ns[] = {
963 ITEM_ICMP6_ND_NS_TARGET_ADDR,
968 static const enum index item_icmp6_nd_na[] = {
969 ITEM_ICMP6_ND_NA_TARGET_ADDR,
974 static const enum index item_icmp6_nd_opt[] = {
975 ITEM_ICMP6_ND_OPT_TYPE,
980 static const enum index item_icmp6_nd_opt_sla_eth[] = {
981 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
986 static const enum index item_icmp6_nd_opt_tla_eth[] = {
987 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
992 static const enum index item_meta[] = {
998 static const enum index item_gtp_psc[] = {
1005 static const enum index item_pppoed[] = {
1011 static const enum index item_pppoes[] = {
1017 static const enum index item_pppoe_proto_id[] = {
1018 ITEM_PPPOE_PROTO_ID,
1023 static const enum index item_higig2[] = {
1024 ITEM_HIGIG2_CLASSIFICATION,
1030 static const enum index item_esp[] = {
1036 static const enum index next_set_raw[] = {
1042 static const enum index item_tag[] = {
1049 static const enum index item_l2tpv3oip[] = {
1050 ITEM_L2TPV3OIP_SESSION_ID,
1055 static const enum index next_action[] = {
1071 ACTION_OF_SET_MPLS_TTL,
1072 ACTION_OF_DEC_MPLS_TTL,
1073 ACTION_OF_SET_NW_TTL,
1074 ACTION_OF_DEC_NW_TTL,
1075 ACTION_OF_COPY_TTL_OUT,
1076 ACTION_OF_COPY_TTL_IN,
1078 ACTION_OF_PUSH_VLAN,
1079 ACTION_OF_SET_VLAN_VID,
1080 ACTION_OF_SET_VLAN_PCP,
1082 ACTION_OF_PUSH_MPLS,
1089 ACTION_MPLSOGRE_ENCAP,
1090 ACTION_MPLSOGRE_DECAP,
1091 ACTION_MPLSOUDP_ENCAP,
1092 ACTION_MPLSOUDP_DECAP,
1093 ACTION_SET_IPV4_SRC,
1094 ACTION_SET_IPV4_DST,
1095 ACTION_SET_IPV6_SRC,
1096 ACTION_SET_IPV6_DST,
1112 ACTION_SET_IPV4_DSCP,
1113 ACTION_SET_IPV6_DSCP,
1117 static const enum index action_mark[] = {
1123 static const enum index action_queue[] = {
1129 static const enum index action_count[] = {
1131 ACTION_COUNT_SHARED,
1136 static const enum index action_rss[] = {
1147 static const enum index action_vf[] = {
1154 static const enum index action_phy_port[] = {
1155 ACTION_PHY_PORT_ORIGINAL,
1156 ACTION_PHY_PORT_INDEX,
1161 static const enum index action_port_id[] = {
1162 ACTION_PORT_ID_ORIGINAL,
1168 static const enum index action_meter[] = {
1174 static const enum index action_of_set_mpls_ttl[] = {
1175 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1180 static const enum index action_of_set_nw_ttl[] = {
1181 ACTION_OF_SET_NW_TTL_NW_TTL,
1186 static const enum index action_of_push_vlan[] = {
1187 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1192 static const enum index action_of_set_vlan_vid[] = {
1193 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1198 static const enum index action_of_set_vlan_pcp[] = {
1199 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1204 static const enum index action_of_pop_mpls[] = {
1205 ACTION_OF_POP_MPLS_ETHERTYPE,
1210 static const enum index action_of_push_mpls[] = {
1211 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1216 static const enum index action_set_ipv4_src[] = {
1217 ACTION_SET_IPV4_SRC_IPV4_SRC,
1222 static const enum index action_set_mac_src[] = {
1223 ACTION_SET_MAC_SRC_MAC_SRC,
1228 static const enum index action_set_ipv4_dst[] = {
1229 ACTION_SET_IPV4_DST_IPV4_DST,
1234 static const enum index action_set_ipv6_src[] = {
1235 ACTION_SET_IPV6_SRC_IPV6_SRC,
1240 static const enum index action_set_ipv6_dst[] = {
1241 ACTION_SET_IPV6_DST_IPV6_DST,
1246 static const enum index action_set_tp_src[] = {
1247 ACTION_SET_TP_SRC_TP_SRC,
1252 static const enum index action_set_tp_dst[] = {
1253 ACTION_SET_TP_DST_TP_DST,
1258 static const enum index action_set_ttl[] = {
1264 static const enum index action_jump[] = {
1270 static const enum index action_set_mac_dst[] = {
1271 ACTION_SET_MAC_DST_MAC_DST,
1276 static const enum index action_inc_tcp_seq[] = {
1277 ACTION_INC_TCP_SEQ_VALUE,
1282 static const enum index action_dec_tcp_seq[] = {
1283 ACTION_DEC_TCP_SEQ_VALUE,
1288 static const enum index action_inc_tcp_ack[] = {
1289 ACTION_INC_TCP_ACK_VALUE,
1294 static const enum index action_dec_tcp_ack[] = {
1295 ACTION_DEC_TCP_ACK_VALUE,
1300 static const enum index action_raw_encap[] = {
1301 ACTION_RAW_ENCAP_INDEX,
1306 static const enum index action_raw_decap[] = {
1307 ACTION_RAW_DECAP_INDEX,
1312 static const enum index action_set_tag[] = {
1313 ACTION_SET_TAG_DATA,
1314 ACTION_SET_TAG_INDEX,
1315 ACTION_SET_TAG_MASK,
1320 static const enum index action_set_meta[] = {
1321 ACTION_SET_META_DATA,
1322 ACTION_SET_META_MASK,
1327 static const enum index action_set_ipv4_dscp[] = {
1328 ACTION_SET_IPV4_DSCP_VALUE,
1333 static const enum index action_set_ipv6_dscp[] = {
1334 ACTION_SET_IPV6_DSCP_VALUE,
1339 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1340 const char *, unsigned int,
1341 void *, unsigned int);
1342 static int parse_set_init(struct context *, const struct token *,
1343 const char *, unsigned int,
1344 void *, unsigned int);
1345 static int parse_init(struct context *, const struct token *,
1346 const char *, unsigned int,
1347 void *, unsigned int);
1348 static int parse_vc(struct context *, const struct token *,
1349 const char *, unsigned int,
1350 void *, unsigned int);
1351 static int parse_vc_spec(struct context *, const struct token *,
1352 const char *, unsigned int, void *, unsigned int);
1353 static int parse_vc_conf(struct context *, const struct token *,
1354 const char *, unsigned int, void *, unsigned int);
1355 static int parse_vc_action_rss(struct context *, const struct token *,
1356 const char *, unsigned int, void *,
1358 static int parse_vc_action_rss_func(struct context *, const struct token *,
1359 const char *, unsigned int, void *,
1361 static int parse_vc_action_rss_type(struct context *, const struct token *,
1362 const char *, unsigned int, void *,
1364 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1365 const char *, unsigned int, void *,
1367 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1368 const char *, unsigned int, void *,
1370 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1371 const char *, unsigned int, void *,
1373 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1374 const char *, unsigned int, void *,
1376 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1377 const char *, unsigned int, void *,
1379 static int parse_vc_action_mplsogre_encap(struct context *,
1380 const struct token *, const char *,
1381 unsigned int, void *, unsigned int);
1382 static int parse_vc_action_mplsogre_decap(struct context *,
1383 const struct token *, const char *,
1384 unsigned int, void *, unsigned int);
1385 static int parse_vc_action_mplsoudp_encap(struct context *,
1386 const struct token *, const char *,
1387 unsigned int, void *, unsigned int);
1388 static int parse_vc_action_mplsoudp_decap(struct context *,
1389 const struct token *, const char *,
1390 unsigned int, void *, unsigned int);
1391 static int parse_vc_action_raw_encap(struct context *,
1392 const struct token *, const char *,
1393 unsigned int, void *, unsigned int);
1394 static int parse_vc_action_raw_decap(struct context *,
1395 const struct token *, const char *,
1396 unsigned int, void *, unsigned int);
1397 static int parse_vc_action_raw_encap_index(struct context *,
1398 const struct token *, const char *,
1399 unsigned int, void *, unsigned int);
1400 static int parse_vc_action_raw_decap_index(struct context *,
1401 const struct token *, const char *,
1402 unsigned int, void *, unsigned int);
1403 static int parse_vc_action_set_meta(struct context *ctx,
1404 const struct token *token, const char *str,
1405 unsigned int len, void *buf,
1407 static int parse_destroy(struct context *, const struct token *,
1408 const char *, unsigned int,
1409 void *, unsigned int);
1410 static int parse_flush(struct context *, const struct token *,
1411 const char *, unsigned int,
1412 void *, unsigned int);
1413 static int parse_query(struct context *, const struct token *,
1414 const char *, unsigned int,
1415 void *, unsigned int);
1416 static int parse_action(struct context *, const struct token *,
1417 const char *, unsigned int,
1418 void *, unsigned int);
1419 static int parse_list(struct context *, const struct token *,
1420 const char *, unsigned int,
1421 void *, unsigned int);
1422 static int parse_isolate(struct context *, const struct token *,
1423 const char *, unsigned int,
1424 void *, unsigned int);
1425 static int parse_int(struct context *, const struct token *,
1426 const char *, unsigned int,
1427 void *, unsigned int);
1428 static int parse_prefix(struct context *, const struct token *,
1429 const char *, unsigned int,
1430 void *, unsigned int);
1431 static int parse_boolean(struct context *, const struct token *,
1432 const char *, unsigned int,
1433 void *, unsigned int);
1434 static int parse_string(struct context *, const struct token *,
1435 const char *, unsigned int,
1436 void *, unsigned int);
1437 static int parse_hex(struct context *ctx, const struct token *token,
1438 const char *str, unsigned int len,
1439 void *buf, unsigned int size);
1440 static int parse_mac_addr(struct context *, const struct token *,
1441 const char *, unsigned int,
1442 void *, unsigned int);
1443 static int parse_ipv4_addr(struct context *, const struct token *,
1444 const char *, unsigned int,
1445 void *, unsigned int);
1446 static int parse_ipv6_addr(struct context *, const struct token *,
1447 const char *, unsigned int,
1448 void *, unsigned int);
1449 static int parse_port(struct context *, const struct token *,
1450 const char *, unsigned int,
1451 void *, unsigned int);
1452 static int comp_none(struct context *, const struct token *,
1453 unsigned int, char *, unsigned int);
1454 static int comp_boolean(struct context *, const struct token *,
1455 unsigned int, char *, unsigned int);
1456 static int comp_action(struct context *, const struct token *,
1457 unsigned int, char *, unsigned int);
1458 static int comp_port(struct context *, const struct token *,
1459 unsigned int, char *, unsigned int);
1460 static int comp_rule_id(struct context *, const struct token *,
1461 unsigned int, char *, unsigned int);
1462 static int comp_vc_action_rss_type(struct context *, const struct token *,
1463 unsigned int, char *, unsigned int);
1464 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1465 unsigned int, char *, unsigned int);
1466 static int comp_set_raw_index(struct context *, const struct token *,
1467 unsigned int, char *, unsigned int);
1469 /** Token definitions. */
1470 static const struct token token_list[] = {
1471 /* Special tokens. */
1474 .help = "null entry, abused as the entry point",
1475 .next = NEXT(NEXT_ENTRY(FLOW)),
1480 .help = "command may end here",
1483 .name = "START_SET",
1484 .help = "null entry, abused as the entry point for set",
1485 .next = NEXT(NEXT_ENTRY(SET)),
1490 .help = "set command may end here",
1492 /* Common tokens. */
1496 .help = "integer value",
1501 .name = "{unsigned}",
1503 .help = "unsigned integer value",
1510 .help = "prefix length for bit-mask",
1511 .call = parse_prefix,
1515 .name = "{boolean}",
1517 .help = "any boolean value",
1518 .call = parse_boolean,
1519 .comp = comp_boolean,
1524 .help = "fixed string",
1525 .call = parse_string,
1531 .help = "fixed string",
1536 .name = "{MAC address}",
1538 .help = "standard MAC address notation",
1539 .call = parse_mac_addr,
1543 .name = "{IPv4 address}",
1544 .type = "IPV4 ADDRESS",
1545 .help = "standard IPv4 address notation",
1546 .call = parse_ipv4_addr,
1550 .name = "{IPv6 address}",
1551 .type = "IPV6 ADDRESS",
1552 .help = "standard IPv6 address notation",
1553 .call = parse_ipv6_addr,
1557 .name = "{rule id}",
1559 .help = "rule identifier",
1561 .comp = comp_rule_id,
1564 .name = "{port_id}",
1566 .help = "port identifier",
1571 .name = "{group_id}",
1573 .help = "group identifier",
1577 [PRIORITY_LEVEL] = {
1580 .help = "priority level",
1584 /* Top-level command. */
1587 .type = "{command} {port_id} [{arg} [...]]",
1588 .help = "manage ingress/egress flow rules",
1589 .next = NEXT(NEXT_ENTRY
1599 /* Sub-level commands. */
1602 .help = "check whether a flow rule can be created",
1603 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1604 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1609 .help = "create a flow rule",
1610 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1611 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1616 .help = "destroy specific flow rules",
1617 .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
1618 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1619 .call = parse_destroy,
1623 .help = "destroy all flow rules",
1624 .next = NEXT(NEXT_ENTRY(PORT_ID)),
1625 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1626 .call = parse_flush,
1630 .help = "query an existing flow rule",
1631 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
1632 NEXT_ENTRY(RULE_ID),
1633 NEXT_ENTRY(PORT_ID)),
1634 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
1635 ARGS_ENTRY(struct buffer, args.query.rule),
1636 ARGS_ENTRY(struct buffer, port)),
1637 .call = parse_query,
1641 .help = "list existing flow rules",
1642 .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
1643 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1648 .help = "restrict ingress traffic to the defined flow rules",
1649 .next = NEXT(NEXT_ENTRY(BOOLEAN),
1650 NEXT_ENTRY(PORT_ID)),
1651 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
1652 ARGS_ENTRY(struct buffer, port)),
1653 .call = parse_isolate,
1655 /* Destroy arguments. */
1658 .help = "specify a rule identifier",
1659 .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
1660 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
1661 .call = parse_destroy,
1663 /* Query arguments. */
1667 .help = "action to query, must be part of the rule",
1668 .call = parse_action,
1669 .comp = comp_action,
1671 /* List arguments. */
1674 .help = "specify a group",
1675 .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
1676 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
1679 /* Validate/create attributes. */
1682 .help = "specify a group",
1683 .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
1684 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
1689 .help = "specify a priority level",
1690 .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
1691 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
1696 .help = "affect rule to ingress",
1697 .next = NEXT(next_vc_attr),
1702 .help = "affect rule to egress",
1703 .next = NEXT(next_vc_attr),
1708 .help = "apply rule directly to endpoints found in pattern",
1709 .next = NEXT(next_vc_attr),
1712 /* Validate/create pattern. */
1715 .help = "submit a list of pattern items",
1716 .next = NEXT(next_item),
1721 .help = "match value perfectly (with full bit-mask)",
1722 .call = parse_vc_spec,
1724 [ITEM_PARAM_SPEC] = {
1726 .help = "match value according to configured bit-mask",
1727 .call = parse_vc_spec,
1729 [ITEM_PARAM_LAST] = {
1731 .help = "specify upper bound to establish a range",
1732 .call = parse_vc_spec,
1734 [ITEM_PARAM_MASK] = {
1736 .help = "specify bit-mask with relevant bits set to one",
1737 .call = parse_vc_spec,
1739 [ITEM_PARAM_PREFIX] = {
1741 .help = "generate bit-mask from a prefix length",
1742 .call = parse_vc_spec,
1746 .help = "specify next pattern item",
1747 .next = NEXT(next_item),
1751 .help = "end list of pattern items",
1752 .priv = PRIV_ITEM(END, 0),
1753 .next = NEXT(NEXT_ENTRY(ACTIONS)),
1758 .help = "no-op pattern item",
1759 .priv = PRIV_ITEM(VOID, 0),
1760 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1765 .help = "perform actions when pattern does not match",
1766 .priv = PRIV_ITEM(INVERT, 0),
1767 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1772 .help = "match any protocol for the current layer",
1773 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
1774 .next = NEXT(item_any),
1779 .help = "number of layers covered",
1780 .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
1781 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
1785 .help = "match traffic from/to the physical function",
1786 .priv = PRIV_ITEM(PF, 0),
1787 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1792 .help = "match traffic from/to a virtual function ID",
1793 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
1794 .next = NEXT(item_vf),
1800 .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
1801 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
1805 .help = "match traffic from/to a specific physical port",
1806 .priv = PRIV_ITEM(PHY_PORT,
1807 sizeof(struct rte_flow_item_phy_port)),
1808 .next = NEXT(item_phy_port),
1811 [ITEM_PHY_PORT_INDEX] = {
1813 .help = "physical port index",
1814 .next = NEXT(item_phy_port, NEXT_ENTRY(UNSIGNED), item_param),
1815 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
1819 .help = "match traffic from/to a given DPDK port ID",
1820 .priv = PRIV_ITEM(PORT_ID,
1821 sizeof(struct rte_flow_item_port_id)),
1822 .next = NEXT(item_port_id),
1825 [ITEM_PORT_ID_ID] = {
1827 .help = "DPDK port ID",
1828 .next = NEXT(item_port_id, NEXT_ENTRY(UNSIGNED), item_param),
1829 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
1833 .help = "match traffic against value set in previously matched rule",
1834 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
1835 .next = NEXT(item_mark),
1840 .help = "Integer value to match against",
1841 .next = NEXT(item_mark, NEXT_ENTRY(UNSIGNED), item_param),
1842 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
1846 .help = "match an arbitrary byte string",
1847 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
1848 .next = NEXT(item_raw),
1851 [ITEM_RAW_RELATIVE] = {
1853 .help = "look for pattern after the previous item",
1854 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1855 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1858 [ITEM_RAW_SEARCH] = {
1860 .help = "search pattern from offset (see also limit)",
1861 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1862 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1865 [ITEM_RAW_OFFSET] = {
1867 .help = "absolute or relative offset for pattern",
1868 .next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
1869 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
1871 [ITEM_RAW_LIMIT] = {
1873 .help = "search area limit for start of pattern",
1874 .next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
1875 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
1877 [ITEM_RAW_PATTERN] = {
1879 .help = "byte string to look for",
1880 .next = NEXT(item_raw,
1882 NEXT_ENTRY(ITEM_PARAM_IS,
1885 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
1886 ARGS_ENTRY(struct rte_flow_item_raw, length),
1887 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
1888 ITEM_RAW_PATTERN_SIZE)),
1892 .help = "match Ethernet header",
1893 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
1894 .next = NEXT(item_eth),
1899 .help = "destination MAC",
1900 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1901 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
1905 .help = "source MAC",
1906 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1907 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
1911 .help = "EtherType",
1912 .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
1913 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
1917 .help = "match 802.1Q/ad VLAN tag",
1918 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
1919 .next = NEXT(item_vlan),
1924 .help = "tag control information",
1925 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1926 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
1930 .help = "priority code point",
1931 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1932 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1937 .help = "drop eligible indicator",
1938 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1939 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1944 .help = "VLAN identifier",
1945 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1946 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1949 [ITEM_VLAN_INNER_TYPE] = {
1950 .name = "inner_type",
1951 .help = "inner EtherType",
1952 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1953 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
1958 .help = "match IPv4 header",
1959 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
1960 .next = NEXT(item_ipv4),
1965 .help = "type of service",
1966 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1967 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1968 hdr.type_of_service)),
1972 .help = "time to live",
1973 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1974 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1977 [ITEM_IPV4_PROTO] = {
1979 .help = "next protocol ID",
1980 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1981 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1982 hdr.next_proto_id)),
1986 .help = "source address",
1987 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1988 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1993 .help = "destination address",
1994 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1995 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2000 .help = "match IPv6 header",
2001 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
2002 .next = NEXT(item_ipv6),
2007 .help = "traffic class",
2008 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2009 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2011 "\x0f\xf0\x00\x00")),
2013 [ITEM_IPV6_FLOW] = {
2015 .help = "flow label",
2016 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2017 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2019 "\x00\x0f\xff\xff")),
2021 [ITEM_IPV6_PROTO] = {
2023 .help = "protocol (next header)",
2024 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2025 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2030 .help = "hop limit",
2031 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2032 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2037 .help = "source address",
2038 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
2039 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2044 .help = "destination address",
2045 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
2046 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2051 .help = "match ICMP header",
2052 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
2053 .next = NEXT(item_icmp),
2056 [ITEM_ICMP_TYPE] = {
2058 .help = "ICMP packet type",
2059 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2060 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2063 [ITEM_ICMP_CODE] = {
2065 .help = "ICMP packet code",
2066 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2067 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2072 .help = "match UDP header",
2073 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
2074 .next = NEXT(item_udp),
2079 .help = "UDP source port",
2080 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
2081 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2086 .help = "UDP destination port",
2087 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
2088 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2093 .help = "match TCP header",
2094 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
2095 .next = NEXT(item_tcp),
2100 .help = "TCP source port",
2101 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
2102 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2107 .help = "TCP destination port",
2108 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
2109 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2112 [ITEM_TCP_FLAGS] = {
2114 .help = "TCP flags",
2115 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
2116 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2121 .help = "match SCTP header",
2122 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
2123 .next = NEXT(item_sctp),
2128 .help = "SCTP source port",
2129 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2130 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2135 .help = "SCTP destination port",
2136 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2137 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2142 .help = "validation tag",
2143 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2144 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2147 [ITEM_SCTP_CKSUM] = {
2150 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2151 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2156 .help = "match VXLAN header",
2157 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
2158 .next = NEXT(item_vxlan),
2161 [ITEM_VXLAN_VNI] = {
2163 .help = "VXLAN identifier",
2164 .next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
2165 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
2169 .help = "match E-Tag header",
2170 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
2171 .next = NEXT(item_e_tag),
2174 [ITEM_E_TAG_GRP_ECID_B] = {
2175 .name = "grp_ecid_b",
2176 .help = "GRP and E-CID base",
2177 .next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
2178 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
2184 .help = "match NVGRE header",
2185 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
2186 .next = NEXT(item_nvgre),
2189 [ITEM_NVGRE_TNI] = {
2191 .help = "virtual subnet ID",
2192 .next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
2193 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
2197 .help = "match MPLS header",
2198 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
2199 .next = NEXT(item_mpls),
2202 [ITEM_MPLS_LABEL] = {
2204 .help = "MPLS label",
2205 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
2206 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2212 .help = "MPLS Traffic Class",
2213 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
2214 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2220 .help = "MPLS Bottom-of-Stack",
2221 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
2222 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2228 .help = "match GRE header",
2229 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
2230 .next = NEXT(item_gre),
2233 [ITEM_GRE_PROTO] = {
2235 .help = "GRE protocol type",
2236 .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
2237 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2240 [ITEM_GRE_C_RSVD0_VER] = {
2241 .name = "c_rsvd0_ver",
2243 "checksum (1b), undefined (1b), key bit (1b),"
2244 " sequence number (1b), reserved 0 (9b),"
2246 .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
2247 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2250 [ITEM_GRE_C_BIT] = {
2252 .help = "checksum bit (C)",
2253 .next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
2254 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2256 "\x80\x00\x00\x00")),
2258 [ITEM_GRE_S_BIT] = {
2260 .help = "sequence number bit (S)",
2261 .next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
2262 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2264 "\x10\x00\x00\x00")),
2266 [ITEM_GRE_K_BIT] = {
2268 .help = "key bit (K)",
2269 .next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
2270 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2272 "\x20\x00\x00\x00")),
2276 .help = "fuzzy pattern match, expect faster than default",
2277 .priv = PRIV_ITEM(FUZZY,
2278 sizeof(struct rte_flow_item_fuzzy)),
2279 .next = NEXT(item_fuzzy),
2282 [ITEM_FUZZY_THRESH] = {
2284 .help = "match accuracy threshold",
2285 .next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param),
2286 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
2291 .help = "match GTP header",
2292 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
2293 .next = NEXT(item_gtp),
2298 .help = "tunnel endpoint identifier",
2299 .next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
2300 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
2304 .help = "match GTP header",
2305 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
2306 .next = NEXT(item_gtp),
2311 .help = "match GTP header",
2312 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
2313 .next = NEXT(item_gtp),
2318 .help = "match GENEVE header",
2319 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
2320 .next = NEXT(item_geneve),
2323 [ITEM_GENEVE_VNI] = {
2325 .help = "virtual network identifier",
2326 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
2327 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
2329 [ITEM_GENEVE_PROTO] = {
2331 .help = "GENEVE protocol type",
2332 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
2333 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
2336 [ITEM_VXLAN_GPE] = {
2337 .name = "vxlan-gpe",
2338 .help = "match VXLAN-GPE header",
2339 .priv = PRIV_ITEM(VXLAN_GPE,
2340 sizeof(struct rte_flow_item_vxlan_gpe)),
2341 .next = NEXT(item_vxlan_gpe),
2344 [ITEM_VXLAN_GPE_VNI] = {
2346 .help = "VXLAN-GPE identifier",
2347 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(UNSIGNED), item_param),
2348 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
2351 [ITEM_ARP_ETH_IPV4] = {
2352 .name = "arp_eth_ipv4",
2353 .help = "match ARP header for Ethernet/IPv4",
2354 .priv = PRIV_ITEM(ARP_ETH_IPV4,
2355 sizeof(struct rte_flow_item_arp_eth_ipv4)),
2356 .next = NEXT(item_arp_eth_ipv4),
2359 [ITEM_ARP_ETH_IPV4_SHA] = {
2361 .help = "sender hardware address",
2362 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
2364 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2367 [ITEM_ARP_ETH_IPV4_SPA] = {
2369 .help = "sender IPv4 address",
2370 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
2372 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2375 [ITEM_ARP_ETH_IPV4_THA] = {
2377 .help = "target hardware address",
2378 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
2380 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2383 [ITEM_ARP_ETH_IPV4_TPA] = {
2385 .help = "target IPv4 address",
2386 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
2388 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2393 .help = "match presence of any IPv6 extension header",
2394 .priv = PRIV_ITEM(IPV6_EXT,
2395 sizeof(struct rte_flow_item_ipv6_ext)),
2396 .next = NEXT(item_ipv6_ext),
2399 [ITEM_IPV6_EXT_NEXT_HDR] = {
2401 .help = "next header",
2402 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
2403 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
2408 .help = "match any ICMPv6 header",
2409 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
2410 .next = NEXT(item_icmp6),
2413 [ITEM_ICMP6_TYPE] = {
2415 .help = "ICMPv6 type",
2416 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2417 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2420 [ITEM_ICMP6_CODE] = {
2422 .help = "ICMPv6 code",
2423 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2424 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2427 [ITEM_ICMP6_ND_NS] = {
2428 .name = "icmp6_nd_ns",
2429 .help = "match ICMPv6 neighbor discovery solicitation",
2430 .priv = PRIV_ITEM(ICMP6_ND_NS,
2431 sizeof(struct rte_flow_item_icmp6_nd_ns)),
2432 .next = NEXT(item_icmp6_nd_ns),
2435 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
2436 .name = "target_addr",
2437 .help = "target address",
2438 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR),
2440 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
2443 [ITEM_ICMP6_ND_NA] = {
2444 .name = "icmp6_nd_na",
2445 .help = "match ICMPv6 neighbor discovery advertisement",
2446 .priv = PRIV_ITEM(ICMP6_ND_NA,
2447 sizeof(struct rte_flow_item_icmp6_nd_na)),
2448 .next = NEXT(item_icmp6_nd_na),
2451 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
2452 .name = "target_addr",
2453 .help = "target address",
2454 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR),
2456 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
2459 [ITEM_ICMP6_ND_OPT] = {
2460 .name = "icmp6_nd_opt",
2461 .help = "match presence of any ICMPv6 neighbor discovery"
2463 .priv = PRIV_ITEM(ICMP6_ND_OPT,
2464 sizeof(struct rte_flow_item_icmp6_nd_opt)),
2465 .next = NEXT(item_icmp6_nd_opt),
2468 [ITEM_ICMP6_ND_OPT_TYPE] = {
2470 .help = "ND option type",
2471 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED),
2473 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
2476 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
2477 .name = "icmp6_nd_opt_sla_eth",
2478 .help = "match ICMPv6 neighbor discovery source Ethernet"
2479 " link-layer address option",
2481 (ICMP6_ND_OPT_SLA_ETH,
2482 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
2483 .next = NEXT(item_icmp6_nd_opt_sla_eth),
2486 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
2488 .help = "source Ethernet LLA",
2489 .next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR),
2491 .args = ARGS(ARGS_ENTRY_HTON
2492 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
2494 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
2495 .name = "icmp6_nd_opt_tla_eth",
2496 .help = "match ICMPv6 neighbor discovery target Ethernet"
2497 " link-layer address option",
2499 (ICMP6_ND_OPT_TLA_ETH,
2500 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
2501 .next = NEXT(item_icmp6_nd_opt_tla_eth),
2504 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
2506 .help = "target Ethernet LLA",
2507 .next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR),
2509 .args = ARGS(ARGS_ENTRY_HTON
2510 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
2514 .help = "match metadata header",
2515 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
2516 .next = NEXT(item_meta),
2519 [ITEM_META_DATA] = {
2521 .help = "metadata value",
2522 .next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
2523 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
2524 data, "\xff\xff\xff\xff")),
2528 .help = "match GRE key",
2529 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
2530 .next = NEXT(item_gre_key),
2533 [ITEM_GRE_KEY_VALUE] = {
2535 .help = "key value",
2536 .next = NEXT(item_gre_key, NEXT_ENTRY(UNSIGNED), item_param),
2537 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
2541 .help = "match GTP extension header with type 0x85",
2542 .priv = PRIV_ITEM(GTP_PSC,
2543 sizeof(struct rte_flow_item_gtp_psc)),
2544 .next = NEXT(item_gtp_psc),
2547 [ITEM_GTP_PSC_QFI] = {
2549 .help = "QoS flow identifier",
2550 .next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
2551 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
2554 [ITEM_GTP_PSC_PDU_T] = {
2557 .next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
2558 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
2563 .help = "match PPPoE session header",
2564 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
2565 .next = NEXT(item_pppoes),
2570 .help = "match PPPoE discovery header",
2571 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
2572 .next = NEXT(item_pppoed),
2575 [ITEM_PPPOE_SEID] = {
2577 .help = "session identifier",
2578 .next = NEXT(item_pppoes, NEXT_ENTRY(UNSIGNED), item_param),
2579 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
2582 [ITEM_PPPOE_PROTO_ID] = {
2584 .help = "match PPPoE session protocol identifier",
2585 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
2586 sizeof(struct rte_flow_item_pppoe_proto_id)),
2587 .next = NEXT(item_pppoe_proto_id),
2592 .help = "matches higig2 header",
2593 .priv = PRIV_ITEM(HIGIG2,
2594 sizeof(struct rte_flow_item_higig2_hdr)),
2595 .next = NEXT(item_higig2),
2598 [ITEM_HIGIG2_CLASSIFICATION] = {
2599 .name = "classification",
2600 .help = "matches classification of higig2 header",
2601 .next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
2602 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
2603 hdr.ppt1.classification)),
2605 [ITEM_HIGIG2_VID] = {
2607 .help = "matches vid of higig2 header",
2608 .next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
2609 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
2614 .help = "match tag value",
2615 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
2616 .next = NEXT(item_tag),
2621 .help = "tag value to match",
2622 .next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED), item_param),
2623 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
2625 [ITEM_TAG_INDEX] = {
2627 .help = "index of tag array to match",
2628 .next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED),
2629 NEXT_ENTRY(ITEM_PARAM_IS)),
2630 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
2632 [ITEM_L2TPV3OIP] = {
2633 .name = "l2tpv3oip",
2634 .help = "match L2TPv3 over IP header",
2635 .priv = PRIV_ITEM(L2TPV3OIP,
2636 sizeof(struct rte_flow_item_l2tpv3oip)),
2637 .next = NEXT(item_l2tpv3oip),
2640 [ITEM_L2TPV3OIP_SESSION_ID] = {
2641 .name = "session_id",
2642 .help = "session identifier",
2643 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(UNSIGNED), item_param),
2644 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
2649 .help = "match ESP header",
2650 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
2651 .next = NEXT(item_esp),
2656 .help = "security policy index",
2657 .next = NEXT(item_esp, NEXT_ENTRY(UNSIGNED), item_param),
2658 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
2661 /* Validate/create actions. */
2664 .help = "submit a list of associated actions",
2665 .next = NEXT(next_action),
2670 .help = "specify next action",
2671 .next = NEXT(next_action),
2675 .help = "end list of actions",
2676 .priv = PRIV_ACTION(END, 0),
2681 .help = "no-op action",
2682 .priv = PRIV_ACTION(VOID, 0),
2683 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2686 [ACTION_PASSTHRU] = {
2688 .help = "let subsequent rule process matched packets",
2689 .priv = PRIV_ACTION(PASSTHRU, 0),
2690 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2695 .help = "redirect traffic to a given group",
2696 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
2697 .next = NEXT(action_jump),
2700 [ACTION_JUMP_GROUP] = {
2702 .help = "group to redirect traffic to",
2703 .next = NEXT(action_jump, NEXT_ENTRY(UNSIGNED)),
2704 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
2705 .call = parse_vc_conf,
2709 .help = "attach 32 bit value to packets",
2710 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
2711 .next = NEXT(action_mark),
2714 [ACTION_MARK_ID] = {
2716 .help = "32 bit value to return with packets",
2717 .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
2718 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
2719 .call = parse_vc_conf,
2723 .help = "flag packets",
2724 .priv = PRIV_ACTION(FLAG, 0),
2725 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2730 .help = "assign packets to a given queue index",
2731 .priv = PRIV_ACTION(QUEUE,
2732 sizeof(struct rte_flow_action_queue)),
2733 .next = NEXT(action_queue),
2736 [ACTION_QUEUE_INDEX] = {
2738 .help = "queue index to use",
2739 .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
2740 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
2741 .call = parse_vc_conf,
2745 .help = "drop packets (note: passthru has priority)",
2746 .priv = PRIV_ACTION(DROP, 0),
2747 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2752 .help = "enable counters for this rule",
2753 .priv = PRIV_ACTION(COUNT,
2754 sizeof(struct rte_flow_action_count)),
2755 .next = NEXT(action_count),
2758 [ACTION_COUNT_ID] = {
2759 .name = "identifier",
2760 .help = "counter identifier to use",
2761 .next = NEXT(action_count, NEXT_ENTRY(UNSIGNED)),
2762 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
2763 .call = parse_vc_conf,
2765 [ACTION_COUNT_SHARED] = {
2767 .help = "shared counter",
2768 .next = NEXT(action_count, NEXT_ENTRY(BOOLEAN)),
2769 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
2771 .call = parse_vc_conf,
2775 .help = "spread packets among several queues",
2776 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
2777 .next = NEXT(action_rss),
2778 .call = parse_vc_action_rss,
2780 [ACTION_RSS_FUNC] = {
2782 .help = "RSS hash function to apply",
2783 .next = NEXT(action_rss,
2784 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
2785 ACTION_RSS_FUNC_TOEPLITZ,
2786 ACTION_RSS_FUNC_SIMPLE_XOR,
2787 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
2789 [ACTION_RSS_FUNC_DEFAULT] = {
2791 .help = "default hash function",
2792 .call = parse_vc_action_rss_func,
2794 [ACTION_RSS_FUNC_TOEPLITZ] = {
2796 .help = "Toeplitz hash function",
2797 .call = parse_vc_action_rss_func,
2799 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
2800 .name = "simple_xor",
2801 .help = "simple XOR hash function",
2802 .call = parse_vc_action_rss_func,
2804 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
2805 .name = "symmetric_toeplitz",
2806 .help = "Symmetric Toeplitz hash function",
2807 .call = parse_vc_action_rss_func,
2809 [ACTION_RSS_LEVEL] = {
2811 .help = "encapsulation level for \"types\"",
2812 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2813 .args = ARGS(ARGS_ENTRY_ARB
2814 (offsetof(struct action_rss_data, conf) +
2815 offsetof(struct rte_flow_action_rss, level),
2816 sizeof(((struct rte_flow_action_rss *)0)->
2819 [ACTION_RSS_TYPES] = {
2821 .help = "specific RSS hash types",
2822 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
2824 [ACTION_RSS_TYPE] = {
2826 .help = "RSS hash type",
2827 .call = parse_vc_action_rss_type,
2828 .comp = comp_vc_action_rss_type,
2830 [ACTION_RSS_KEY] = {
2832 .help = "RSS hash key",
2833 .next = NEXT(action_rss, NEXT_ENTRY(HEX)),
2834 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
2836 (offsetof(struct action_rss_data, conf) +
2837 offsetof(struct rte_flow_action_rss, key_len),
2838 sizeof(((struct rte_flow_action_rss *)0)->
2840 ARGS_ENTRY(struct action_rss_data, key)),
2842 [ACTION_RSS_KEY_LEN] = {
2844 .help = "RSS hash key length in bytes",
2845 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2846 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
2847 (offsetof(struct action_rss_data, conf) +
2848 offsetof(struct rte_flow_action_rss, key_len),
2849 sizeof(((struct rte_flow_action_rss *)0)->
2852 RSS_HASH_KEY_LENGTH)),
2854 [ACTION_RSS_QUEUES] = {
2856 .help = "queue indices to use",
2857 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
2858 .call = parse_vc_conf,
2860 [ACTION_RSS_QUEUE] = {
2862 .help = "queue index",
2863 .call = parse_vc_action_rss_queue,
2864 .comp = comp_vc_action_rss_queue,
2868 .help = "direct traffic to physical function",
2869 .priv = PRIV_ACTION(PF, 0),
2870 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2875 .help = "direct traffic to a virtual function ID",
2876 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
2877 .next = NEXT(action_vf),
2880 [ACTION_VF_ORIGINAL] = {
2882 .help = "use original VF ID if possible",
2883 .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
2884 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
2886 .call = parse_vc_conf,
2891 .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
2892 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
2893 .call = parse_vc_conf,
2895 [ACTION_PHY_PORT] = {
2897 .help = "direct packets to physical port index",
2898 .priv = PRIV_ACTION(PHY_PORT,
2899 sizeof(struct rte_flow_action_phy_port)),
2900 .next = NEXT(action_phy_port),
2903 [ACTION_PHY_PORT_ORIGINAL] = {
2905 .help = "use original port index if possible",
2906 .next = NEXT(action_phy_port, NEXT_ENTRY(BOOLEAN)),
2907 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
2909 .call = parse_vc_conf,
2911 [ACTION_PHY_PORT_INDEX] = {
2913 .help = "physical port index",
2914 .next = NEXT(action_phy_port, NEXT_ENTRY(UNSIGNED)),
2915 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
2917 .call = parse_vc_conf,
2919 [ACTION_PORT_ID] = {
2921 .help = "direct matching traffic to a given DPDK port ID",
2922 .priv = PRIV_ACTION(PORT_ID,
2923 sizeof(struct rte_flow_action_port_id)),
2924 .next = NEXT(action_port_id),
2927 [ACTION_PORT_ID_ORIGINAL] = {
2929 .help = "use original DPDK port ID if possible",
2930 .next = NEXT(action_port_id, NEXT_ENTRY(BOOLEAN)),
2931 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
2933 .call = parse_vc_conf,
2935 [ACTION_PORT_ID_ID] = {
2937 .help = "DPDK port ID",
2938 .next = NEXT(action_port_id, NEXT_ENTRY(UNSIGNED)),
2939 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
2940 .call = parse_vc_conf,
2944 .help = "meter the directed packets at given id",
2945 .priv = PRIV_ACTION(METER,
2946 sizeof(struct rte_flow_action_meter)),
2947 .next = NEXT(action_meter),
2950 [ACTION_METER_ID] = {
2952 .help = "meter id to use",
2953 .next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
2954 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
2955 .call = parse_vc_conf,
2957 [ACTION_OF_SET_MPLS_TTL] = {
2958 .name = "of_set_mpls_ttl",
2959 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
2962 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
2963 .next = NEXT(action_of_set_mpls_ttl),
2966 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
2969 .next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)),
2970 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
2972 .call = parse_vc_conf,
2974 [ACTION_OF_DEC_MPLS_TTL] = {
2975 .name = "of_dec_mpls_ttl",
2976 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
2977 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
2978 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2981 [ACTION_OF_SET_NW_TTL] = {
2982 .name = "of_set_nw_ttl",
2983 .help = "OpenFlow's OFPAT_SET_NW_TTL",
2986 sizeof(struct rte_flow_action_of_set_nw_ttl)),
2987 .next = NEXT(action_of_set_nw_ttl),
2990 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
2993 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)),
2994 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
2996 .call = parse_vc_conf,
2998 [ACTION_OF_DEC_NW_TTL] = {
2999 .name = "of_dec_nw_ttl",
3000 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
3001 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
3002 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3005 [ACTION_OF_COPY_TTL_OUT] = {
3006 .name = "of_copy_ttl_out",
3007 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
3008 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
3009 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3012 [ACTION_OF_COPY_TTL_IN] = {
3013 .name = "of_copy_ttl_in",
3014 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
3015 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
3016 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3019 [ACTION_OF_POP_VLAN] = {
3020 .name = "of_pop_vlan",
3021 .help = "OpenFlow's OFPAT_POP_VLAN",
3022 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
3023 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3026 [ACTION_OF_PUSH_VLAN] = {
3027 .name = "of_push_vlan",
3028 .help = "OpenFlow's OFPAT_PUSH_VLAN",
3031 sizeof(struct rte_flow_action_of_push_vlan)),
3032 .next = NEXT(action_of_push_vlan),
3035 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
3036 .name = "ethertype",
3037 .help = "EtherType",
3038 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)),
3039 .args = ARGS(ARGS_ENTRY_HTON
3040 (struct rte_flow_action_of_push_vlan,
3042 .call = parse_vc_conf,
3044 [ACTION_OF_SET_VLAN_VID] = {
3045 .name = "of_set_vlan_vid",
3046 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
3049 sizeof(struct rte_flow_action_of_set_vlan_vid)),
3050 .next = NEXT(action_of_set_vlan_vid),
3053 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
3056 .next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)),
3057 .args = ARGS(ARGS_ENTRY_HTON
3058 (struct rte_flow_action_of_set_vlan_vid,
3060 .call = parse_vc_conf,
3062 [ACTION_OF_SET_VLAN_PCP] = {
3063 .name = "of_set_vlan_pcp",
3064 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
3067 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
3068 .next = NEXT(action_of_set_vlan_pcp),
3071 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
3073 .help = "VLAN priority",
3074 .next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)),
3075 .args = ARGS(ARGS_ENTRY_HTON
3076 (struct rte_flow_action_of_set_vlan_pcp,
3078 .call = parse_vc_conf,
3080 [ACTION_OF_POP_MPLS] = {
3081 .name = "of_pop_mpls",
3082 .help = "OpenFlow's OFPAT_POP_MPLS",
3083 .priv = PRIV_ACTION(OF_POP_MPLS,
3084 sizeof(struct rte_flow_action_of_pop_mpls)),
3085 .next = NEXT(action_of_pop_mpls),
3088 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
3089 .name = "ethertype",
3090 .help = "EtherType",
3091 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)),
3092 .args = ARGS(ARGS_ENTRY_HTON
3093 (struct rte_flow_action_of_pop_mpls,
3095 .call = parse_vc_conf,
3097 [ACTION_OF_PUSH_MPLS] = {
3098 .name = "of_push_mpls",
3099 .help = "OpenFlow's OFPAT_PUSH_MPLS",
3102 sizeof(struct rte_flow_action_of_push_mpls)),
3103 .next = NEXT(action_of_push_mpls),
3106 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
3107 .name = "ethertype",
3108 .help = "EtherType",
3109 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)),
3110 .args = ARGS(ARGS_ENTRY_HTON
3111 (struct rte_flow_action_of_push_mpls,
3113 .call = parse_vc_conf,
3115 [ACTION_VXLAN_ENCAP] = {
3116 .name = "vxlan_encap",
3117 .help = "VXLAN encapsulation, uses configuration set by \"set"
3119 .priv = PRIV_ACTION(VXLAN_ENCAP,
3120 sizeof(struct action_vxlan_encap_data)),
3121 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3122 .call = parse_vc_action_vxlan_encap,
3124 [ACTION_VXLAN_DECAP] = {
3125 .name = "vxlan_decap",
3126 .help = "Performs a decapsulation action by stripping all"
3127 " headers of the VXLAN tunnel network overlay from the"
3129 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
3130 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3133 [ACTION_NVGRE_ENCAP] = {
3134 .name = "nvgre_encap",
3135 .help = "NVGRE encapsulation, uses configuration set by \"set"
3137 .priv = PRIV_ACTION(NVGRE_ENCAP,
3138 sizeof(struct action_nvgre_encap_data)),
3139 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3140 .call = parse_vc_action_nvgre_encap,
3142 [ACTION_NVGRE_DECAP] = {
3143 .name = "nvgre_decap",
3144 .help = "Performs a decapsulation action by stripping all"
3145 " headers of the NVGRE tunnel network overlay from the"
3147 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
3148 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3151 [ACTION_L2_ENCAP] = {
3153 .help = "l2 encap, uses configuration set by"
3154 " \"set l2_encap\"",
3155 .priv = PRIV_ACTION(RAW_ENCAP,
3156 sizeof(struct action_raw_encap_data)),
3157 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3158 .call = parse_vc_action_l2_encap,
3160 [ACTION_L2_DECAP] = {
3162 .help = "l2 decap, uses configuration set by"
3163 " \"set l2_decap\"",
3164 .priv = PRIV_ACTION(RAW_DECAP,
3165 sizeof(struct action_raw_decap_data)),
3166 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3167 .call = parse_vc_action_l2_decap,
3169 [ACTION_MPLSOGRE_ENCAP] = {
3170 .name = "mplsogre_encap",
3171 .help = "mplsogre encapsulation, uses configuration set by"
3172 " \"set mplsogre_encap\"",
3173 .priv = PRIV_ACTION(RAW_ENCAP,
3174 sizeof(struct action_raw_encap_data)),
3175 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3176 .call = parse_vc_action_mplsogre_encap,
3178 [ACTION_MPLSOGRE_DECAP] = {
3179 .name = "mplsogre_decap",
3180 .help = "mplsogre decapsulation, uses configuration set by"
3181 " \"set mplsogre_decap\"",
3182 .priv = PRIV_ACTION(RAW_DECAP,
3183 sizeof(struct action_raw_decap_data)),
3184 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3185 .call = parse_vc_action_mplsogre_decap,
3187 [ACTION_MPLSOUDP_ENCAP] = {
3188 .name = "mplsoudp_encap",
3189 .help = "mplsoudp encapsulation, uses configuration set by"
3190 " \"set mplsoudp_encap\"",
3191 .priv = PRIV_ACTION(RAW_ENCAP,
3192 sizeof(struct action_raw_encap_data)),
3193 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3194 .call = parse_vc_action_mplsoudp_encap,
3196 [ACTION_MPLSOUDP_DECAP] = {
3197 .name = "mplsoudp_decap",
3198 .help = "mplsoudp decapsulation, uses configuration set by"
3199 " \"set mplsoudp_decap\"",
3200 .priv = PRIV_ACTION(RAW_DECAP,
3201 sizeof(struct action_raw_decap_data)),
3202 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3203 .call = parse_vc_action_mplsoudp_decap,
3205 [ACTION_SET_IPV4_SRC] = {
3206 .name = "set_ipv4_src",
3207 .help = "Set a new IPv4 source address in the outermost"
3209 .priv = PRIV_ACTION(SET_IPV4_SRC,
3210 sizeof(struct rte_flow_action_set_ipv4)),
3211 .next = NEXT(action_set_ipv4_src),
3214 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
3215 .name = "ipv4_addr",
3216 .help = "new IPv4 source address to set",
3217 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(IPV4_ADDR)),
3218 .args = ARGS(ARGS_ENTRY_HTON
3219 (struct rte_flow_action_set_ipv4, ipv4_addr)),
3220 .call = parse_vc_conf,
3222 [ACTION_SET_IPV4_DST] = {
3223 .name = "set_ipv4_dst",
3224 .help = "Set a new IPv4 destination address in the outermost"
3226 .priv = PRIV_ACTION(SET_IPV4_DST,
3227 sizeof(struct rte_flow_action_set_ipv4)),
3228 .next = NEXT(action_set_ipv4_dst),
3231 [ACTION_SET_IPV4_DST_IPV4_DST] = {
3232 .name = "ipv4_addr",
3233 .help = "new IPv4 destination address to set",
3234 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(IPV4_ADDR)),
3235 .args = ARGS(ARGS_ENTRY_HTON
3236 (struct rte_flow_action_set_ipv4, ipv4_addr)),
3237 .call = parse_vc_conf,
3239 [ACTION_SET_IPV6_SRC] = {
3240 .name = "set_ipv6_src",
3241 .help = "Set a new IPv6 source address in the outermost"
3243 .priv = PRIV_ACTION(SET_IPV6_SRC,
3244 sizeof(struct rte_flow_action_set_ipv6)),
3245 .next = NEXT(action_set_ipv6_src),
3248 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
3249 .name = "ipv6_addr",
3250 .help = "new IPv6 source address to set",
3251 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(IPV6_ADDR)),
3252 .args = ARGS(ARGS_ENTRY_HTON
3253 (struct rte_flow_action_set_ipv6, ipv6_addr)),
3254 .call = parse_vc_conf,
3256 [ACTION_SET_IPV6_DST] = {
3257 .name = "set_ipv6_dst",
3258 .help = "Set a new IPv6 destination address in the outermost"
3260 .priv = PRIV_ACTION(SET_IPV6_DST,
3261 sizeof(struct rte_flow_action_set_ipv6)),
3262 .next = NEXT(action_set_ipv6_dst),
3265 [ACTION_SET_IPV6_DST_IPV6_DST] = {
3266 .name = "ipv6_addr",
3267 .help = "new IPv6 destination address to set",
3268 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(IPV6_ADDR)),
3269 .args = ARGS(ARGS_ENTRY_HTON
3270 (struct rte_flow_action_set_ipv6, ipv6_addr)),
3271 .call = parse_vc_conf,
3273 [ACTION_SET_TP_SRC] = {
3274 .name = "set_tp_src",
3275 .help = "set a new source port number in the outermost"
3277 .priv = PRIV_ACTION(SET_TP_SRC,
3278 sizeof(struct rte_flow_action_set_tp)),
3279 .next = NEXT(action_set_tp_src),
3282 [ACTION_SET_TP_SRC_TP_SRC] = {
3284 .help = "new source port number to set",
3285 .next = NEXT(action_set_tp_src, NEXT_ENTRY(UNSIGNED)),
3286 .args = ARGS(ARGS_ENTRY_HTON
3287 (struct rte_flow_action_set_tp, port)),
3288 .call = parse_vc_conf,
3290 [ACTION_SET_TP_DST] = {
3291 .name = "set_tp_dst",
3292 .help = "set a new destination port number in the outermost"
3294 .priv = PRIV_ACTION(SET_TP_DST,
3295 sizeof(struct rte_flow_action_set_tp)),
3296 .next = NEXT(action_set_tp_dst),
3299 [ACTION_SET_TP_DST_TP_DST] = {
3301 .help = "new destination port number to set",
3302 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(UNSIGNED)),
3303 .args = ARGS(ARGS_ENTRY_HTON
3304 (struct rte_flow_action_set_tp, port)),
3305 .call = parse_vc_conf,
3307 [ACTION_MAC_SWAP] = {
3309 .help = "Swap the source and destination MAC addresses"
3310 " in the outermost Ethernet header",
3311 .priv = PRIV_ACTION(MAC_SWAP, 0),
3312 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3315 [ACTION_DEC_TTL] = {
3317 .help = "decrease network TTL if available",
3318 .priv = PRIV_ACTION(DEC_TTL, 0),
3319 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3322 [ACTION_SET_TTL] = {
3324 .help = "set ttl value",
3325 .priv = PRIV_ACTION(SET_TTL,
3326 sizeof(struct rte_flow_action_set_ttl)),
3327 .next = NEXT(action_set_ttl),
3330 [ACTION_SET_TTL_TTL] = {
3331 .name = "ttl_value",
3332 .help = "new ttl value to set",
3333 .next = NEXT(action_set_ttl, NEXT_ENTRY(UNSIGNED)),
3334 .args = ARGS(ARGS_ENTRY_HTON
3335 (struct rte_flow_action_set_ttl, ttl_value)),
3336 .call = parse_vc_conf,
3338 [ACTION_SET_MAC_SRC] = {
3339 .name = "set_mac_src",
3340 .help = "set source mac address",
3341 .priv = PRIV_ACTION(SET_MAC_SRC,
3342 sizeof(struct rte_flow_action_set_mac)),
3343 .next = NEXT(action_set_mac_src),
3346 [ACTION_SET_MAC_SRC_MAC_SRC] = {
3348 .help = "new source mac address",
3349 .next = NEXT(action_set_mac_src, NEXT_ENTRY(MAC_ADDR)),
3350 .args = ARGS(ARGS_ENTRY_HTON
3351 (struct rte_flow_action_set_mac, mac_addr)),
3352 .call = parse_vc_conf,
3354 [ACTION_SET_MAC_DST] = {
3355 .name = "set_mac_dst",
3356 .help = "set destination mac address",
3357 .priv = PRIV_ACTION(SET_MAC_DST,
3358 sizeof(struct rte_flow_action_set_mac)),
3359 .next = NEXT(action_set_mac_dst),
3362 [ACTION_SET_MAC_DST_MAC_DST] = {
3364 .help = "new destination mac address to set",
3365 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(MAC_ADDR)),
3366 .args = ARGS(ARGS_ENTRY_HTON
3367 (struct rte_flow_action_set_mac, mac_addr)),
3368 .call = parse_vc_conf,
3370 [ACTION_INC_TCP_SEQ] = {
3371 .name = "inc_tcp_seq",
3372 .help = "increase TCP sequence number",
3373 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
3374 .next = NEXT(action_inc_tcp_seq),
3377 [ACTION_INC_TCP_SEQ_VALUE] = {
3379 .help = "the value to increase TCP sequence number by",
3380 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(UNSIGNED)),
3381 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3382 .call = parse_vc_conf,
3384 [ACTION_DEC_TCP_SEQ] = {
3385 .name = "dec_tcp_seq",
3386 .help = "decrease TCP sequence number",
3387 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
3388 .next = NEXT(action_dec_tcp_seq),
3391 [ACTION_DEC_TCP_SEQ_VALUE] = {
3393 .help = "the value to decrease TCP sequence number by",
3394 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(UNSIGNED)),
3395 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3396 .call = parse_vc_conf,
3398 [ACTION_INC_TCP_ACK] = {
3399 .name = "inc_tcp_ack",
3400 .help = "increase TCP acknowledgment number",
3401 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
3402 .next = NEXT(action_inc_tcp_ack),
3405 [ACTION_INC_TCP_ACK_VALUE] = {
3407 .help = "the value to increase TCP acknowledgment number by",
3408 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(UNSIGNED)),
3409 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3410 .call = parse_vc_conf,
3412 [ACTION_DEC_TCP_ACK] = {
3413 .name = "dec_tcp_ack",
3414 .help = "decrease TCP acknowledgment number",
3415 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
3416 .next = NEXT(action_dec_tcp_ack),
3419 [ACTION_DEC_TCP_ACK_VALUE] = {
3421 .help = "the value to decrease TCP acknowledgment number by",
3422 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(UNSIGNED)),
3423 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3424 .call = parse_vc_conf,
3426 [ACTION_RAW_ENCAP] = {
3427 .name = "raw_encap",
3428 .help = "encapsulation data, defined by set raw_encap",
3429 .priv = PRIV_ACTION(RAW_ENCAP,
3430 sizeof(struct action_raw_encap_data)),
3431 .next = NEXT(action_raw_encap),
3432 .call = parse_vc_action_raw_encap,
3434 [ACTION_RAW_ENCAP_INDEX] = {
3436 .help = "the index of raw_encap_confs",
3437 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
3439 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
3442 .help = "unsigned integer value",
3443 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3444 .call = parse_vc_action_raw_encap_index,
3445 .comp = comp_set_raw_index,
3447 [ACTION_RAW_DECAP] = {
3448 .name = "raw_decap",
3449 .help = "decapsulation data, defined by set raw_encap",
3450 .priv = PRIV_ACTION(RAW_DECAP,
3451 sizeof(struct action_raw_decap_data)),
3452 .next = NEXT(action_raw_decap),
3453 .call = parse_vc_action_raw_decap,
3455 [ACTION_RAW_DECAP_INDEX] = {
3457 .help = "the index of raw_encap_confs",
3458 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
3460 [ACTION_RAW_DECAP_INDEX_VALUE] = {
3463 .help = "unsigned integer value",
3464 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3465 .call = parse_vc_action_raw_decap_index,
3466 .comp = comp_set_raw_index,
3468 /* Top level command. */
3471 .help = "set raw encap/decap data",
3472 .type = "set raw_encap|raw_decap <index> <pattern>",
3473 .next = NEXT(NEXT_ENTRY
3476 .call = parse_set_init,
3478 /* Sub-level commands. */
3480 .name = "raw_encap",
3481 .help = "set raw encap data",
3482 .next = NEXT(next_set_raw),
3483 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3484 (offsetof(struct buffer, port),
3485 sizeof(((struct buffer *)0)->port),
3486 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
3487 .call = parse_set_raw_encap_decap,
3490 .name = "raw_decap",
3491 .help = "set raw decap data",
3492 .next = NEXT(next_set_raw),
3493 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3494 (offsetof(struct buffer, port),
3495 sizeof(((struct buffer *)0)->port),
3496 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
3497 .call = parse_set_raw_encap_decap,
3502 .help = "index of raw_encap/raw_decap data",
3503 .next = NEXT(next_item),
3506 [ACTION_SET_TAG] = {
3509 .priv = PRIV_ACTION(SET_TAG,
3510 sizeof(struct rte_flow_action_set_tag)),
3511 .next = NEXT(action_set_tag),
3514 [ACTION_SET_TAG_INDEX] = {
3516 .help = "index of tag array",
3517 .next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
3518 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
3519 .call = parse_vc_conf,
3521 [ACTION_SET_TAG_DATA] = {
3523 .help = "tag value",
3524 .next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
3525 .args = ARGS(ARGS_ENTRY
3526 (struct rte_flow_action_set_tag, data)),
3527 .call = parse_vc_conf,
3529 [ACTION_SET_TAG_MASK] = {
3531 .help = "mask for tag value",
3532 .next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
3533 .args = ARGS(ARGS_ENTRY
3534 (struct rte_flow_action_set_tag, mask)),
3535 .call = parse_vc_conf,
3537 [ACTION_SET_META] = {
3539 .help = "set metadata",
3540 .priv = PRIV_ACTION(SET_META,
3541 sizeof(struct rte_flow_action_set_meta)),
3542 .next = NEXT(action_set_meta),
3543 .call = parse_vc_action_set_meta,
3545 [ACTION_SET_META_DATA] = {
3547 .help = "metadata value",
3548 .next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
3549 .args = ARGS(ARGS_ENTRY
3550 (struct rte_flow_action_set_meta, data)),
3551 .call = parse_vc_conf,
3553 [ACTION_SET_META_MASK] = {
3555 .help = "mask for metadata value",
3556 .next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
3557 .args = ARGS(ARGS_ENTRY
3558 (struct rte_flow_action_set_meta, mask)),
3559 .call = parse_vc_conf,
3561 [ACTION_SET_IPV4_DSCP] = {
3562 .name = "set_ipv4_dscp",
3563 .help = "set DSCP value",
3564 .priv = PRIV_ACTION(SET_IPV4_DSCP,
3565 sizeof(struct rte_flow_action_set_dscp)),
3566 .next = NEXT(action_set_ipv4_dscp),
3569 [ACTION_SET_IPV4_DSCP_VALUE] = {
3570 .name = "dscp_value",
3571 .help = "new IPv4 DSCP value to set",
3572 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(UNSIGNED)),
3573 .args = ARGS(ARGS_ENTRY
3574 (struct rte_flow_action_set_dscp, dscp)),
3575 .call = parse_vc_conf,
3577 [ACTION_SET_IPV6_DSCP] = {
3578 .name = "set_ipv6_dscp",
3579 .help = "set DSCP value",
3580 .priv = PRIV_ACTION(SET_IPV6_DSCP,
3581 sizeof(struct rte_flow_action_set_dscp)),
3582 .next = NEXT(action_set_ipv6_dscp),
3585 [ACTION_SET_IPV6_DSCP_VALUE] = {
3586 .name = "dscp_value",
3587 .help = "new IPv6 DSCP value to set",
3588 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(UNSIGNED)),
3589 .args = ARGS(ARGS_ENTRY
3590 (struct rte_flow_action_set_dscp, dscp)),
3591 .call = parse_vc_conf,
3595 /** Remove and return last entry from argument stack. */
3596 static const struct arg *
3597 pop_args(struct context *ctx)
3599 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
3602 /** Add entry on top of the argument stack. */
3604 push_args(struct context *ctx, const struct arg *arg)
3606 if (ctx->args_num == CTX_STACK_SIZE)
3608 ctx->args[ctx->args_num++] = arg;
3612 /** Spread value into buffer according to bit-mask. */
3614 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
3616 uint32_t i = arg->size;
3624 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3633 unsigned int shift = 0;
3634 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
3636 for (shift = 0; arg->mask[i] >> shift; ++shift) {
3637 if (!(arg->mask[i] & (1 << shift)))
3642 *buf &= ~(1 << shift);
3643 *buf |= (val & 1) << shift;
3651 /** Compare a string with a partial one of a given length. */
3653 strcmp_partial(const char *full, const char *partial, size_t partial_len)
3655 int r = strncmp(full, partial, partial_len);
3659 if (strlen(full) <= partial_len)
3661 return full[partial_len];
3665 * Parse a prefix length and generate a bit-mask.
3667 * Last argument (ctx->args) is retrieved to determine mask size, storage
3668 * location and whether the result must use network byte ordering.
3671 parse_prefix(struct context *ctx, const struct token *token,
3672 const char *str, unsigned int len,
3673 void *buf, unsigned int size)
3675 const struct arg *arg = pop_args(ctx);
3676 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
3683 /* Argument is expected. */
3687 u = strtoumax(str, &end, 0);
3688 if (errno || (size_t)(end - str) != len)
3693 extra = arg_entry_bf_fill(NULL, 0, arg);
3702 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
3703 !arg_entry_bf_fill(ctx->objmask, -1, arg))
3710 if (bytes > size || bytes + !!extra > size)
3714 buf = (uint8_t *)ctx->object + arg->offset;
3715 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3717 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
3718 memset(buf, 0x00, size - bytes);
3720 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
3724 memset(buf, 0xff, bytes);
3725 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
3727 ((uint8_t *)buf)[bytes] = conv[extra];
3730 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
3733 push_args(ctx, arg);
3737 /** Default parsing function for token name matching. */
3739 parse_default(struct context *ctx, const struct token *token,
3740 const char *str, unsigned int len,
3741 void *buf, unsigned int size)
3746 if (strcmp_partial(token->name, str, len))
3751 /** Parse flow command, initialize output buffer for subsequent tokens. */
3753 parse_init(struct context *ctx, const struct token *token,
3754 const char *str, unsigned int len,
3755 void *buf, unsigned int size)
3757 struct buffer *out = buf;
3759 /* Token name must match. */
3760 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3762 /* Nothing else to do if there is no buffer. */
3765 /* Make sure buffer is large enough. */
3766 if (size < sizeof(*out))
3768 /* Initialize buffer. */
3769 memset(out, 0x00, sizeof(*out));
3770 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
3773 ctx->objmask = NULL;
3777 /** Parse tokens for validate/create commands. */
3779 parse_vc(struct context *ctx, const struct token *token,
3780 const char *str, unsigned int len,
3781 void *buf, unsigned int size)
3783 struct buffer *out = buf;
3787 /* Token name must match. */
3788 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3790 /* Nothing else to do if there is no buffer. */
3793 if (!out->command) {
3794 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
3796 if (sizeof(*out) > size)
3798 out->command = ctx->curr;
3801 ctx->objmask = NULL;
3802 out->args.vc.data = (uint8_t *)out + size;
3806 ctx->object = &out->args.vc.attr;
3807 ctx->objmask = NULL;
3808 switch (ctx->curr) {
3813 out->args.vc.attr.ingress = 1;
3816 out->args.vc.attr.egress = 1;
3819 out->args.vc.attr.transfer = 1;
3822 out->args.vc.pattern =
3823 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
3825 ctx->object = out->args.vc.pattern;
3826 ctx->objmask = NULL;
3829 out->args.vc.actions =
3830 (void *)RTE_ALIGN_CEIL((uintptr_t)
3831 (out->args.vc.pattern +
3832 out->args.vc.pattern_n),
3834 ctx->object = out->args.vc.actions;
3835 ctx->objmask = NULL;
3842 if (!out->args.vc.actions) {
3843 const struct parse_item_priv *priv = token->priv;
3844 struct rte_flow_item *item =
3845 out->args.vc.pattern + out->args.vc.pattern_n;
3847 data_size = priv->size * 3; /* spec, last, mask */
3848 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3849 (out->args.vc.data - data_size),
3851 if ((uint8_t *)item + sizeof(*item) > data)
3853 *item = (struct rte_flow_item){
3856 ++out->args.vc.pattern_n;
3858 ctx->objmask = NULL;
3860 const struct parse_action_priv *priv = token->priv;
3861 struct rte_flow_action *action =
3862 out->args.vc.actions + out->args.vc.actions_n;
3864 data_size = priv->size; /* configuration */
3865 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3866 (out->args.vc.data - data_size),
3868 if ((uint8_t *)action + sizeof(*action) > data)
3870 *action = (struct rte_flow_action){
3872 .conf = data_size ? data : NULL,
3874 ++out->args.vc.actions_n;
3875 ctx->object = action;
3876 ctx->objmask = NULL;
3878 memset(data, 0, data_size);
3879 out->args.vc.data = data;
3880 ctx->objdata = data_size;
3884 /** Parse pattern item parameter type. */
3886 parse_vc_spec(struct context *ctx, const struct token *token,
3887 const char *str, unsigned int len,
3888 void *buf, unsigned int size)
3890 struct buffer *out = buf;
3891 struct rte_flow_item *item;
3897 /* Token name must match. */
3898 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3900 /* Parse parameter types. */
3901 switch (ctx->curr) {
3902 static const enum index prefix[] = NEXT_ENTRY(PREFIX);
3908 case ITEM_PARAM_SPEC:
3911 case ITEM_PARAM_LAST:
3914 case ITEM_PARAM_PREFIX:
3915 /* Modify next token to expect a prefix. */
3916 if (ctx->next_num < 2)
3918 ctx->next[ctx->next_num - 2] = prefix;
3920 case ITEM_PARAM_MASK:
3926 /* Nothing else to do if there is no buffer. */
3929 if (!out->args.vc.pattern_n)
3931 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
3932 data_size = ctx->objdata / 3; /* spec, last, mask */
3933 /* Point to selected object. */
3934 ctx->object = out->args.vc.data + (data_size * index);
3936 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
3937 item->mask = ctx->objmask;
3939 ctx->objmask = NULL;
3940 /* Update relevant item pointer. */
3941 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
3946 /** Parse action configuration field. */
3948 parse_vc_conf(struct context *ctx, const struct token *token,
3949 const char *str, unsigned int len,
3950 void *buf, unsigned int size)
3952 struct buffer *out = buf;
3955 /* Token name must match. */
3956 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3958 /* Nothing else to do if there is no buffer. */
3961 /* Point to selected object. */
3962 ctx->object = out->args.vc.data;
3963 ctx->objmask = NULL;
3967 /** Parse RSS action. */
3969 parse_vc_action_rss(struct context *ctx, const struct token *token,
3970 const char *str, unsigned int len,
3971 void *buf, unsigned int size)
3973 struct buffer *out = buf;
3974 struct rte_flow_action *action;
3975 struct action_rss_data *action_rss_data;
3979 ret = parse_vc(ctx, token, str, len, buf, size);
3982 /* Nothing else to do if there is no buffer. */
3985 if (!out->args.vc.actions_n)
3987 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3988 /* Point to selected object. */
3989 ctx->object = out->args.vc.data;
3990 ctx->objmask = NULL;
3991 /* Set up default configuration. */
3992 action_rss_data = ctx->object;
3993 *action_rss_data = (struct action_rss_data){
3994 .conf = (struct rte_flow_action_rss){
3995 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
3998 .key_len = sizeof(action_rss_data->key),
3999 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
4000 .key = action_rss_data->key,
4001 .queue = action_rss_data->queue,
4003 .key = "testpmd's default RSS hash key, "
4004 "override it for better balancing",
4007 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
4008 action_rss_data->queue[i] = i;
4009 if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
4010 ctx->port != (portid_t)RTE_PORT_ALL) {
4011 struct rte_eth_dev_info info;
4014 ret2 = rte_eth_dev_info_get(ctx->port, &info);
4018 action_rss_data->conf.key_len =
4019 RTE_MIN(sizeof(action_rss_data->key),
4020 info.hash_key_size);
4022 action->conf = &action_rss_data->conf;
4027 * Parse func field for RSS action.
4029 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
4030 * ACTION_RSS_FUNC_* index that called this function.
4033 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
4034 const char *str, unsigned int len,
4035 void *buf, unsigned int size)
4037 struct action_rss_data *action_rss_data;
4038 enum rte_eth_hash_function func;
4042 /* Token name must match. */
4043 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4045 switch (ctx->curr) {
4046 case ACTION_RSS_FUNC_DEFAULT:
4047 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
4049 case ACTION_RSS_FUNC_TOEPLITZ:
4050 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
4052 case ACTION_RSS_FUNC_SIMPLE_XOR:
4053 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
4055 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
4056 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
4063 action_rss_data = ctx->object;
4064 action_rss_data->conf.func = func;
4069 * Parse type field for RSS action.
4071 * Valid tokens are type field names and the "end" token.
4074 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
4075 const char *str, unsigned int len,
4076 void *buf, unsigned int size)
4078 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
4079 struct action_rss_data *action_rss_data;
4085 if (ctx->curr != ACTION_RSS_TYPE)
4087 if (!(ctx->objdata >> 16) && ctx->object) {
4088 action_rss_data = ctx->object;
4089 action_rss_data->conf.types = 0;
4091 if (!strcmp_partial("end", str, len)) {
4092 ctx->objdata &= 0xffff;
4095 for (i = 0; rss_type_table[i].str; ++i)
4096 if (!strcmp_partial(rss_type_table[i].str, str, len))
4098 if (!rss_type_table[i].str)
4100 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
4102 if (ctx->next_num == RTE_DIM(ctx->next))
4104 ctx->next[ctx->next_num++] = next;
4107 action_rss_data = ctx->object;
4108 action_rss_data->conf.types |= rss_type_table[i].rss_type;
4113 * Parse queue field for RSS action.
4115 * Valid tokens are queue indices and the "end" token.
4118 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
4119 const char *str, unsigned int len,
4120 void *buf, unsigned int size)
4122 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
4123 struct action_rss_data *action_rss_data;
4124 const struct arg *arg;
4131 if (ctx->curr != ACTION_RSS_QUEUE)
4133 i = ctx->objdata >> 16;
4134 if (!strcmp_partial("end", str, len)) {
4135 ctx->objdata &= 0xffff;
4138 if (i >= ACTION_RSS_QUEUE_NUM)
4140 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
4141 i * sizeof(action_rss_data->queue[i]),
4142 sizeof(action_rss_data->queue[i]));
4143 if (push_args(ctx, arg))
4145 ret = parse_int(ctx, token, str, len, NULL, 0);
4151 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
4153 if (ctx->next_num == RTE_DIM(ctx->next))
4155 ctx->next[ctx->next_num++] = next;
4159 action_rss_data = ctx->object;
4160 action_rss_data->conf.queue_num = i;
4161 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
4165 /** Parse VXLAN encap action. */
4167 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
4168 const char *str, unsigned int len,
4169 void *buf, unsigned int size)
4171 struct buffer *out = buf;
4172 struct rte_flow_action *action;
4173 struct action_vxlan_encap_data *action_vxlan_encap_data;
4176 ret = parse_vc(ctx, token, str, len, buf, size);
4179 /* Nothing else to do if there is no buffer. */
4182 if (!out->args.vc.actions_n)
4184 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4185 /* Point to selected object. */
4186 ctx->object = out->args.vc.data;
4187 ctx->objmask = NULL;
4188 /* Set up default configuration. */
4189 action_vxlan_encap_data = ctx->object;
4190 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
4191 .conf = (struct rte_flow_action_vxlan_encap){
4192 .definition = action_vxlan_encap_data->items,
4196 .type = RTE_FLOW_ITEM_TYPE_ETH,
4197 .spec = &action_vxlan_encap_data->item_eth,
4198 .mask = &rte_flow_item_eth_mask,
4201 .type = RTE_FLOW_ITEM_TYPE_VLAN,
4202 .spec = &action_vxlan_encap_data->item_vlan,
4203 .mask = &rte_flow_item_vlan_mask,
4206 .type = RTE_FLOW_ITEM_TYPE_IPV4,
4207 .spec = &action_vxlan_encap_data->item_ipv4,
4208 .mask = &rte_flow_item_ipv4_mask,
4211 .type = RTE_FLOW_ITEM_TYPE_UDP,
4212 .spec = &action_vxlan_encap_data->item_udp,
4213 .mask = &rte_flow_item_udp_mask,
4216 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
4217 .spec = &action_vxlan_encap_data->item_vxlan,
4218 .mask = &rte_flow_item_vxlan_mask,
4221 .type = RTE_FLOW_ITEM_TYPE_END,
4226 .tci = vxlan_encap_conf.vlan_tci,
4230 .src_addr = vxlan_encap_conf.ipv4_src,
4231 .dst_addr = vxlan_encap_conf.ipv4_dst,
4234 .src_port = vxlan_encap_conf.udp_src,
4235 .dst_port = vxlan_encap_conf.udp_dst,
4237 .item_vxlan.flags = 0,
4239 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
4240 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4241 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
4242 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4243 if (!vxlan_encap_conf.select_ipv4) {
4244 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
4245 &vxlan_encap_conf.ipv6_src,
4246 sizeof(vxlan_encap_conf.ipv6_src));
4247 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
4248 &vxlan_encap_conf.ipv6_dst,
4249 sizeof(vxlan_encap_conf.ipv6_dst));
4250 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
4251 .type = RTE_FLOW_ITEM_TYPE_IPV6,
4252 .spec = &action_vxlan_encap_data->item_ipv6,
4253 .mask = &rte_flow_item_ipv6_mask,
4256 if (!vxlan_encap_conf.select_vlan)
4257 action_vxlan_encap_data->items[1].type =
4258 RTE_FLOW_ITEM_TYPE_VOID;
4259 if (vxlan_encap_conf.select_tos_ttl) {
4260 if (vxlan_encap_conf.select_ipv4) {
4261 static struct rte_flow_item_ipv4 ipv4_mask_tos;
4263 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
4264 sizeof(ipv4_mask_tos));
4265 ipv4_mask_tos.hdr.type_of_service = 0xff;
4266 ipv4_mask_tos.hdr.time_to_live = 0xff;
4267 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
4268 vxlan_encap_conf.ip_tos;
4269 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
4270 vxlan_encap_conf.ip_ttl;
4271 action_vxlan_encap_data->items[2].mask =
4274 static struct rte_flow_item_ipv6 ipv6_mask_tos;
4276 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
4277 sizeof(ipv6_mask_tos));
4278 ipv6_mask_tos.hdr.vtc_flow |=
4279 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
4280 ipv6_mask_tos.hdr.hop_limits = 0xff;
4281 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
4283 ((uint32_t)vxlan_encap_conf.ip_tos <<
4284 RTE_IPV6_HDR_TC_SHIFT);
4285 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
4286 vxlan_encap_conf.ip_ttl;
4287 action_vxlan_encap_data->items[2].mask =
4291 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
4292 RTE_DIM(vxlan_encap_conf.vni));
4293 action->conf = &action_vxlan_encap_data->conf;
4297 /** Parse NVGRE encap action. */
4299 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
4300 const char *str, unsigned int len,
4301 void *buf, unsigned int size)
4303 struct buffer *out = buf;
4304 struct rte_flow_action *action;
4305 struct action_nvgre_encap_data *action_nvgre_encap_data;
4308 ret = parse_vc(ctx, token, str, len, buf, size);
4311 /* Nothing else to do if there is no buffer. */
4314 if (!out->args.vc.actions_n)
4316 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4317 /* Point to selected object. */
4318 ctx->object = out->args.vc.data;
4319 ctx->objmask = NULL;
4320 /* Set up default configuration. */
4321 action_nvgre_encap_data = ctx->object;
4322 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
4323 .conf = (struct rte_flow_action_nvgre_encap){
4324 .definition = action_nvgre_encap_data->items,
4328 .type = RTE_FLOW_ITEM_TYPE_ETH,
4329 .spec = &action_nvgre_encap_data->item_eth,
4330 .mask = &rte_flow_item_eth_mask,
4333 .type = RTE_FLOW_ITEM_TYPE_VLAN,
4334 .spec = &action_nvgre_encap_data->item_vlan,
4335 .mask = &rte_flow_item_vlan_mask,
4338 .type = RTE_FLOW_ITEM_TYPE_IPV4,
4339 .spec = &action_nvgre_encap_data->item_ipv4,
4340 .mask = &rte_flow_item_ipv4_mask,
4343 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
4344 .spec = &action_nvgre_encap_data->item_nvgre,
4345 .mask = &rte_flow_item_nvgre_mask,
4348 .type = RTE_FLOW_ITEM_TYPE_END,
4353 .tci = nvgre_encap_conf.vlan_tci,
4357 .src_addr = nvgre_encap_conf.ipv4_src,
4358 .dst_addr = nvgre_encap_conf.ipv4_dst,
4360 .item_nvgre.flow_id = 0,
4362 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
4363 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4364 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
4365 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4366 if (!nvgre_encap_conf.select_ipv4) {
4367 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
4368 &nvgre_encap_conf.ipv6_src,
4369 sizeof(nvgre_encap_conf.ipv6_src));
4370 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
4371 &nvgre_encap_conf.ipv6_dst,
4372 sizeof(nvgre_encap_conf.ipv6_dst));
4373 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
4374 .type = RTE_FLOW_ITEM_TYPE_IPV6,
4375 .spec = &action_nvgre_encap_data->item_ipv6,
4376 .mask = &rte_flow_item_ipv6_mask,
4379 if (!nvgre_encap_conf.select_vlan)
4380 action_nvgre_encap_data->items[1].type =
4381 RTE_FLOW_ITEM_TYPE_VOID;
4382 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
4383 RTE_DIM(nvgre_encap_conf.tni));
4384 action->conf = &action_nvgre_encap_data->conf;
4388 /** Parse l2 encap action. */
4390 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
4391 const char *str, unsigned int len,
4392 void *buf, unsigned int size)
4394 struct buffer *out = buf;
4395 struct rte_flow_action *action;
4396 struct action_raw_encap_data *action_encap_data;
4397 struct rte_flow_item_eth eth = { .type = 0, };
4398 struct rte_flow_item_vlan vlan = {
4399 .tci = mplsoudp_encap_conf.vlan_tci,
4405 ret = parse_vc(ctx, token, str, len, buf, size);
4408 /* Nothing else to do if there is no buffer. */
4411 if (!out->args.vc.actions_n)
4413 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4414 /* Point to selected object. */
4415 ctx->object = out->args.vc.data;
4416 ctx->objmask = NULL;
4417 /* Copy the headers to the buffer. */
4418 action_encap_data = ctx->object;
4419 *action_encap_data = (struct action_raw_encap_data) {
4420 .conf = (struct rte_flow_action_raw_encap){
4421 .data = action_encap_data->data,
4425 header = action_encap_data->data;
4426 if (l2_encap_conf.select_vlan)
4427 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4428 else if (l2_encap_conf.select_ipv4)
4429 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4431 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4432 memcpy(eth.dst.addr_bytes,
4433 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4434 memcpy(eth.src.addr_bytes,
4435 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4436 memcpy(header, ð, sizeof(eth));
4437 header += sizeof(eth);
4438 if (l2_encap_conf.select_vlan) {
4439 if (l2_encap_conf.select_ipv4)
4440 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4442 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4443 memcpy(header, &vlan, sizeof(vlan));
4444 header += sizeof(vlan);
4446 action_encap_data->conf.size = header -
4447 action_encap_data->data;
4448 action->conf = &action_encap_data->conf;
4452 /** Parse l2 decap action. */
4454 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
4455 const char *str, unsigned int len,
4456 void *buf, unsigned int size)
4458 struct buffer *out = buf;
4459 struct rte_flow_action *action;
4460 struct action_raw_decap_data *action_decap_data;
4461 struct rte_flow_item_eth eth = { .type = 0, };
4462 struct rte_flow_item_vlan vlan = {
4463 .tci = mplsoudp_encap_conf.vlan_tci,
4469 ret = parse_vc(ctx, token, str, len, buf, size);
4472 /* Nothing else to do if there is no buffer. */
4475 if (!out->args.vc.actions_n)
4477 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4478 /* Point to selected object. */
4479 ctx->object = out->args.vc.data;
4480 ctx->objmask = NULL;
4481 /* Copy the headers to the buffer. */
4482 action_decap_data = ctx->object;
4483 *action_decap_data = (struct action_raw_decap_data) {
4484 .conf = (struct rte_flow_action_raw_decap){
4485 .data = action_decap_data->data,
4489 header = action_decap_data->data;
4490 if (l2_decap_conf.select_vlan)
4491 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4492 memcpy(header, ð, sizeof(eth));
4493 header += sizeof(eth);
4494 if (l2_decap_conf.select_vlan) {
4495 memcpy(header, &vlan, sizeof(vlan));
4496 header += sizeof(vlan);
4498 action_decap_data->conf.size = header -
4499 action_decap_data->data;
4500 action->conf = &action_decap_data->conf;
4504 #define ETHER_TYPE_MPLS_UNICAST 0x8847
4506 /** Parse MPLSOGRE encap action. */
4508 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
4509 const char *str, unsigned int len,
4510 void *buf, unsigned int size)
4512 struct buffer *out = buf;
4513 struct rte_flow_action *action;
4514 struct action_raw_encap_data *action_encap_data;
4515 struct rte_flow_item_eth eth = { .type = 0, };
4516 struct rte_flow_item_vlan vlan = {
4517 .tci = mplsogre_encap_conf.vlan_tci,
4520 struct rte_flow_item_ipv4 ipv4 = {
4522 .src_addr = mplsogre_encap_conf.ipv4_src,
4523 .dst_addr = mplsogre_encap_conf.ipv4_dst,
4524 .next_proto_id = IPPROTO_GRE,
4525 .version_ihl = RTE_IPV4_VHL_DEF,
4526 .time_to_live = IPDEFTTL,
4529 struct rte_flow_item_ipv6 ipv6 = {
4531 .proto = IPPROTO_GRE,
4532 .hop_limits = IPDEFTTL,
4535 struct rte_flow_item_gre gre = {
4536 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
4538 struct rte_flow_item_mpls mpls;
4542 ret = parse_vc(ctx, token, str, len, buf, size);
4545 /* Nothing else to do if there is no buffer. */
4548 if (!out->args.vc.actions_n)
4550 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4551 /* Point to selected object. */
4552 ctx->object = out->args.vc.data;
4553 ctx->objmask = NULL;
4554 /* Copy the headers to the buffer. */
4555 action_encap_data = ctx->object;
4556 *action_encap_data = (struct action_raw_encap_data) {
4557 .conf = (struct rte_flow_action_raw_encap){
4558 .data = action_encap_data->data,
4563 header = action_encap_data->data;
4564 if (mplsogre_encap_conf.select_vlan)
4565 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4566 else if (mplsogre_encap_conf.select_ipv4)
4567 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4569 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4570 memcpy(eth.dst.addr_bytes,
4571 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4572 memcpy(eth.src.addr_bytes,
4573 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4574 memcpy(header, ð, sizeof(eth));
4575 header += sizeof(eth);
4576 if (mplsogre_encap_conf.select_vlan) {
4577 if (mplsogre_encap_conf.select_ipv4)
4578 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4580 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4581 memcpy(header, &vlan, sizeof(vlan));
4582 header += sizeof(vlan);
4584 if (mplsogre_encap_conf.select_ipv4) {
4585 memcpy(header, &ipv4, sizeof(ipv4));
4586 header += sizeof(ipv4);
4588 memcpy(&ipv6.hdr.src_addr,
4589 &mplsogre_encap_conf.ipv6_src,
4590 sizeof(mplsogre_encap_conf.ipv6_src));
4591 memcpy(&ipv6.hdr.dst_addr,
4592 &mplsogre_encap_conf.ipv6_dst,
4593 sizeof(mplsogre_encap_conf.ipv6_dst));
4594 memcpy(header, &ipv6, sizeof(ipv6));
4595 header += sizeof(ipv6);
4597 memcpy(header, &gre, sizeof(gre));
4598 header += sizeof(gre);
4599 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
4600 RTE_DIM(mplsogre_encap_conf.label));
4601 mpls.label_tc_s[2] |= 0x1;
4602 memcpy(header, &mpls, sizeof(mpls));
4603 header += sizeof(mpls);
4604 action_encap_data->conf.size = header -
4605 action_encap_data->data;
4606 action->conf = &action_encap_data->conf;
4610 /** Parse MPLSOGRE decap action. */
4612 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
4613 const char *str, unsigned int len,
4614 void *buf, unsigned int size)
4616 struct buffer *out = buf;
4617 struct rte_flow_action *action;
4618 struct action_raw_decap_data *action_decap_data;
4619 struct rte_flow_item_eth eth = { .type = 0, };
4620 struct rte_flow_item_vlan vlan = {.tci = 0};
4621 struct rte_flow_item_ipv4 ipv4 = {
4623 .next_proto_id = IPPROTO_GRE,
4626 struct rte_flow_item_ipv6 ipv6 = {
4628 .proto = IPPROTO_GRE,
4631 struct rte_flow_item_gre gre = {
4632 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
4634 struct rte_flow_item_mpls mpls;
4638 ret = parse_vc(ctx, token, str, len, buf, size);
4641 /* Nothing else to do if there is no buffer. */
4644 if (!out->args.vc.actions_n)
4646 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4647 /* Point to selected object. */
4648 ctx->object = out->args.vc.data;
4649 ctx->objmask = NULL;
4650 /* Copy the headers to the buffer. */
4651 action_decap_data = ctx->object;
4652 *action_decap_data = (struct action_raw_decap_data) {
4653 .conf = (struct rte_flow_action_raw_decap){
4654 .data = action_decap_data->data,
4658 header = action_decap_data->data;
4659 if (mplsogre_decap_conf.select_vlan)
4660 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4661 else if (mplsogre_encap_conf.select_ipv4)
4662 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4664 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4665 memcpy(eth.dst.addr_bytes,
4666 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4667 memcpy(eth.src.addr_bytes,
4668 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4669 memcpy(header, ð, sizeof(eth));
4670 header += sizeof(eth);
4671 if (mplsogre_encap_conf.select_vlan) {
4672 if (mplsogre_encap_conf.select_ipv4)
4673 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4675 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4676 memcpy(header, &vlan, sizeof(vlan));
4677 header += sizeof(vlan);
4679 if (mplsogre_encap_conf.select_ipv4) {
4680 memcpy(header, &ipv4, sizeof(ipv4));
4681 header += sizeof(ipv4);
4683 memcpy(header, &ipv6, sizeof(ipv6));
4684 header += sizeof(ipv6);
4686 memcpy(header, &gre, sizeof(gre));
4687 header += sizeof(gre);
4688 memset(&mpls, 0, sizeof(mpls));
4689 memcpy(header, &mpls, sizeof(mpls));
4690 header += sizeof(mpls);
4691 action_decap_data->conf.size = header -
4692 action_decap_data->data;
4693 action->conf = &action_decap_data->conf;
4697 /** Parse MPLSOUDP encap action. */
4699 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
4700 const char *str, unsigned int len,
4701 void *buf, unsigned int size)
4703 struct buffer *out = buf;
4704 struct rte_flow_action *action;
4705 struct action_raw_encap_data *action_encap_data;
4706 struct rte_flow_item_eth eth = { .type = 0, };
4707 struct rte_flow_item_vlan vlan = {
4708 .tci = mplsoudp_encap_conf.vlan_tci,
4711 struct rte_flow_item_ipv4 ipv4 = {
4713 .src_addr = mplsoudp_encap_conf.ipv4_src,
4714 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
4715 .next_proto_id = IPPROTO_UDP,
4716 .version_ihl = RTE_IPV4_VHL_DEF,
4717 .time_to_live = IPDEFTTL,
4720 struct rte_flow_item_ipv6 ipv6 = {
4722 .proto = IPPROTO_UDP,
4723 .hop_limits = IPDEFTTL,
4726 struct rte_flow_item_udp udp = {
4728 .src_port = mplsoudp_encap_conf.udp_src,
4729 .dst_port = mplsoudp_encap_conf.udp_dst,
4732 struct rte_flow_item_mpls mpls;
4736 ret = parse_vc(ctx, token, str, len, buf, size);
4739 /* Nothing else to do if there is no buffer. */
4742 if (!out->args.vc.actions_n)
4744 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4745 /* Point to selected object. */
4746 ctx->object = out->args.vc.data;
4747 ctx->objmask = NULL;
4748 /* Copy the headers to the buffer. */
4749 action_encap_data = ctx->object;
4750 *action_encap_data = (struct action_raw_encap_data) {
4751 .conf = (struct rte_flow_action_raw_encap){
4752 .data = action_encap_data->data,
4757 header = action_encap_data->data;
4758 if (mplsoudp_encap_conf.select_vlan)
4759 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4760 else if (mplsoudp_encap_conf.select_ipv4)
4761 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4763 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4764 memcpy(eth.dst.addr_bytes,
4765 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4766 memcpy(eth.src.addr_bytes,
4767 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4768 memcpy(header, ð, sizeof(eth));
4769 header += sizeof(eth);
4770 if (mplsoudp_encap_conf.select_vlan) {
4771 if (mplsoudp_encap_conf.select_ipv4)
4772 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4774 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4775 memcpy(header, &vlan, sizeof(vlan));
4776 header += sizeof(vlan);
4778 if (mplsoudp_encap_conf.select_ipv4) {
4779 memcpy(header, &ipv4, sizeof(ipv4));
4780 header += sizeof(ipv4);
4782 memcpy(&ipv6.hdr.src_addr,
4783 &mplsoudp_encap_conf.ipv6_src,
4784 sizeof(mplsoudp_encap_conf.ipv6_src));
4785 memcpy(&ipv6.hdr.dst_addr,
4786 &mplsoudp_encap_conf.ipv6_dst,
4787 sizeof(mplsoudp_encap_conf.ipv6_dst));
4788 memcpy(header, &ipv6, sizeof(ipv6));
4789 header += sizeof(ipv6);
4791 memcpy(header, &udp, sizeof(udp));
4792 header += sizeof(udp);
4793 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
4794 RTE_DIM(mplsoudp_encap_conf.label));
4795 mpls.label_tc_s[2] |= 0x1;
4796 memcpy(header, &mpls, sizeof(mpls));
4797 header += sizeof(mpls);
4798 action_encap_data->conf.size = header -
4799 action_encap_data->data;
4800 action->conf = &action_encap_data->conf;
4804 /** Parse MPLSOUDP decap action. */
4806 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
4807 const char *str, unsigned int len,
4808 void *buf, unsigned int size)
4810 struct buffer *out = buf;
4811 struct rte_flow_action *action;
4812 struct action_raw_decap_data *action_decap_data;
4813 struct rte_flow_item_eth eth = { .type = 0, };
4814 struct rte_flow_item_vlan vlan = {.tci = 0};
4815 struct rte_flow_item_ipv4 ipv4 = {
4817 .next_proto_id = IPPROTO_UDP,
4820 struct rte_flow_item_ipv6 ipv6 = {
4822 .proto = IPPROTO_UDP,
4825 struct rte_flow_item_udp udp = {
4827 .dst_port = rte_cpu_to_be_16(6635),
4830 struct rte_flow_item_mpls mpls;
4834 ret = parse_vc(ctx, token, str, len, buf, size);
4837 /* Nothing else to do if there is no buffer. */
4840 if (!out->args.vc.actions_n)
4842 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4843 /* Point to selected object. */
4844 ctx->object = out->args.vc.data;
4845 ctx->objmask = NULL;
4846 /* Copy the headers to the buffer. */
4847 action_decap_data = ctx->object;
4848 *action_decap_data = (struct action_raw_decap_data) {
4849 .conf = (struct rte_flow_action_raw_decap){
4850 .data = action_decap_data->data,
4854 header = action_decap_data->data;
4855 if (mplsoudp_decap_conf.select_vlan)
4856 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4857 else if (mplsoudp_encap_conf.select_ipv4)
4858 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4860 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4861 memcpy(eth.dst.addr_bytes,
4862 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4863 memcpy(eth.src.addr_bytes,
4864 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4865 memcpy(header, ð, sizeof(eth));
4866 header += sizeof(eth);
4867 if (mplsoudp_encap_conf.select_vlan) {
4868 if (mplsoudp_encap_conf.select_ipv4)
4869 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4871 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4872 memcpy(header, &vlan, sizeof(vlan));
4873 header += sizeof(vlan);
4875 if (mplsoudp_encap_conf.select_ipv4) {
4876 memcpy(header, &ipv4, sizeof(ipv4));
4877 header += sizeof(ipv4);
4879 memcpy(header, &ipv6, sizeof(ipv6));
4880 header += sizeof(ipv6);
4882 memcpy(header, &udp, sizeof(udp));
4883 header += sizeof(udp);
4884 memset(&mpls, 0, sizeof(mpls));
4885 memcpy(header, &mpls, sizeof(mpls));
4886 header += sizeof(mpls);
4887 action_decap_data->conf.size = header -
4888 action_decap_data->data;
4889 action->conf = &action_decap_data->conf;
4894 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
4895 const char *str, unsigned int len, void *buf,
4898 struct action_raw_decap_data *action_raw_decap_data;
4899 struct rte_flow_action *action;
4900 const struct arg *arg;
4901 struct buffer *out = buf;
4905 RTE_SET_USED(token);
4908 arg = ARGS_ENTRY_ARB_BOUNDED
4909 (offsetof(struct action_raw_decap_data, idx),
4910 sizeof(((struct action_raw_decap_data *)0)->idx),
4911 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
4912 if (push_args(ctx, arg))
4914 ret = parse_int(ctx, token, str, len, NULL, 0);
4921 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4922 action_raw_decap_data = ctx->object;
4923 idx = action_raw_decap_data->idx;
4924 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
4925 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
4926 action->conf = &action_raw_decap_data->conf;
4932 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
4933 const char *str, unsigned int len, void *buf,
4936 struct action_raw_encap_data *action_raw_encap_data;
4937 struct rte_flow_action *action;
4938 const struct arg *arg;
4939 struct buffer *out = buf;
4943 RTE_SET_USED(token);
4946 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
4948 arg = ARGS_ENTRY_ARB_BOUNDED
4949 (offsetof(struct action_raw_encap_data, idx),
4950 sizeof(((struct action_raw_encap_data *)0)->idx),
4951 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
4952 if (push_args(ctx, arg))
4954 ret = parse_int(ctx, token, str, len, NULL, 0);
4961 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4962 action_raw_encap_data = ctx->object;
4963 idx = action_raw_encap_data->idx;
4964 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
4965 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
4966 action_raw_encap_data->conf.preserve = NULL;
4967 action->conf = &action_raw_encap_data->conf;
4972 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
4973 const char *str, unsigned int len, void *buf,
4976 struct buffer *out = buf;
4977 struct rte_flow_action *action;
4978 struct action_raw_encap_data *action_raw_encap_data = NULL;
4981 ret = parse_vc(ctx, token, str, len, buf, size);
4984 /* Nothing else to do if there is no buffer. */
4987 if (!out->args.vc.actions_n)
4989 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4990 /* Point to selected object. */
4991 ctx->object = out->args.vc.data;
4992 ctx->objmask = NULL;
4993 /* Copy the headers to the buffer. */
4994 action_raw_encap_data = ctx->object;
4995 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
4996 action_raw_encap_data->conf.preserve = NULL;
4997 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
4998 action->conf = &action_raw_encap_data->conf;
5003 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
5004 const char *str, unsigned int len, void *buf,
5007 struct buffer *out = buf;
5008 struct rte_flow_action *action;
5009 struct action_raw_decap_data *action_raw_decap_data = NULL;
5012 ret = parse_vc(ctx, token, str, len, buf, size);
5015 /* Nothing else to do if there is no buffer. */
5018 if (!out->args.vc.actions_n)
5020 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5021 /* Point to selected object. */
5022 ctx->object = out->args.vc.data;
5023 ctx->objmask = NULL;
5024 /* Copy the headers to the buffer. */
5025 action_raw_decap_data = ctx->object;
5026 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
5027 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
5028 action->conf = &action_raw_decap_data->conf;
5033 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
5034 const char *str, unsigned int len, void *buf,
5039 ret = parse_vc(ctx, token, str, len, buf, size);
5042 ret = rte_flow_dynf_metadata_register();
5048 /** Parse tokens for destroy command. */
5050 parse_destroy(struct context *ctx, const struct token *token,
5051 const char *str, unsigned int len,
5052 void *buf, unsigned int size)
5054 struct buffer *out = buf;
5056 /* Token name must match. */
5057 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5059 /* Nothing else to do if there is no buffer. */
5062 if (!out->command) {
5063 if (ctx->curr != DESTROY)
5065 if (sizeof(*out) > size)
5067 out->command = ctx->curr;
5070 ctx->objmask = NULL;
5071 out->args.destroy.rule =
5072 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5076 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
5077 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
5080 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
5081 ctx->objmask = NULL;
5085 /** Parse tokens for flush command. */
5087 parse_flush(struct context *ctx, const struct token *token,
5088 const char *str, unsigned int len,
5089 void *buf, unsigned int size)
5091 struct buffer *out = buf;
5093 /* Token name must match. */
5094 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5096 /* Nothing else to do if there is no buffer. */
5099 if (!out->command) {
5100 if (ctx->curr != FLUSH)
5102 if (sizeof(*out) > size)
5104 out->command = ctx->curr;
5107 ctx->objmask = NULL;
5112 /** Parse tokens for query command. */
5114 parse_query(struct context *ctx, const struct token *token,
5115 const char *str, unsigned int len,
5116 void *buf, unsigned int size)
5118 struct buffer *out = buf;
5120 /* Token name must match. */
5121 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5123 /* Nothing else to do if there is no buffer. */
5126 if (!out->command) {
5127 if (ctx->curr != QUERY)
5129 if (sizeof(*out) > size)
5131 out->command = ctx->curr;
5134 ctx->objmask = NULL;
5139 /** Parse action names. */
5141 parse_action(struct context *ctx, const struct token *token,
5142 const char *str, unsigned int len,
5143 void *buf, unsigned int size)
5145 struct buffer *out = buf;
5146 const struct arg *arg = pop_args(ctx);
5150 /* Argument is expected. */
5153 /* Parse action name. */
5154 for (i = 0; next_action[i]; ++i) {
5155 const struct parse_action_priv *priv;
5157 token = &token_list[next_action[i]];
5158 if (strcmp_partial(token->name, str, len))
5164 memcpy((uint8_t *)ctx->object + arg->offset,
5170 push_args(ctx, arg);
5174 /** Parse tokens for list command. */
5176 parse_list(struct context *ctx, const struct token *token,
5177 const char *str, unsigned int len,
5178 void *buf, unsigned int size)
5180 struct buffer *out = buf;
5182 /* Token name must match. */
5183 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5185 /* Nothing else to do if there is no buffer. */
5188 if (!out->command) {
5189 if (ctx->curr != LIST)
5191 if (sizeof(*out) > size)
5193 out->command = ctx->curr;
5196 ctx->objmask = NULL;
5197 out->args.list.group =
5198 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5202 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
5203 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
5206 ctx->object = out->args.list.group + out->args.list.group_n++;
5207 ctx->objmask = NULL;
5211 /** Parse tokens for isolate command. */
5213 parse_isolate(struct context *ctx, const struct token *token,
5214 const char *str, unsigned int len,
5215 void *buf, unsigned int size)
5217 struct buffer *out = buf;
5219 /* Token name must match. */
5220 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5222 /* Nothing else to do if there is no buffer. */
5225 if (!out->command) {
5226 if (ctx->curr != ISOLATE)
5228 if (sizeof(*out) > size)
5230 out->command = ctx->curr;
5233 ctx->objmask = NULL;
5239 * Parse signed/unsigned integers 8 to 64-bit long.
5241 * Last argument (ctx->args) is retrieved to determine integer type and
5245 parse_int(struct context *ctx, const struct token *token,
5246 const char *str, unsigned int len,
5247 void *buf, unsigned int size)
5249 const struct arg *arg = pop_args(ctx);
5254 /* Argument is expected. */
5259 (uintmax_t)strtoimax(str, &end, 0) :
5260 strtoumax(str, &end, 0);
5261 if (errno || (size_t)(end - str) != len)
5264 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
5265 (intmax_t)u > (intmax_t)arg->max)) ||
5266 (!arg->sign && (u < arg->min || u > arg->max))))
5271 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
5272 !arg_entry_bf_fill(ctx->objmask, -1, arg))
5276 buf = (uint8_t *)ctx->object + arg->offset;
5278 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
5282 case sizeof(uint8_t):
5283 *(uint8_t *)buf = u;
5285 case sizeof(uint16_t):
5286 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
5288 case sizeof(uint8_t [3]):
5289 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5291 ((uint8_t *)buf)[0] = u;
5292 ((uint8_t *)buf)[1] = u >> 8;
5293 ((uint8_t *)buf)[2] = u >> 16;
5297 ((uint8_t *)buf)[0] = u >> 16;
5298 ((uint8_t *)buf)[1] = u >> 8;
5299 ((uint8_t *)buf)[2] = u;
5301 case sizeof(uint32_t):
5302 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
5304 case sizeof(uint64_t):
5305 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
5310 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
5312 buf = (uint8_t *)ctx->objmask + arg->offset;
5317 push_args(ctx, arg);
5324 * Three arguments (ctx->args) are retrieved from the stack to store data,
5325 * its actual length and address (in that order).
5328 parse_string(struct context *ctx, const struct token *token,
5329 const char *str, unsigned int len,
5330 void *buf, unsigned int size)
5332 const struct arg *arg_data = pop_args(ctx);
5333 const struct arg *arg_len = pop_args(ctx);
5334 const struct arg *arg_addr = pop_args(ctx);
5335 char tmp[16]; /* Ought to be enough. */
5338 /* Arguments are expected. */
5342 push_args(ctx, arg_data);
5346 push_args(ctx, arg_len);
5347 push_args(ctx, arg_data);
5350 size = arg_data->size;
5351 /* Bit-mask fill is not supported. */
5352 if (arg_data->mask || size < len)
5356 /* Let parse_int() fill length information first. */
5357 ret = snprintf(tmp, sizeof(tmp), "%u", len);
5360 push_args(ctx, arg_len);
5361 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
5366 buf = (uint8_t *)ctx->object + arg_data->offset;
5367 /* Output buffer is not necessarily NUL-terminated. */
5368 memcpy(buf, str, len);
5369 memset((uint8_t *)buf + len, 0x00, size - len);
5371 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
5372 /* Save address if requested. */
5373 if (arg_addr->size) {
5374 memcpy((uint8_t *)ctx->object + arg_addr->offset,
5376 (uint8_t *)ctx->object + arg_data->offset
5380 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
5382 (uint8_t *)ctx->objmask + arg_data->offset
5388 push_args(ctx, arg_addr);
5389 push_args(ctx, arg_len);
5390 push_args(ctx, arg_data);
5395 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
5401 /* Check input parameters */
5402 if ((src == NULL) ||
5408 /* Convert chars to bytes */
5409 for (i = 0, len = 0; i < *size; i += 2) {
5410 snprintf(tmp, 3, "%s", src + i);
5411 dst[len++] = strtoul(tmp, &c, 16);
5426 parse_hex(struct context *ctx, const struct token *token,
5427 const char *str, unsigned int len,
5428 void *buf, unsigned int size)
5430 const struct arg *arg_data = pop_args(ctx);
5431 const struct arg *arg_len = pop_args(ctx);
5432 const struct arg *arg_addr = pop_args(ctx);
5433 char tmp[16]; /* Ought to be enough. */
5435 unsigned int hexlen = len;
5436 unsigned int length = 256;
5437 uint8_t hex_tmp[length];
5439 /* Arguments are expected. */
5443 push_args(ctx, arg_data);
5447 push_args(ctx, arg_len);
5448 push_args(ctx, arg_data);
5451 size = arg_data->size;
5452 /* Bit-mask fill is not supported. */
5458 /* translate bytes string to array. */
5459 if (str[0] == '0' && ((str[1] == 'x') ||
5464 if (hexlen > length)
5466 ret = parse_hex_string(str, hex_tmp, &hexlen);
5469 /* Let parse_int() fill length information first. */
5470 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
5473 push_args(ctx, arg_len);
5474 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
5479 buf = (uint8_t *)ctx->object + arg_data->offset;
5480 /* Output buffer is not necessarily NUL-terminated. */
5481 memcpy(buf, hex_tmp, hexlen);
5482 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
5484 memset((uint8_t *)ctx->objmask + arg_data->offset,
5486 /* Save address if requested. */
5487 if (arg_addr->size) {
5488 memcpy((uint8_t *)ctx->object + arg_addr->offset,
5490 (uint8_t *)ctx->object + arg_data->offset
5494 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
5496 (uint8_t *)ctx->objmask + arg_data->offset
5502 push_args(ctx, arg_addr);
5503 push_args(ctx, arg_len);
5504 push_args(ctx, arg_data);
5510 * Parse a MAC address.
5512 * Last argument (ctx->args) is retrieved to determine storage size and
5516 parse_mac_addr(struct context *ctx, const struct token *token,
5517 const char *str, unsigned int len,
5518 void *buf, unsigned int size)
5520 const struct arg *arg = pop_args(ctx);
5521 struct rte_ether_addr tmp;
5525 /* Argument is expected. */
5529 /* Bit-mask fill is not supported. */
5530 if (arg->mask || size != sizeof(tmp))
5532 /* Only network endian is supported. */
5535 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
5536 if (ret < 0 || (unsigned int)ret != len)
5540 buf = (uint8_t *)ctx->object + arg->offset;
5541 memcpy(buf, &tmp, size);
5543 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5546 push_args(ctx, arg);
5551 * Parse an IPv4 address.
5553 * Last argument (ctx->args) is retrieved to determine storage size and
5557 parse_ipv4_addr(struct context *ctx, const struct token *token,
5558 const char *str, unsigned int len,
5559 void *buf, unsigned int size)
5561 const struct arg *arg = pop_args(ctx);
5566 /* Argument is expected. */
5570 /* Bit-mask fill is not supported. */
5571 if (arg->mask || size != sizeof(tmp))
5573 /* Only network endian is supported. */
5576 memcpy(str2, str, len);
5578 ret = inet_pton(AF_INET, str2, &tmp);
5580 /* Attempt integer parsing. */
5581 push_args(ctx, arg);
5582 return parse_int(ctx, token, str, len, buf, size);
5586 buf = (uint8_t *)ctx->object + arg->offset;
5587 memcpy(buf, &tmp, size);
5589 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5592 push_args(ctx, arg);
5597 * Parse an IPv6 address.
5599 * Last argument (ctx->args) is retrieved to determine storage size and
5603 parse_ipv6_addr(struct context *ctx, const struct token *token,
5604 const char *str, unsigned int len,
5605 void *buf, unsigned int size)
5607 const struct arg *arg = pop_args(ctx);
5609 struct in6_addr tmp;
5613 /* Argument is expected. */
5617 /* Bit-mask fill is not supported. */
5618 if (arg->mask || size != sizeof(tmp))
5620 /* Only network endian is supported. */
5623 memcpy(str2, str, len);
5625 ret = inet_pton(AF_INET6, str2, &tmp);
5630 buf = (uint8_t *)ctx->object + arg->offset;
5631 memcpy(buf, &tmp, size);
5633 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5636 push_args(ctx, arg);
5640 /** Boolean values (even indices stand for false). */
5641 static const char *const boolean_name[] = {
5651 * Parse a boolean value.
5653 * Last argument (ctx->args) is retrieved to determine storage size and
5657 parse_boolean(struct context *ctx, const struct token *token,
5658 const char *str, unsigned int len,
5659 void *buf, unsigned int size)
5661 const struct arg *arg = pop_args(ctx);
5665 /* Argument is expected. */
5668 for (i = 0; boolean_name[i]; ++i)
5669 if (!strcmp_partial(boolean_name[i], str, len))
5671 /* Process token as integer. */
5672 if (boolean_name[i])
5673 str = i & 1 ? "1" : "0";
5674 push_args(ctx, arg);
5675 ret = parse_int(ctx, token, str, strlen(str), buf, size);
5676 return ret > 0 ? (int)len : ret;
5679 /** Parse port and update context. */
5681 parse_port(struct context *ctx, const struct token *token,
5682 const char *str, unsigned int len,
5683 void *buf, unsigned int size)
5685 struct buffer *out = &(struct buffer){ .port = 0 };
5693 ctx->objmask = NULL;
5694 size = sizeof(*out);
5696 ret = parse_int(ctx, token, str, len, out, size);
5698 ctx->port = out->port;
5704 /** Parse set command, initialize output buffer for subsequent tokens. */
5706 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
5707 const char *str, unsigned int len,
5708 void *buf, unsigned int size)
5710 struct buffer *out = buf;
5712 /* Token name must match. */
5713 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5715 /* Nothing else to do if there is no buffer. */
5718 /* Make sure buffer is large enough. */
5719 if (size < sizeof(*out))
5722 ctx->objmask = NULL;
5726 out->command = ctx->curr;
5731 * Parse set raw_encap/raw_decap command,
5732 * initialize output buffer for subsequent tokens.
5735 parse_set_init(struct context *ctx, const struct token *token,
5736 const char *str, unsigned int len,
5737 void *buf, unsigned int size)
5739 struct buffer *out = buf;
5741 /* Token name must match. */
5742 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5744 /* Nothing else to do if there is no buffer. */
5747 /* Make sure buffer is large enough. */
5748 if (size < sizeof(*out))
5750 /* Initialize buffer. */
5751 memset(out, 0x00, sizeof(*out));
5752 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5755 ctx->objmask = NULL;
5756 if (!out->command) {
5757 if (ctx->curr != SET)
5759 if (sizeof(*out) > size)
5761 out->command = ctx->curr;
5762 out->args.vc.data = (uint8_t *)out + size;
5763 /* All we need is pattern */
5764 out->args.vc.pattern =
5765 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5767 ctx->object = out->args.vc.pattern;
5772 /** No completion. */
5774 comp_none(struct context *ctx, const struct token *token,
5775 unsigned int ent, char *buf, unsigned int size)
5785 /** Complete boolean values. */
5787 comp_boolean(struct context *ctx, const struct token *token,
5788 unsigned int ent, char *buf, unsigned int size)
5794 for (i = 0; boolean_name[i]; ++i)
5795 if (buf && i == ent)
5796 return strlcpy(buf, boolean_name[i], size);
5802 /** Complete action names. */
5804 comp_action(struct context *ctx, const struct token *token,
5805 unsigned int ent, char *buf, unsigned int size)
5811 for (i = 0; next_action[i]; ++i)
5812 if (buf && i == ent)
5813 return strlcpy(buf, token_list[next_action[i]].name,
5820 /** Complete available ports. */
5822 comp_port(struct context *ctx, const struct token *token,
5823 unsigned int ent, char *buf, unsigned int size)
5830 RTE_ETH_FOREACH_DEV(p) {
5831 if (buf && i == ent)
5832 return snprintf(buf, size, "%u", p);
5840 /** Complete available rule IDs. */
5842 comp_rule_id(struct context *ctx, const struct token *token,
5843 unsigned int ent, char *buf, unsigned int size)
5846 struct rte_port *port;
5847 struct port_flow *pf;
5850 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
5851 ctx->port == (portid_t)RTE_PORT_ALL)
5853 port = &ports[ctx->port];
5854 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
5855 if (buf && i == ent)
5856 return snprintf(buf, size, "%u", pf->id);
5864 /** Complete type field for RSS action. */
5866 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
5867 unsigned int ent, char *buf, unsigned int size)
5873 for (i = 0; rss_type_table[i].str; ++i)
5878 return strlcpy(buf, rss_type_table[ent].str, size);
5880 return snprintf(buf, size, "end");
5884 /** Complete queue field for RSS action. */
5886 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
5887 unsigned int ent, char *buf, unsigned int size)
5894 return snprintf(buf, size, "%u", ent);
5896 return snprintf(buf, size, "end");
5900 /** Complete index number for set raw_encap/raw_decap commands. */
5902 comp_set_raw_index(struct context *ctx, const struct token *token,
5903 unsigned int ent, char *buf, unsigned int size)
5909 RTE_SET_USED(token);
5910 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
5911 if (buf && idx == ent)
5912 return snprintf(buf, size, "%u", idx);
5918 /** Internal context. */
5919 static struct context cmd_flow_context;
5921 /** Global parser instance (cmdline API). */
5922 cmdline_parse_inst_t cmd_flow;
5923 cmdline_parse_inst_t cmd_set_raw;
5925 /** Initialize context. */
5927 cmd_flow_context_init(struct context *ctx)
5929 /* A full memset() is not necessary. */
5939 ctx->objmask = NULL;
5942 /** Parse a token (cmdline API). */
5944 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
5947 struct context *ctx = &cmd_flow_context;
5948 const struct token *token;
5949 const enum index *list;
5954 token = &token_list[ctx->curr];
5955 /* Check argument length. */
5958 for (len = 0; src[len]; ++len)
5959 if (src[len] == '#' || isspace(src[len]))
5963 /* Last argument and EOL detection. */
5964 for (i = len; src[i]; ++i)
5965 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
5967 else if (!isspace(src[i])) {
5972 if (src[i] == '\r' || src[i] == '\n') {
5976 /* Initialize context if necessary. */
5977 if (!ctx->next_num) {
5980 ctx->next[ctx->next_num++] = token->next[0];
5982 /* Process argument through candidates. */
5983 ctx->prev = ctx->curr;
5984 list = ctx->next[ctx->next_num - 1];
5985 for (i = 0; list[i]; ++i) {
5986 const struct token *next = &token_list[list[i]];
5989 ctx->curr = list[i];
5991 tmp = next->call(ctx, next, src, len, result, size);
5993 tmp = parse_default(ctx, next, src, len, result, size);
5994 if (tmp == -1 || tmp != len)
6002 /* Push subsequent tokens if any. */
6004 for (i = 0; token->next[i]; ++i) {
6005 if (ctx->next_num == RTE_DIM(ctx->next))
6007 ctx->next[ctx->next_num++] = token->next[i];
6009 /* Push arguments if any. */
6011 for (i = 0; token->args[i]; ++i) {
6012 if (ctx->args_num == RTE_DIM(ctx->args))
6014 ctx->args[ctx->args_num++] = token->args[i];
6019 /** Return number of completion entries (cmdline API). */
6021 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
6023 struct context *ctx = &cmd_flow_context;
6024 const struct token *token = &token_list[ctx->curr];
6025 const enum index *list;
6029 /* Count number of tokens in current list. */
6031 list = ctx->next[ctx->next_num - 1];
6033 list = token->next[0];
6034 for (i = 0; list[i]; ++i)
6039 * If there is a single token, use its completion callback, otherwise
6040 * return the number of entries.
6042 token = &token_list[list[0]];
6043 if (i == 1 && token->comp) {
6044 /* Save index for cmd_flow_get_help(). */
6045 ctx->prev = list[0];
6046 return token->comp(ctx, token, 0, NULL, 0);
6051 /** Return a completion entry (cmdline API). */
6053 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
6054 char *dst, unsigned int size)
6056 struct context *ctx = &cmd_flow_context;
6057 const struct token *token = &token_list[ctx->curr];
6058 const enum index *list;
6062 /* Count number of tokens in current list. */
6064 list = ctx->next[ctx->next_num - 1];
6066 list = token->next[0];
6067 for (i = 0; list[i]; ++i)
6071 /* If there is a single token, use its completion callback. */
6072 token = &token_list[list[0]];
6073 if (i == 1 && token->comp) {
6074 /* Save index for cmd_flow_get_help(). */
6075 ctx->prev = list[0];
6076 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
6078 /* Otherwise make sure the index is valid and use defaults. */
6081 token = &token_list[list[index]];
6082 strlcpy(dst, token->name, size);
6083 /* Save index for cmd_flow_get_help(). */
6084 ctx->prev = list[index];
6088 /** Populate help strings for current token (cmdline API). */
6090 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
6092 struct context *ctx = &cmd_flow_context;
6093 const struct token *token = &token_list[ctx->prev];
6098 /* Set token type and update global help with details. */
6099 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
6101 cmd_flow.help_str = token->help;
6103 cmd_flow.help_str = token->name;
6107 /** Token definition template (cmdline API). */
6108 static struct cmdline_token_hdr cmd_flow_token_hdr = {
6109 .ops = &(struct cmdline_token_ops){
6110 .parse = cmd_flow_parse,
6111 .complete_get_nb = cmd_flow_complete_get_nb,
6112 .complete_get_elt = cmd_flow_complete_get_elt,
6113 .get_help = cmd_flow_get_help,
6118 /** Populate the next dynamic token. */
6120 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
6121 cmdline_parse_token_hdr_t **hdr_inst)
6123 struct context *ctx = &cmd_flow_context;
6125 /* Always reinitialize context before requesting the first token. */
6126 if (!(hdr_inst - cmd_flow.tokens))
6127 cmd_flow_context_init(ctx);
6128 /* Return NULL when no more tokens are expected. */
6129 if (!ctx->next_num && ctx->curr) {
6133 /* Determine if command should end here. */
6134 if (ctx->eol && ctx->last && ctx->next_num) {
6135 const enum index *list = ctx->next[ctx->next_num - 1];
6138 for (i = 0; list[i]; ++i) {
6145 *hdr = &cmd_flow_token_hdr;
6148 /** Dispatch parsed buffer to function calls. */
6150 cmd_flow_parsed(const struct buffer *in)
6152 switch (in->command) {
6154 port_flow_validate(in->port, &in->args.vc.attr,
6155 in->args.vc.pattern, in->args.vc.actions);
6158 port_flow_create(in->port, &in->args.vc.attr,
6159 in->args.vc.pattern, in->args.vc.actions);
6162 port_flow_destroy(in->port, in->args.destroy.rule_n,
6163 in->args.destroy.rule);
6166 port_flow_flush(in->port);
6169 port_flow_query(in->port, in->args.query.rule,
6170 &in->args.query.action);
6173 port_flow_list(in->port, in->args.list.group_n,
6174 in->args.list.group);
6177 port_flow_isolate(in->port, in->args.isolate.set);
6184 /** Token generator and output processing callback (cmdline API). */
6186 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
6189 cmd_flow_tok(arg0, arg2);
6191 cmd_flow_parsed(arg0);
6194 /** Global parser instance (cmdline API). */
6195 cmdline_parse_inst_t cmd_flow = {
6197 .data = NULL, /**< Unused. */
6198 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
6201 }, /**< Tokens are returned by cmd_flow_tok(). */
6204 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
6207 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
6209 struct rte_flow_item_ipv4 *ipv4;
6210 struct rte_flow_item_eth *eth;
6211 struct rte_flow_item_ipv6 *ipv6;
6212 struct rte_flow_item_vxlan *vxlan;
6213 struct rte_flow_item_vxlan_gpe *gpe;
6214 struct rte_flow_item_nvgre *nvgre;
6215 uint32_t ipv6_vtc_flow;
6217 switch (item->type) {
6218 case RTE_FLOW_ITEM_TYPE_ETH:
6219 eth = (struct rte_flow_item_eth *)buf;
6221 eth->type = rte_cpu_to_be_16(next_proto);
6223 case RTE_FLOW_ITEM_TYPE_IPV4:
6224 ipv4 = (struct rte_flow_item_ipv4 *)buf;
6225 ipv4->hdr.version_ihl = 0x45;
6226 if (next_proto && ipv4->hdr.next_proto_id == 0)
6227 ipv4->hdr.next_proto_id = (uint8_t)next_proto;
6229 case RTE_FLOW_ITEM_TYPE_IPV6:
6230 ipv6 = (struct rte_flow_item_ipv6 *)buf;
6231 if (next_proto && ipv6->hdr.proto == 0)
6232 ipv6->hdr.proto = (uint8_t)next_proto;
6233 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->hdr.vtc_flow);
6234 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
6235 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
6236 ipv6->hdr.vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
6238 case RTE_FLOW_ITEM_TYPE_VXLAN:
6239 vxlan = (struct rte_flow_item_vxlan *)buf;
6240 vxlan->flags = 0x08;
6242 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
6243 gpe = (struct rte_flow_item_vxlan_gpe *)buf;
6246 case RTE_FLOW_ITEM_TYPE_NVGRE:
6247 nvgre = (struct rte_flow_item_nvgre *)buf;
6248 nvgre->protocol = rte_cpu_to_be_16(0x6558);
6249 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
6256 /** Helper of get item's default mask. */
6258 flow_item_default_mask(const struct rte_flow_item *item)
6260 const void *mask = NULL;
6261 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
6263 switch (item->type) {
6264 case RTE_FLOW_ITEM_TYPE_ANY:
6265 mask = &rte_flow_item_any_mask;
6267 case RTE_FLOW_ITEM_TYPE_VF:
6268 mask = &rte_flow_item_vf_mask;
6270 case RTE_FLOW_ITEM_TYPE_PORT_ID:
6271 mask = &rte_flow_item_port_id_mask;
6273 case RTE_FLOW_ITEM_TYPE_RAW:
6274 mask = &rte_flow_item_raw_mask;
6276 case RTE_FLOW_ITEM_TYPE_ETH:
6277 mask = &rte_flow_item_eth_mask;
6279 case RTE_FLOW_ITEM_TYPE_VLAN:
6280 mask = &rte_flow_item_vlan_mask;
6282 case RTE_FLOW_ITEM_TYPE_IPV4:
6283 mask = &rte_flow_item_ipv4_mask;
6285 case RTE_FLOW_ITEM_TYPE_IPV6:
6286 mask = &rte_flow_item_ipv6_mask;
6288 case RTE_FLOW_ITEM_TYPE_ICMP:
6289 mask = &rte_flow_item_icmp_mask;
6291 case RTE_FLOW_ITEM_TYPE_UDP:
6292 mask = &rte_flow_item_udp_mask;
6294 case RTE_FLOW_ITEM_TYPE_TCP:
6295 mask = &rte_flow_item_tcp_mask;
6297 case RTE_FLOW_ITEM_TYPE_SCTP:
6298 mask = &rte_flow_item_sctp_mask;
6300 case RTE_FLOW_ITEM_TYPE_VXLAN:
6301 mask = &rte_flow_item_vxlan_mask;
6303 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
6304 mask = &rte_flow_item_vxlan_gpe_mask;
6306 case RTE_FLOW_ITEM_TYPE_E_TAG:
6307 mask = &rte_flow_item_e_tag_mask;
6309 case RTE_FLOW_ITEM_TYPE_NVGRE:
6310 mask = &rte_flow_item_nvgre_mask;
6312 case RTE_FLOW_ITEM_TYPE_MPLS:
6313 mask = &rte_flow_item_mpls_mask;
6315 case RTE_FLOW_ITEM_TYPE_GRE:
6316 mask = &rte_flow_item_gre_mask;
6318 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
6319 mask = &gre_key_default_mask;
6321 case RTE_FLOW_ITEM_TYPE_META:
6322 mask = &rte_flow_item_meta_mask;
6324 case RTE_FLOW_ITEM_TYPE_FUZZY:
6325 mask = &rte_flow_item_fuzzy_mask;
6327 case RTE_FLOW_ITEM_TYPE_GTP:
6328 mask = &rte_flow_item_gtp_mask;
6330 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
6331 mask = &rte_flow_item_gtp_psc_mask;
6333 case RTE_FLOW_ITEM_TYPE_GENEVE:
6334 mask = &rte_flow_item_geneve_mask;
6336 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
6337 mask = &rte_flow_item_pppoe_proto_id_mask;
6339 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
6340 mask = &rte_flow_item_l2tpv3oip_mask;
6342 case RTE_FLOW_ITEM_TYPE_ESP:
6343 mask = &rte_flow_item_esp_mask;
6353 /** Dispatch parsed buffer to function calls. */
6355 cmd_set_raw_parsed(const struct buffer *in)
6357 uint32_t n = in->args.vc.pattern_n;
6359 struct rte_flow_item *item = NULL;
6361 uint8_t *data = NULL;
6362 uint8_t *data_tail = NULL;
6363 size_t *total_size = NULL;
6364 uint16_t upper_layer = 0;
6366 uint16_t idx = in->port; /* We borrow port field as index */
6368 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
6369 in->command == SET_RAW_DECAP);
6370 if (in->command == SET_RAW_ENCAP) {
6371 total_size = &raw_encap_confs[idx].size;
6372 data = (uint8_t *)&raw_encap_confs[idx].data;
6374 total_size = &raw_decap_confs[idx].size;
6375 data = (uint8_t *)&raw_decap_confs[idx].data;
6378 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
6379 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
6380 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
6381 for (i = n - 1 ; i >= 0; --i) {
6382 item = in->args.vc.pattern + i;
6383 if (item->spec == NULL)
6384 item->spec = flow_item_default_mask(item);
6385 switch (item->type) {
6386 case RTE_FLOW_ITEM_TYPE_ETH:
6387 size = sizeof(struct rte_flow_item_eth);
6389 case RTE_FLOW_ITEM_TYPE_VLAN:
6390 size = sizeof(struct rte_flow_item_vlan);
6391 proto = RTE_ETHER_TYPE_VLAN;
6393 case RTE_FLOW_ITEM_TYPE_IPV4:
6394 size = sizeof(struct rte_flow_item_ipv4);
6395 proto = RTE_ETHER_TYPE_IPV4;
6397 case RTE_FLOW_ITEM_TYPE_IPV6:
6398 size = sizeof(struct rte_flow_item_ipv6);
6399 proto = RTE_ETHER_TYPE_IPV6;
6401 case RTE_FLOW_ITEM_TYPE_UDP:
6402 size = sizeof(struct rte_flow_item_udp);
6405 case RTE_FLOW_ITEM_TYPE_TCP:
6406 size = sizeof(struct rte_flow_item_tcp);
6409 case RTE_FLOW_ITEM_TYPE_VXLAN:
6410 size = sizeof(struct rte_flow_item_vxlan);
6412 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
6413 size = sizeof(struct rte_flow_item_vxlan_gpe);
6415 case RTE_FLOW_ITEM_TYPE_GRE:
6416 size = sizeof(struct rte_flow_item_gre);
6419 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
6420 size = sizeof(rte_be32_t);
6423 case RTE_FLOW_ITEM_TYPE_MPLS:
6424 size = sizeof(struct rte_flow_item_mpls);
6427 case RTE_FLOW_ITEM_TYPE_NVGRE:
6428 size = sizeof(struct rte_flow_item_nvgre);
6431 case RTE_FLOW_ITEM_TYPE_GENEVE:
6432 size = sizeof(struct rte_flow_item_geneve);
6434 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
6435 size = sizeof(struct rte_flow_item_l2tpv3oip);
6438 case RTE_FLOW_ITEM_TYPE_ESP:
6439 size = sizeof(struct rte_flow_item_esp);
6443 printf("Error - Not supported item\n");
6445 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
6448 *total_size += size;
6449 rte_memcpy(data_tail - (*total_size), item->spec, size);
6450 /* update some fields which cannot be set by cmdline */
6451 update_fields((data_tail - (*total_size)), item,
6453 upper_layer = proto;
6455 if (verbose_level & 0x1)
6456 printf("total data size is %zu\n", (*total_size));
6457 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
6458 memmove(data, (data_tail - (*total_size)), *total_size);
6461 /** Populate help strings for current token (cmdline API). */
6463 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
6466 struct context *ctx = &cmd_flow_context;
6467 const struct token *token = &token_list[ctx->prev];
6472 /* Set token type and update global help with details. */
6473 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
6475 cmd_set_raw.help_str = token->help;
6477 cmd_set_raw.help_str = token->name;
6481 /** Token definition template (cmdline API). */
6482 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
6483 .ops = &(struct cmdline_token_ops){
6484 .parse = cmd_flow_parse,
6485 .complete_get_nb = cmd_flow_complete_get_nb,
6486 .complete_get_elt = cmd_flow_complete_get_elt,
6487 .get_help = cmd_set_raw_get_help,
6492 /** Populate the next dynamic token. */
6494 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
6495 cmdline_parse_token_hdr_t **hdr_inst)
6497 struct context *ctx = &cmd_flow_context;
6499 /* Always reinitialize context before requesting the first token. */
6500 if (!(hdr_inst - cmd_set_raw.tokens)) {
6501 cmd_flow_context_init(ctx);
6502 ctx->curr = START_SET;
6504 /* Return NULL when no more tokens are expected. */
6505 if (!ctx->next_num && (ctx->curr != START_SET)) {
6509 /* Determine if command should end here. */
6510 if (ctx->eol && ctx->last && ctx->next_num) {
6511 const enum index *list = ctx->next[ctx->next_num - 1];
6514 for (i = 0; list[i]; ++i) {
6521 *hdr = &cmd_set_raw_token_hdr;
6524 /** Token generator and output processing callback (cmdline API). */
6526 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
6529 cmd_set_raw_tok(arg0, arg2);
6531 cmd_set_raw_parsed(arg0);
6534 /** Global parser instance (cmdline API). */
6535 cmdline_parse_inst_t cmd_set_raw = {
6536 .f = cmd_set_raw_cb,
6537 .data = NULL, /**< Unused. */
6538 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
6541 }, /**< Tokens are returned by cmd_flow_tok(). */
6544 /* *** display raw_encap/raw_decap buf */
6545 struct cmd_show_set_raw_result {
6546 cmdline_fixed_string_t cmd_show;
6547 cmdline_fixed_string_t cmd_what;
6548 cmdline_fixed_string_t cmd_all;
6553 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
6555 struct cmd_show_set_raw_result *res = parsed_result;
6556 uint16_t index = res->cmd_index;
6558 uint8_t *raw_data = NULL;
6559 size_t raw_size = 0;
6560 char title[16] = {0};
6564 if (!strcmp(res->cmd_all, "all")) {
6567 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
6568 printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1);
6572 if (!strcmp(res->cmd_what, "raw_encap")) {
6573 raw_data = (uint8_t *)&raw_encap_confs[index].data;
6574 raw_size = raw_encap_confs[index].size;
6575 snprintf(title, 16, "\nindex: %u", index);
6576 rte_hexdump(stdout, title, raw_data, raw_size);
6578 raw_data = (uint8_t *)&raw_decap_confs[index].data;
6579 raw_size = raw_decap_confs[index].size;
6580 snprintf(title, 16, "\nindex: %u", index);
6581 rte_hexdump(stdout, title, raw_data, raw_size);
6583 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
6586 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
6587 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
6589 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
6590 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
6591 cmd_what, "raw_encap#raw_decap");
6592 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
6593 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
6595 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
6596 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
6598 cmdline_parse_inst_t cmd_show_set_raw = {
6599 .f = cmd_show_set_raw_parsed,
6601 .help_str = "show <raw_encap|raw_decap> <index>",
6603 (void *)&cmd_show_set_raw_cmd_show,
6604 (void *)&cmd_show_set_raw_cmd_what,
6605 (void *)&cmd_show_set_raw_cmd_index,
6609 cmdline_parse_inst_t cmd_show_set_raw_all = {
6610 .f = cmd_show_set_raw_parsed,
6612 .help_str = "show <raw_encap|raw_decap> all",
6614 (void *)&cmd_show_set_raw_cmd_show,
6615 (void *)&cmd_show_set_raw_cmd_what,
6616 (void *)&cmd_show_set_raw_cmd_all,