1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016 6WIND S.A.
3 * Copyright 2016 Mellanox Technologies, Ltd
14 #include <rte_string_fns.h>
15 #include <rte_common.h>
16 #include <rte_ethdev.h>
17 #include <rte_byteorder.h>
18 #include <cmdline_parse.h>
19 #include <cmdline_parse_etheraddr.h>
20 #include <cmdline_parse_string.h>
21 #include <cmdline_parse_num.h>
23 #include <rte_hexdump.h>
24 #include <rte_vxlan.h>
28 #include <rte_geneve.h>
32 /** Parser token indices. */
54 COMMON_PRIORITY_LEVEL,
55 COMMON_INDIRECT_ACTION_ID,
60 /* TOP-level command. */
63 /* Top-level command. */
65 /* Sub-leve commands. */
72 /* Top-level command. */
74 /* Sub-level commands. */
93 /* Tunnel arguments. */
100 /* Destroy arguments. */
103 /* Query arguments. */
106 /* List arguments. */
109 /* Destroy aged flow arguments. */
112 /* Validate/create arguments. */
125 /* Indirect action arguments */
126 INDIRECT_ACTION_CREATE,
127 INDIRECT_ACTION_UPDATE,
128 INDIRECT_ACTION_DESTROY,
129 INDIRECT_ACTION_QUERY,
131 /* Indirect action create arguments */
132 INDIRECT_ACTION_CREATE_ID,
133 INDIRECT_ACTION_INGRESS,
134 INDIRECT_ACTION_EGRESS,
135 INDIRECT_ACTION_TRANSFER,
136 INDIRECT_ACTION_SPEC,
138 /* Indirect action destroy arguments */
139 INDIRECT_ACTION_DESTROY_ID,
141 /* Validate/create pattern. */
169 ITEM_RAW_PATTERN_HEX,
180 ITEM_VLAN_INNER_TYPE,
181 ITEM_VLAN_HAS_MORE_VLAN,
186 ITEM_IPV4_FRAGMENT_OFFSET,
198 ITEM_IPV6_HAS_FRAG_EXT,
218 ITEM_VXLAN_LAST_RSVD,
220 ITEM_E_TAG_GRP_ECID_B,
229 ITEM_GRE_C_RSVD0_VER,
248 ITEM_ARP_ETH_IPV4_SHA,
249 ITEM_ARP_ETH_IPV4_SPA,
250 ITEM_ARP_ETH_IPV4_THA,
251 ITEM_ARP_ETH_IPV4_TPA,
253 ITEM_IPV6_EXT_NEXT_HDR,
255 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
256 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
257 ITEM_IPV6_FRAG_EXT_ID,
262 ITEM_ICMP6_ND_NS_TARGET_ADDR,
264 ITEM_ICMP6_ND_NA_TARGET_ADDR,
266 ITEM_ICMP6_ND_OPT_TYPE,
267 ITEM_ICMP6_ND_OPT_SLA_ETH,
268 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
269 ITEM_ICMP6_ND_OPT_TLA_ETH,
270 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
283 ITEM_HIGIG2_CLASSIFICATION,
289 ITEM_L2TPV3OIP_SESSION_ID,
299 ITEM_ECPRI_COMMON_TYPE,
300 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
301 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
302 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
303 ITEM_ECPRI_MSG_IQ_DATA_PCID,
304 ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
305 ITEM_ECPRI_MSG_DLY_MSR_MSRID,
307 ITEM_GENEVE_OPT_CLASS,
308 ITEM_GENEVE_OPT_TYPE,
309 ITEM_GENEVE_OPT_LENGTH,
310 ITEM_GENEVE_OPT_DATA,
312 ITEM_INTEGRITY_LEVEL,
313 ITEM_INTEGRITY_VALUE,
318 ITEM_PORT_REPRESENTOR,
319 ITEM_PORT_REPRESENTOR_PORT_ID,
320 ITEM_REPRESENTED_PORT,
321 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
323 ITEM_FLEX_ITEM_HANDLE,
324 ITEM_FLEX_PATTERN_HANDLE,
327 ITEM_L2TPV2_TYPE_DATA,
328 ITEM_L2TPV2_TYPE_DATA_L,
329 ITEM_L2TPV2_TYPE_DATA_S,
330 ITEM_L2TPV2_TYPE_DATA_O,
331 ITEM_L2TPV2_TYPE_DATA_L_S,
332 ITEM_L2TPV2_TYPE_CTRL,
333 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
334 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
335 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
336 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
337 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
338 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
339 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
340 ITEM_L2TPV2_MSG_DATA_S_NS,
341 ITEM_L2TPV2_MSG_DATA_S_NR,
342 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
343 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
344 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
345 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
346 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
347 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
348 ITEM_L2TPV2_MSG_DATA_L_S_NS,
349 ITEM_L2TPV2_MSG_DATA_L_S_NR,
350 ITEM_L2TPV2_MSG_CTRL_LENGTH,
351 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
352 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
353 ITEM_L2TPV2_MSG_CTRL_NS,
354 ITEM_L2TPV2_MSG_CTRL_NR,
360 /* Validate/create actions. */
379 ACTION_RSS_FUNC_DEFAULT,
380 ACTION_RSS_FUNC_TOEPLITZ,
381 ACTION_RSS_FUNC_SIMPLE_XOR,
382 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
394 ACTION_PHY_PORT_ORIGINAL,
395 ACTION_PHY_PORT_INDEX,
397 ACTION_PORT_ID_ORIGINAL,
401 ACTION_METER_COLOR_TYPE,
402 ACTION_METER_COLOR_GREEN,
403 ACTION_METER_COLOR_YELLOW,
404 ACTION_METER_COLOR_RED,
406 ACTION_OF_SET_MPLS_TTL,
407 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
408 ACTION_OF_DEC_MPLS_TTL,
409 ACTION_OF_SET_NW_TTL,
410 ACTION_OF_SET_NW_TTL_NW_TTL,
411 ACTION_OF_DEC_NW_TTL,
412 ACTION_OF_COPY_TTL_OUT,
413 ACTION_OF_COPY_TTL_IN,
416 ACTION_OF_PUSH_VLAN_ETHERTYPE,
417 ACTION_OF_SET_VLAN_VID,
418 ACTION_OF_SET_VLAN_VID_VLAN_VID,
419 ACTION_OF_SET_VLAN_PCP,
420 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
422 ACTION_OF_POP_MPLS_ETHERTYPE,
424 ACTION_OF_PUSH_MPLS_ETHERTYPE,
431 ACTION_MPLSOGRE_ENCAP,
432 ACTION_MPLSOGRE_DECAP,
433 ACTION_MPLSOUDP_ENCAP,
434 ACTION_MPLSOUDP_DECAP,
436 ACTION_SET_IPV4_SRC_IPV4_SRC,
438 ACTION_SET_IPV4_DST_IPV4_DST,
440 ACTION_SET_IPV6_SRC_IPV6_SRC,
442 ACTION_SET_IPV6_DST_IPV6_DST,
444 ACTION_SET_TP_SRC_TP_SRC,
446 ACTION_SET_TP_DST_TP_DST,
452 ACTION_SET_MAC_SRC_MAC_SRC,
454 ACTION_SET_MAC_DST_MAC_DST,
456 ACTION_INC_TCP_SEQ_VALUE,
458 ACTION_DEC_TCP_SEQ_VALUE,
460 ACTION_INC_TCP_ACK_VALUE,
462 ACTION_DEC_TCP_ACK_VALUE,
465 ACTION_RAW_ENCAP_INDEX,
466 ACTION_RAW_ENCAP_INDEX_VALUE,
467 ACTION_RAW_DECAP_INDEX,
468 ACTION_RAW_DECAP_INDEX_VALUE,
471 ACTION_SET_TAG_INDEX,
474 ACTION_SET_META_DATA,
475 ACTION_SET_META_MASK,
476 ACTION_SET_IPV4_DSCP,
477 ACTION_SET_IPV4_DSCP_VALUE,
478 ACTION_SET_IPV6_DSCP,
479 ACTION_SET_IPV6_DSCP_VALUE,
485 ACTION_SAMPLE_INDEX_VALUE,
487 INDIRECT_ACTION_ID2PTR,
489 ACTION_MODIFY_FIELD_OP,
490 ACTION_MODIFY_FIELD_OP_VALUE,
491 ACTION_MODIFY_FIELD_DST_TYPE,
492 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
493 ACTION_MODIFY_FIELD_DST_LEVEL,
494 ACTION_MODIFY_FIELD_DST_OFFSET,
495 ACTION_MODIFY_FIELD_SRC_TYPE,
496 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
497 ACTION_MODIFY_FIELD_SRC_LEVEL,
498 ACTION_MODIFY_FIELD_SRC_OFFSET,
499 ACTION_MODIFY_FIELD_SRC_VALUE,
500 ACTION_MODIFY_FIELD_SRC_POINTER,
501 ACTION_MODIFY_FIELD_WIDTH,
503 ACTION_CONNTRACK_UPDATE,
504 ACTION_CONNTRACK_UPDATE_DIR,
505 ACTION_CONNTRACK_UPDATE_CTX,
509 ACTION_PORT_REPRESENTOR,
510 ACTION_PORT_REPRESENTOR_PORT_ID,
511 ACTION_REPRESENTED_PORT,
512 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
515 /** Maximum size for pattern in struct rte_flow_item_raw. */
516 #define ITEM_RAW_PATTERN_SIZE 512
518 /** Maximum size for GENEVE option data pattern in bytes. */
519 #define ITEM_GENEVE_OPT_DATA_SIZE 124
521 /** Storage size for struct rte_flow_item_raw including pattern. */
522 #define ITEM_RAW_SIZE \
523 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
525 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
526 #define ACTION_MODIFY_PATTERN_SIZE 32
528 /** Storage size for struct rte_flow_action_modify_field including pattern. */
529 #define ACTION_MODIFY_SIZE \
530 (sizeof(struct rte_flow_action_modify_field) + \
531 ACTION_MODIFY_PATTERN_SIZE)
533 /** Maximum number of queue indices in struct rte_flow_action_rss. */
534 #define ACTION_RSS_QUEUE_NUM 128
536 /** Storage for struct rte_flow_action_rss including external data. */
537 struct action_rss_data {
538 struct rte_flow_action_rss conf;
539 uint8_t key[RSS_HASH_KEY_LENGTH];
540 uint16_t queue[ACTION_RSS_QUEUE_NUM];
543 /** Maximum data size in struct rte_flow_action_raw_encap. */
544 #define ACTION_RAW_ENCAP_MAX_DATA 512
545 #define RAW_ENCAP_CONFS_MAX_NUM 8
547 /** Storage for struct rte_flow_action_raw_encap. */
548 struct raw_encap_conf {
549 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
550 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
554 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
556 /** Storage for struct rte_flow_action_raw_encap including external data. */
557 struct action_raw_encap_data {
558 struct rte_flow_action_raw_encap conf;
559 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
560 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
564 /** Storage for struct rte_flow_action_raw_decap. */
565 struct raw_decap_conf {
566 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
570 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
572 /** Storage for struct rte_flow_action_raw_decap including external data. */
573 struct action_raw_decap_data {
574 struct rte_flow_action_raw_decap conf;
575 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
579 struct vxlan_encap_conf vxlan_encap_conf = {
583 .vni = "\x00\x00\x00",
585 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
586 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
587 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
588 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
589 "\x00\x00\x00\x00\x00\x00\x00\x01",
590 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
591 "\x00\x00\x00\x00\x00\x00\x11\x11",
595 .eth_src = "\x00\x00\x00\x00\x00\x00",
596 .eth_dst = "\xff\xff\xff\xff\xff\xff",
599 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
600 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
602 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
603 struct action_vxlan_encap_data {
604 struct rte_flow_action_vxlan_encap conf;
605 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
606 struct rte_flow_item_eth item_eth;
607 struct rte_flow_item_vlan item_vlan;
609 struct rte_flow_item_ipv4 item_ipv4;
610 struct rte_flow_item_ipv6 item_ipv6;
612 struct rte_flow_item_udp item_udp;
613 struct rte_flow_item_vxlan item_vxlan;
616 struct nvgre_encap_conf nvgre_encap_conf = {
619 .tni = "\x00\x00\x00",
620 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
621 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
622 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
623 "\x00\x00\x00\x00\x00\x00\x00\x01",
624 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
625 "\x00\x00\x00\x00\x00\x00\x11\x11",
627 .eth_src = "\x00\x00\x00\x00\x00\x00",
628 .eth_dst = "\xff\xff\xff\xff\xff\xff",
631 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
632 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
634 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
635 struct action_nvgre_encap_data {
636 struct rte_flow_action_nvgre_encap conf;
637 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
638 struct rte_flow_item_eth item_eth;
639 struct rte_flow_item_vlan item_vlan;
641 struct rte_flow_item_ipv4 item_ipv4;
642 struct rte_flow_item_ipv6 item_ipv6;
644 struct rte_flow_item_nvgre item_nvgre;
647 struct l2_encap_conf l2_encap_conf;
649 struct l2_decap_conf l2_decap_conf;
651 struct mplsogre_encap_conf mplsogre_encap_conf;
653 struct mplsogre_decap_conf mplsogre_decap_conf;
655 struct mplsoudp_encap_conf mplsoudp_encap_conf;
657 struct mplsoudp_decap_conf mplsoudp_decap_conf;
659 struct rte_flow_action_conntrack conntrack_context;
661 #define ACTION_SAMPLE_ACTIONS_NUM 10
662 #define RAW_SAMPLE_CONFS_MAX_NUM 8
663 /** Storage for struct rte_flow_action_sample including external data. */
664 struct action_sample_data {
665 struct rte_flow_action_sample conf;
668 /** Storage for struct rte_flow_action_sample. */
669 struct raw_sample_conf {
670 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
672 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
673 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
674 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
675 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
676 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
677 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
678 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
679 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
680 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
681 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
683 static const char *const modify_field_ops[] = {
684 "set", "add", "sub", NULL
687 static const char *const modify_field_ids[] = {
688 "start", "mac_dst", "mac_src",
689 "vlan_type", "vlan_id", "mac_type",
690 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
691 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
692 "tcp_port_src", "tcp_port_dst",
693 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
694 "udp_port_src", "udp_port_dst",
695 "vxlan_vni", "geneve_vni", "gtp_teid",
696 "tag", "mark", "meta", "pointer", "value", NULL
699 /** Maximum number of subsequent tokens and arguments on the stack. */
700 #define CTX_STACK_SIZE 16
702 /** Parser context. */
704 /** Stack of subsequent token lists to process. */
705 const enum index *next[CTX_STACK_SIZE];
706 /** Arguments for stacked tokens. */
707 const void *args[CTX_STACK_SIZE];
708 enum index curr; /**< Current token index. */
709 enum index prev; /**< Index of the last token seen. */
710 int next_num; /**< Number of entries in next[]. */
711 int args_num; /**< Number of entries in args[]. */
712 uint32_t eol:1; /**< EOL has been detected. */
713 uint32_t last:1; /**< No more arguments. */
714 portid_t port; /**< Current port ID (for completions). */
715 uint32_t objdata; /**< Object-specific data. */
716 void *object; /**< Address of current object for relative offsets. */
717 void *objmask; /**< Object a full mask must be written to. */
720 /** Token argument. */
722 uint32_t hton:1; /**< Use network byte ordering. */
723 uint32_t sign:1; /**< Value is signed. */
724 uint32_t bounded:1; /**< Value is bounded. */
725 uintmax_t min; /**< Minimum value if bounded. */
726 uintmax_t max; /**< Maximum value if bounded. */
727 uint32_t offset; /**< Relative offset from ctx->object. */
728 uint32_t size; /**< Field size. */
729 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
732 /** Parser token definition. */
734 /** Type displayed during completion (defaults to "TOKEN"). */
736 /** Help displayed during completion (defaults to token name). */
738 /** Private data used by parser functions. */
741 * Lists of subsequent tokens to push on the stack. Each call to the
742 * parser consumes the last entry of that stack.
744 const enum index *const *next;
745 /** Arguments stack for subsequent tokens that need them. */
746 const struct arg *const *args;
748 * Token-processing callback, returns -1 in case of error, the
749 * length of the matched string otherwise. If NULL, attempts to
750 * match the token name.
752 * If buf is not NULL, the result should be stored in it according
753 * to context. An error is returned if not large enough.
755 int (*call)(struct context *ctx, const struct token *token,
756 const char *str, unsigned int len,
757 void *buf, unsigned int size);
759 * Callback that provides possible values for this token, used for
760 * completion. Returns -1 in case of error, the number of possible
761 * values otherwise. If NULL, the token name is used.
763 * If buf is not NULL, entry index ent is written to buf and the
764 * full length of the entry is returned (same behavior as
767 int (*comp)(struct context *ctx, const struct token *token,
768 unsigned int ent, char *buf, unsigned int size);
769 /** Mandatory token name, no default value. */
773 /** Static initializer for the next field. */
774 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
776 /** Static initializer for a NEXT() entry. */
777 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
779 /** Static initializer for the args field. */
780 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
782 /** Static initializer for ARGS() to target a field. */
783 #define ARGS_ENTRY(s, f) \
784 (&(const struct arg){ \
785 .offset = offsetof(s, f), \
786 .size = sizeof(((s *)0)->f), \
789 /** Static initializer for ARGS() to target a bit-field. */
790 #define ARGS_ENTRY_BF(s, f, b) \
791 (&(const struct arg){ \
793 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
796 /** Static initializer for ARGS() to target a field with limits. */
797 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
798 (&(const struct arg){ \
802 .offset = offsetof(s, f), \
803 .size = sizeof(((s *)0)->f), \
806 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
807 #define ARGS_ENTRY_MASK(s, f, m) \
808 (&(const struct arg){ \
809 .offset = offsetof(s, f), \
810 .size = sizeof(((s *)0)->f), \
811 .mask = (const void *)(m), \
814 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
815 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
816 (&(const struct arg){ \
818 .offset = offsetof(s, f), \
819 .size = sizeof(((s *)0)->f), \
820 .mask = (const void *)(m), \
823 /** Static initializer for ARGS() to target a pointer. */
824 #define ARGS_ENTRY_PTR(s, f) \
825 (&(const struct arg){ \
826 .size = sizeof(*((s *)0)->f), \
829 /** Static initializer for ARGS() with arbitrary offset and size. */
830 #define ARGS_ENTRY_ARB(o, s) \
831 (&(const struct arg){ \
836 /** Same as ARGS_ENTRY_ARB() with bounded values. */
837 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
838 (&(const struct arg){ \
846 /** Same as ARGS_ENTRY() using network byte ordering. */
847 #define ARGS_ENTRY_HTON(s, f) \
848 (&(const struct arg){ \
850 .offset = offsetof(s, f), \
851 .size = sizeof(((s *)0)->f), \
854 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
855 #define ARG_ENTRY_HTON(s) \
856 (&(const struct arg){ \
862 /** Parser output buffer layout expected by cmd_flow_parsed(). */
864 enum index command; /**< Flow command. */
865 portid_t port; /**< Affected port ID. */
869 uint32_t action_id_n;
870 } ia_destroy; /**< Indirect action destroy arguments. */
873 } ia; /* Indirect action query arguments */
875 struct rte_flow_attr attr;
876 struct tunnel_ops tunnel_ops;
877 struct rte_flow_item *pattern;
878 struct rte_flow_action *actions;
882 } vc; /**< Validate/create arguments. */
886 } destroy; /**< Destroy arguments. */
891 } dump; /**< Dump arguments. */
894 struct rte_flow_action action;
895 } query; /**< Query arguments. */
899 } list; /**< List arguments. */
902 } isolate; /**< Isolated mode arguments. */
905 } aged; /**< Aged arguments. */
908 } policy;/**< Policy arguments. */
913 } flex; /**< Flex arguments*/
914 } args; /**< Command arguments. */
917 /** Private data for pattern items. */
918 struct parse_item_priv {
919 enum rte_flow_item_type type; /**< Item type. */
920 uint32_t size; /**< Size of item specification structure. */
923 #define PRIV_ITEM(t, s) \
924 (&(const struct parse_item_priv){ \
925 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
929 /** Private data for actions. */
930 struct parse_action_priv {
931 enum rte_flow_action_type type; /**< Action type. */
932 uint32_t size; /**< Size of action configuration structure. */
935 #define PRIV_ACTION(t, s) \
936 (&(const struct parse_action_priv){ \
937 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
941 static const enum index next_flex_item[] = {
948 static const enum index next_ia_create_attr[] = {
949 INDIRECT_ACTION_CREATE_ID,
950 INDIRECT_ACTION_INGRESS,
951 INDIRECT_ACTION_EGRESS,
952 INDIRECT_ACTION_TRANSFER,
953 INDIRECT_ACTION_SPEC,
957 static const enum index next_dump_subcmd[] = {
963 static const enum index next_ia_subcmd[] = {
964 INDIRECT_ACTION_CREATE,
965 INDIRECT_ACTION_UPDATE,
966 INDIRECT_ACTION_DESTROY,
967 INDIRECT_ACTION_QUERY,
971 static const enum index next_vc_attr[] = {
983 static const enum index next_destroy_attr[] = {
989 static const enum index next_dump_attr[] = {
995 static const enum index next_list_attr[] = {
1001 static const enum index next_aged_attr[] = {
1007 static const enum index next_ia_destroy_attr[] = {
1008 INDIRECT_ACTION_DESTROY_ID,
1013 static const enum index item_param[] = {
1022 static const enum index next_item[] = {
1059 ITEM_ICMP6_ND_OPT_SLA_ETH,
1060 ITEM_ICMP6_ND_OPT_TLA_ETH,
1066 ITEM_PPPOE_PROTO_ID,
1077 ITEM_PORT_REPRESENTOR,
1078 ITEM_REPRESENTED_PORT,
1086 static const enum index item_fuzzy[] = {
1092 static const enum index item_any[] = {
1098 static const enum index item_vf[] = {
1104 static const enum index item_phy_port[] = {
1105 ITEM_PHY_PORT_INDEX,
1110 static const enum index item_port_id[] = {
1116 static const enum index item_mark[] = {
1122 static const enum index item_raw[] = {
1128 ITEM_RAW_PATTERN_HEX,
1133 static const enum index item_eth[] = {
1142 static const enum index item_vlan[] = {
1147 ITEM_VLAN_INNER_TYPE,
1148 ITEM_VLAN_HAS_MORE_VLAN,
1153 static const enum index item_ipv4[] = {
1157 ITEM_IPV4_FRAGMENT_OFFSET,
1166 static const enum index item_ipv6[] = {
1173 ITEM_IPV6_HAS_FRAG_EXT,
1178 static const enum index item_icmp[] = {
1187 static const enum index item_udp[] = {
1194 static const enum index item_tcp[] = {
1202 static const enum index item_sctp[] = {
1211 static const enum index item_vxlan[] = {
1213 ITEM_VXLAN_LAST_RSVD,
1218 static const enum index item_e_tag[] = {
1219 ITEM_E_TAG_GRP_ECID_B,
1224 static const enum index item_nvgre[] = {
1230 static const enum index item_mpls[] = {
1238 static const enum index item_gre[] = {
1240 ITEM_GRE_C_RSVD0_VER,
1248 static const enum index item_gre_key[] = {
1254 static const enum index item_gtp[] = {
1262 static const enum index item_geneve[] = {
1270 static const enum index item_vxlan_gpe[] = {
1276 static const enum index item_arp_eth_ipv4[] = {
1277 ITEM_ARP_ETH_IPV4_SHA,
1278 ITEM_ARP_ETH_IPV4_SPA,
1279 ITEM_ARP_ETH_IPV4_THA,
1280 ITEM_ARP_ETH_IPV4_TPA,
1285 static const enum index item_ipv6_ext[] = {
1286 ITEM_IPV6_EXT_NEXT_HDR,
1291 static const enum index item_ipv6_frag_ext[] = {
1292 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1293 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1294 ITEM_IPV6_FRAG_EXT_ID,
1299 static const enum index item_icmp6[] = {
1306 static const enum index item_icmp6_nd_ns[] = {
1307 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1312 static const enum index item_icmp6_nd_na[] = {
1313 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1318 static const enum index item_icmp6_nd_opt[] = {
1319 ITEM_ICMP6_ND_OPT_TYPE,
1324 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1325 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1330 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1331 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1336 static const enum index item_meta[] = {
1342 static const enum index item_gtp_psc[] = {
1349 static const enum index item_pppoed[] = {
1355 static const enum index item_pppoes[] = {
1361 static const enum index item_pppoe_proto_id[] = {
1366 static const enum index item_higig2[] = {
1367 ITEM_HIGIG2_CLASSIFICATION,
1373 static const enum index item_esp[] = {
1379 static const enum index item_ah[] = {
1385 static const enum index item_pfcp[] = {
1392 static const enum index next_set_raw[] = {
1398 static const enum index item_tag[] = {
1405 static const enum index item_l2tpv3oip[] = {
1406 ITEM_L2TPV3OIP_SESSION_ID,
1411 static const enum index item_ecpri[] = {
1417 static const enum index item_ecpri_common[] = {
1418 ITEM_ECPRI_COMMON_TYPE,
1422 static const enum index item_ecpri_common_type[] = {
1423 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1424 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1425 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1429 static const enum index item_geneve_opt[] = {
1430 ITEM_GENEVE_OPT_CLASS,
1431 ITEM_GENEVE_OPT_TYPE,
1432 ITEM_GENEVE_OPT_LENGTH,
1433 ITEM_GENEVE_OPT_DATA,
1438 static const enum index item_integrity[] = {
1439 ITEM_INTEGRITY_LEVEL,
1440 ITEM_INTEGRITY_VALUE,
1444 static const enum index item_integrity_lv[] = {
1445 ITEM_INTEGRITY_LEVEL,
1446 ITEM_INTEGRITY_VALUE,
1451 static const enum index item_port_representor[] = {
1452 ITEM_PORT_REPRESENTOR_PORT_ID,
1457 static const enum index item_represented_port[] = {
1458 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1463 static const enum index item_flex[] = {
1464 ITEM_FLEX_PATTERN_HANDLE,
1465 ITEM_FLEX_ITEM_HANDLE,
1470 static const enum index item_l2tpv2[] = {
1476 static const enum index item_l2tpv2_type[] = {
1477 ITEM_L2TPV2_TYPE_DATA,
1478 ITEM_L2TPV2_TYPE_DATA_L,
1479 ITEM_L2TPV2_TYPE_DATA_S,
1480 ITEM_L2TPV2_TYPE_DATA_O,
1481 ITEM_L2TPV2_TYPE_DATA_L_S,
1482 ITEM_L2TPV2_TYPE_CTRL,
1486 static const enum index item_l2tpv2_type_data[] = {
1487 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1488 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1493 static const enum index item_l2tpv2_type_data_l[] = {
1494 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1495 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1496 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1501 static const enum index item_l2tpv2_type_data_s[] = {
1502 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1503 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1504 ITEM_L2TPV2_MSG_DATA_S_NS,
1505 ITEM_L2TPV2_MSG_DATA_S_NR,
1510 static const enum index item_l2tpv2_type_data_o[] = {
1511 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1512 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1513 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1518 static const enum index item_l2tpv2_type_data_l_s[] = {
1519 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1520 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1521 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1522 ITEM_L2TPV2_MSG_DATA_L_S_NS,
1523 ITEM_L2TPV2_MSG_DATA_L_S_NR,
1528 static const enum index item_l2tpv2_type_ctrl[] = {
1529 ITEM_L2TPV2_MSG_CTRL_LENGTH,
1530 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1531 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1532 ITEM_L2TPV2_MSG_CTRL_NS,
1533 ITEM_L2TPV2_MSG_CTRL_NR,
1538 static const enum index item_ppp[] = {
1546 static const enum index next_action[] = {
1563 ACTION_OF_SET_MPLS_TTL,
1564 ACTION_OF_DEC_MPLS_TTL,
1565 ACTION_OF_SET_NW_TTL,
1566 ACTION_OF_DEC_NW_TTL,
1567 ACTION_OF_COPY_TTL_OUT,
1568 ACTION_OF_COPY_TTL_IN,
1570 ACTION_OF_PUSH_VLAN,
1571 ACTION_OF_SET_VLAN_VID,
1572 ACTION_OF_SET_VLAN_PCP,
1574 ACTION_OF_PUSH_MPLS,
1581 ACTION_MPLSOGRE_ENCAP,
1582 ACTION_MPLSOGRE_DECAP,
1583 ACTION_MPLSOUDP_ENCAP,
1584 ACTION_MPLSOUDP_DECAP,
1585 ACTION_SET_IPV4_SRC,
1586 ACTION_SET_IPV4_DST,
1587 ACTION_SET_IPV6_SRC,
1588 ACTION_SET_IPV6_DST,
1604 ACTION_SET_IPV4_DSCP,
1605 ACTION_SET_IPV6_DSCP,
1609 ACTION_MODIFY_FIELD,
1611 ACTION_CONNTRACK_UPDATE,
1612 ACTION_PORT_REPRESENTOR,
1613 ACTION_REPRESENTED_PORT,
1617 static const enum index action_mark[] = {
1623 static const enum index action_queue[] = {
1629 static const enum index action_count[] = {
1635 static const enum index action_rss[] = {
1646 static const enum index action_vf[] = {
1653 static const enum index action_phy_port[] = {
1654 ACTION_PHY_PORT_ORIGINAL,
1655 ACTION_PHY_PORT_INDEX,
1660 static const enum index action_port_id[] = {
1661 ACTION_PORT_ID_ORIGINAL,
1667 static const enum index action_meter[] = {
1673 static const enum index action_meter_color[] = {
1674 ACTION_METER_COLOR_TYPE,
1679 static const enum index action_of_set_mpls_ttl[] = {
1680 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1685 static const enum index action_of_set_nw_ttl[] = {
1686 ACTION_OF_SET_NW_TTL_NW_TTL,
1691 static const enum index action_of_push_vlan[] = {
1692 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1697 static const enum index action_of_set_vlan_vid[] = {
1698 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1703 static const enum index action_of_set_vlan_pcp[] = {
1704 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1709 static const enum index action_of_pop_mpls[] = {
1710 ACTION_OF_POP_MPLS_ETHERTYPE,
1715 static const enum index action_of_push_mpls[] = {
1716 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1721 static const enum index action_set_ipv4_src[] = {
1722 ACTION_SET_IPV4_SRC_IPV4_SRC,
1727 static const enum index action_set_mac_src[] = {
1728 ACTION_SET_MAC_SRC_MAC_SRC,
1733 static const enum index action_set_ipv4_dst[] = {
1734 ACTION_SET_IPV4_DST_IPV4_DST,
1739 static const enum index action_set_ipv6_src[] = {
1740 ACTION_SET_IPV6_SRC_IPV6_SRC,
1745 static const enum index action_set_ipv6_dst[] = {
1746 ACTION_SET_IPV6_DST_IPV6_DST,
1751 static const enum index action_set_tp_src[] = {
1752 ACTION_SET_TP_SRC_TP_SRC,
1757 static const enum index action_set_tp_dst[] = {
1758 ACTION_SET_TP_DST_TP_DST,
1763 static const enum index action_set_ttl[] = {
1769 static const enum index action_jump[] = {
1775 static const enum index action_set_mac_dst[] = {
1776 ACTION_SET_MAC_DST_MAC_DST,
1781 static const enum index action_inc_tcp_seq[] = {
1782 ACTION_INC_TCP_SEQ_VALUE,
1787 static const enum index action_dec_tcp_seq[] = {
1788 ACTION_DEC_TCP_SEQ_VALUE,
1793 static const enum index action_inc_tcp_ack[] = {
1794 ACTION_INC_TCP_ACK_VALUE,
1799 static const enum index action_dec_tcp_ack[] = {
1800 ACTION_DEC_TCP_ACK_VALUE,
1805 static const enum index action_raw_encap[] = {
1806 ACTION_RAW_ENCAP_INDEX,
1811 static const enum index action_raw_decap[] = {
1812 ACTION_RAW_DECAP_INDEX,
1817 static const enum index action_set_tag[] = {
1818 ACTION_SET_TAG_DATA,
1819 ACTION_SET_TAG_INDEX,
1820 ACTION_SET_TAG_MASK,
1825 static const enum index action_set_meta[] = {
1826 ACTION_SET_META_DATA,
1827 ACTION_SET_META_MASK,
1832 static const enum index action_set_ipv4_dscp[] = {
1833 ACTION_SET_IPV4_DSCP_VALUE,
1838 static const enum index action_set_ipv6_dscp[] = {
1839 ACTION_SET_IPV6_DSCP_VALUE,
1844 static const enum index action_age[] = {
1851 static const enum index action_sample[] = {
1853 ACTION_SAMPLE_RATIO,
1854 ACTION_SAMPLE_INDEX,
1859 static const enum index next_action_sample[] = {
1872 static const enum index action_modify_field_dst[] = {
1873 ACTION_MODIFY_FIELD_DST_LEVEL,
1874 ACTION_MODIFY_FIELD_DST_OFFSET,
1875 ACTION_MODIFY_FIELD_SRC_TYPE,
1879 static const enum index action_modify_field_src[] = {
1880 ACTION_MODIFY_FIELD_SRC_LEVEL,
1881 ACTION_MODIFY_FIELD_SRC_OFFSET,
1882 ACTION_MODIFY_FIELD_SRC_VALUE,
1883 ACTION_MODIFY_FIELD_SRC_POINTER,
1884 ACTION_MODIFY_FIELD_WIDTH,
1888 static const enum index action_update_conntrack[] = {
1889 ACTION_CONNTRACK_UPDATE_DIR,
1890 ACTION_CONNTRACK_UPDATE_CTX,
1895 static const enum index action_port_representor[] = {
1896 ACTION_PORT_REPRESENTOR_PORT_ID,
1901 static const enum index action_represented_port[] = {
1902 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
1907 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1908 const char *, unsigned int,
1909 void *, unsigned int);
1910 static int parse_set_sample_action(struct context *, const struct token *,
1911 const char *, unsigned int,
1912 void *, unsigned int);
1913 static int parse_set_init(struct context *, const struct token *,
1914 const char *, unsigned int,
1915 void *, unsigned int);
1917 parse_flex_handle(struct context *, const struct token *,
1918 const char *, unsigned int, void *, unsigned int);
1919 static int parse_init(struct context *, const struct token *,
1920 const char *, unsigned int,
1921 void *, unsigned int);
1922 static int parse_vc(struct context *, const struct token *,
1923 const char *, unsigned int,
1924 void *, unsigned int);
1925 static int parse_vc_spec(struct context *, const struct token *,
1926 const char *, unsigned int, void *, unsigned int);
1927 static int parse_vc_conf(struct context *, const struct token *,
1928 const char *, unsigned int, void *, unsigned int);
1929 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1930 const char *, unsigned int,
1931 void *, unsigned int);
1932 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
1933 const char *, unsigned int,
1934 void *, unsigned int);
1935 static int parse_vc_action_meter_color_type(struct context *,
1936 const struct token *,
1937 const char *, unsigned int, void *,
1939 static int parse_vc_action_rss(struct context *, const struct token *,
1940 const char *, unsigned int, void *,
1942 static int parse_vc_action_rss_func(struct context *, const struct token *,
1943 const char *, unsigned int, void *,
1945 static int parse_vc_action_rss_type(struct context *, const struct token *,
1946 const char *, unsigned int, void *,
1948 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1949 const char *, unsigned int, void *,
1951 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1952 const char *, unsigned int, void *,
1954 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1955 const char *, unsigned int, void *,
1957 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1958 const char *, unsigned int, void *,
1960 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1961 const char *, unsigned int, void *,
1963 static int parse_vc_action_mplsogre_encap(struct context *,
1964 const struct token *, const char *,
1965 unsigned int, void *, unsigned int);
1966 static int parse_vc_action_mplsogre_decap(struct context *,
1967 const struct token *, const char *,
1968 unsigned int, void *, unsigned int);
1969 static int parse_vc_action_mplsoudp_encap(struct context *,
1970 const struct token *, const char *,
1971 unsigned int, void *, unsigned int);
1972 static int parse_vc_action_mplsoudp_decap(struct context *,
1973 const struct token *, const char *,
1974 unsigned int, void *, unsigned int);
1975 static int parse_vc_action_raw_encap(struct context *,
1976 const struct token *, const char *,
1977 unsigned int, void *, unsigned int);
1978 static int parse_vc_action_raw_decap(struct context *,
1979 const struct token *, const char *,
1980 unsigned int, void *, unsigned int);
1981 static int parse_vc_action_raw_encap_index(struct context *,
1982 const struct token *, const char *,
1983 unsigned int, void *, unsigned int);
1984 static int parse_vc_action_raw_decap_index(struct context *,
1985 const struct token *, const char *,
1986 unsigned int, void *, unsigned int);
1987 static int parse_vc_action_set_meta(struct context *ctx,
1988 const struct token *token, const char *str,
1989 unsigned int len, void *buf,
1991 static int parse_vc_action_sample(struct context *ctx,
1992 const struct token *token, const char *str,
1993 unsigned int len, void *buf,
1996 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
1997 const char *str, unsigned int len, void *buf,
2000 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2001 const char *str, unsigned int len, void *buf,
2004 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2005 const char *str, unsigned int len, void *buf,
2008 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2009 const char *str, unsigned int len, void *buf,
2011 static int parse_destroy(struct context *, const struct token *,
2012 const char *, unsigned int,
2013 void *, unsigned int);
2014 static int parse_flush(struct context *, const struct token *,
2015 const char *, unsigned int,
2016 void *, unsigned int);
2017 static int parse_dump(struct context *, const struct token *,
2018 const char *, unsigned int,
2019 void *, unsigned int);
2020 static int parse_query(struct context *, const struct token *,
2021 const char *, unsigned int,
2022 void *, unsigned int);
2023 static int parse_action(struct context *, const struct token *,
2024 const char *, unsigned int,
2025 void *, unsigned int);
2026 static int parse_list(struct context *, const struct token *,
2027 const char *, unsigned int,
2028 void *, unsigned int);
2029 static int parse_aged(struct context *, const struct token *,
2030 const char *, unsigned int,
2031 void *, unsigned int);
2032 static int parse_isolate(struct context *, const struct token *,
2033 const char *, unsigned int,
2034 void *, unsigned int);
2035 static int parse_tunnel(struct context *, const struct token *,
2036 const char *, unsigned int,
2037 void *, unsigned int);
2038 static int parse_flex(struct context *, const struct token *,
2039 const char *, unsigned int, void *, unsigned int);
2040 static int parse_int(struct context *, const struct token *,
2041 const char *, unsigned int,
2042 void *, unsigned int);
2043 static int parse_prefix(struct context *, const struct token *,
2044 const char *, unsigned int,
2045 void *, unsigned int);
2046 static int parse_boolean(struct context *, const struct token *,
2047 const char *, unsigned int,
2048 void *, unsigned int);
2049 static int parse_string(struct context *, const struct token *,
2050 const char *, unsigned int,
2051 void *, unsigned int);
2052 static int parse_hex(struct context *ctx, const struct token *token,
2053 const char *str, unsigned int len,
2054 void *buf, unsigned int size);
2055 static int parse_string0(struct context *, const struct token *,
2056 const char *, unsigned int,
2057 void *, unsigned int);
2058 static int parse_mac_addr(struct context *, const struct token *,
2059 const char *, unsigned int,
2060 void *, unsigned int);
2061 static int parse_ipv4_addr(struct context *, const struct token *,
2062 const char *, unsigned int,
2063 void *, unsigned int);
2064 static int parse_ipv6_addr(struct context *, const struct token *,
2065 const char *, unsigned int,
2066 void *, unsigned int);
2067 static int parse_port(struct context *, const struct token *,
2068 const char *, unsigned int,
2069 void *, unsigned int);
2070 static int parse_ia(struct context *, const struct token *,
2071 const char *, unsigned int,
2072 void *, unsigned int);
2073 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2074 const char *str, unsigned int len,
2075 void *buf, unsigned int size);
2076 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2077 const char *str, unsigned int len, void *buf,
2079 static int parse_mp(struct context *, const struct token *,
2080 const char *, unsigned int,
2081 void *, unsigned int);
2082 static int comp_none(struct context *, const struct token *,
2083 unsigned int, char *, unsigned int);
2084 static int comp_boolean(struct context *, const struct token *,
2085 unsigned int, char *, unsigned int);
2086 static int comp_action(struct context *, const struct token *,
2087 unsigned int, char *, unsigned int);
2088 static int comp_port(struct context *, const struct token *,
2089 unsigned int, char *, unsigned int);
2090 static int comp_rule_id(struct context *, const struct token *,
2091 unsigned int, char *, unsigned int);
2092 static int comp_vc_action_rss_type(struct context *, const struct token *,
2093 unsigned int, char *, unsigned int);
2094 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2095 unsigned int, char *, unsigned int);
2096 static int comp_set_raw_index(struct context *, const struct token *,
2097 unsigned int, char *, unsigned int);
2098 static int comp_set_sample_index(struct context *, const struct token *,
2099 unsigned int, char *, unsigned int);
2100 static int comp_set_modify_field_op(struct context *, const struct token *,
2101 unsigned int, char *, unsigned int);
2102 static int comp_set_modify_field_id(struct context *, const struct token *,
2103 unsigned int, char *, unsigned int);
2105 /** Token definitions. */
2106 static const struct token token_list[] = {
2107 /* Special tokens. */
2110 .help = "null entry, abused as the entry point",
2111 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2116 .help = "command may end here",
2119 .name = "START_SET",
2120 .help = "null entry, abused as the entry point for set",
2121 .next = NEXT(NEXT_ENTRY(SET)),
2126 .help = "set command may end here",
2128 /* Common tokens. */
2129 [COMMON_INTEGER] = {
2132 .help = "integer value",
2136 [COMMON_UNSIGNED] = {
2137 .name = "{unsigned}",
2139 .help = "unsigned integer value",
2146 .help = "prefix length for bit-mask",
2147 .call = parse_prefix,
2150 [COMMON_BOOLEAN] = {
2151 .name = "{boolean}",
2153 .help = "any boolean value",
2154 .call = parse_boolean,
2155 .comp = comp_boolean,
2160 .help = "fixed string",
2161 .call = parse_string,
2167 .help = "fixed string",
2170 [COMMON_FILE_PATH] = {
2171 .name = "{file path}",
2173 .help = "file path",
2174 .call = parse_string0,
2177 [COMMON_MAC_ADDR] = {
2178 .name = "{MAC address}",
2180 .help = "standard MAC address notation",
2181 .call = parse_mac_addr,
2184 [COMMON_IPV4_ADDR] = {
2185 .name = "{IPv4 address}",
2186 .type = "IPV4 ADDRESS",
2187 .help = "standard IPv4 address notation",
2188 .call = parse_ipv4_addr,
2191 [COMMON_IPV6_ADDR] = {
2192 .name = "{IPv6 address}",
2193 .type = "IPV6 ADDRESS",
2194 .help = "standard IPv6 address notation",
2195 .call = parse_ipv6_addr,
2198 [COMMON_RULE_ID] = {
2199 .name = "{rule id}",
2201 .help = "rule identifier",
2203 .comp = comp_rule_id,
2205 [COMMON_PORT_ID] = {
2206 .name = "{port_id}",
2208 .help = "port identifier",
2212 [COMMON_GROUP_ID] = {
2213 .name = "{group_id}",
2215 .help = "group identifier",
2219 [COMMON_PRIORITY_LEVEL] = {
2222 .help = "priority level",
2226 [COMMON_INDIRECT_ACTION_ID] = {
2227 .name = "{indirect_action_id}",
2228 .type = "INDIRECT_ACTION_ID",
2229 .help = "indirect action id",
2233 [COMMON_POLICY_ID] = {
2234 .name = "{policy_id}",
2235 .type = "POLICY_ID",
2236 .help = "policy id",
2240 [COMMON_FLEX_TOKEN] = {
2241 .name = "{flex token}",
2242 .type = "flex token",
2243 .help = "flex token",
2247 [COMMON_FLEX_HANDLE] = {
2248 .name = "{flex handle}",
2249 .type = "FLEX HANDLE",
2250 .help = "fill flex item data",
2251 .call = parse_flex_handle,
2254 /* Top-level command. */
2257 .type = "{command} {port_id} [{arg} [...]]",
2258 .help = "manage ingress/egress flow rules",
2259 .next = NEXT(NEXT_ENTRY
2274 /* Top-level command. */
2275 [INDIRECT_ACTION] = {
2276 .name = "indirect_action",
2277 .type = "{command} {port_id} [{arg} [...]]",
2278 .help = "manage indirect actions",
2279 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2280 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2283 /* Sub-level commands. */
2284 [INDIRECT_ACTION_CREATE] = {
2286 .help = "create indirect action",
2287 .next = NEXT(next_ia_create_attr),
2290 [INDIRECT_ACTION_UPDATE] = {
2292 .help = "update indirect action",
2293 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2294 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2295 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2298 [INDIRECT_ACTION_DESTROY] = {
2300 .help = "destroy indirect action",
2301 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2302 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2303 .call = parse_ia_destroy,
2305 [INDIRECT_ACTION_QUERY] = {
2307 .help = "query indirect action",
2308 .next = NEXT(NEXT_ENTRY(END),
2309 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2310 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2315 .help = "check whether a flow rule can be created",
2316 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2317 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2322 .help = "create a flow rule",
2323 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2324 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2329 .help = "destroy specific flow rules",
2330 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2331 NEXT_ENTRY(COMMON_PORT_ID)),
2332 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2333 .call = parse_destroy,
2337 .help = "destroy all flow rules",
2338 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2339 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2340 .call = parse_flush,
2344 .help = "dump single/all flow rules to file",
2345 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2346 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2351 .help = "query an existing flow rule",
2352 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
2353 NEXT_ENTRY(COMMON_RULE_ID),
2354 NEXT_ENTRY(COMMON_PORT_ID)),
2355 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
2356 ARGS_ENTRY(struct buffer, args.query.rule),
2357 ARGS_ENTRY(struct buffer, port)),
2358 .call = parse_query,
2362 .help = "list existing flow rules",
2363 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2364 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2369 .help = "list and destroy aged flows",
2370 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2371 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2376 .help = "restrict ingress traffic to the defined flow rules",
2377 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
2378 NEXT_ENTRY(COMMON_PORT_ID)),
2379 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
2380 ARGS_ENTRY(struct buffer, port)),
2381 .call = parse_isolate,
2384 .name = "flex_item",
2385 .help = "flex item API",
2386 .next = NEXT(next_flex_item),
2389 [FLEX_ITEM_INIT] = {
2391 .help = "flex item init",
2392 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
2393 ARGS_ENTRY(struct buffer, port)),
2394 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
2395 NEXT_ENTRY(COMMON_PORT_ID)),
2398 [FLEX_ITEM_CREATE] = {
2400 .help = "flex item create",
2401 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
2402 ARGS_ENTRY(struct buffer, args.flex.token),
2403 ARGS_ENTRY(struct buffer, port)),
2404 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
2405 NEXT_ENTRY(COMMON_FLEX_TOKEN),
2406 NEXT_ENTRY(COMMON_PORT_ID)),
2409 [FLEX_ITEM_DESTROY] = {
2411 .help = "flex item destroy",
2412 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
2413 ARGS_ENTRY(struct buffer, port)),
2414 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
2415 NEXT_ENTRY(COMMON_PORT_ID)),
2420 .help = "new tunnel API",
2421 .next = NEXT(NEXT_ENTRY
2422 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
2423 .call = parse_tunnel,
2425 /* Tunnel arguments. */
2428 .help = "create new tunnel object",
2429 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
2430 NEXT_ENTRY(COMMON_PORT_ID)),
2431 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2432 .call = parse_tunnel,
2434 [TUNNEL_CREATE_TYPE] = {
2436 .help = "create new tunnel",
2437 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
2438 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
2439 .call = parse_tunnel,
2441 [TUNNEL_DESTROY] = {
2443 .help = "destroy tunnel",
2444 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
2445 NEXT_ENTRY(COMMON_PORT_ID)),
2446 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2447 .call = parse_tunnel,
2449 [TUNNEL_DESTROY_ID] = {
2451 .help = "tunnel identifier to destroy",
2452 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
2453 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2454 .call = parse_tunnel,
2458 .help = "list existing tunnels",
2459 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2460 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2461 .call = parse_tunnel,
2463 /* Destroy arguments. */
2466 .help = "specify a rule identifier",
2467 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2468 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
2469 .call = parse_destroy,
2471 /* Dump arguments. */
2475 .next = NEXT(next_dump_attr),
2476 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
2481 .help = "dump one rule",
2482 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2483 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
2484 ARGS_ENTRY(struct buffer, args.dump.rule)),
2487 /* Query arguments. */
2491 .help = "action to query, must be part of the rule",
2492 .call = parse_action,
2493 .comp = comp_action,
2495 /* List arguments. */
2498 .help = "specify a group",
2499 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2500 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
2505 .help = "specify aged flows need be destroyed",
2509 /* Validate/create attributes. */
2512 .help = "specify a group",
2513 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2514 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
2519 .help = "specify a priority level",
2520 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2521 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
2526 .help = "affect rule to ingress",
2527 .next = NEXT(next_vc_attr),
2532 .help = "affect rule to egress",
2533 .next = NEXT(next_vc_attr),
2538 .help = "apply rule directly to endpoints found in pattern",
2539 .next = NEXT(next_vc_attr),
2543 .name = "tunnel_set",
2544 .help = "tunnel steer rule",
2545 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2546 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2549 [VC_TUNNEL_MATCH] = {
2550 .name = "tunnel_match",
2551 .help = "tunnel match rule",
2552 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2553 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2556 /* Validate/create pattern. */
2559 .help = "submit a list of pattern items",
2560 .next = NEXT(next_item),
2565 .help = "match value perfectly (with full bit-mask)",
2566 .call = parse_vc_spec,
2568 [ITEM_PARAM_SPEC] = {
2570 .help = "match value according to configured bit-mask",
2571 .call = parse_vc_spec,
2573 [ITEM_PARAM_LAST] = {
2575 .help = "specify upper bound to establish a range",
2576 .call = parse_vc_spec,
2578 [ITEM_PARAM_MASK] = {
2580 .help = "specify bit-mask with relevant bits set to one",
2581 .call = parse_vc_spec,
2583 [ITEM_PARAM_PREFIX] = {
2585 .help = "generate bit-mask from a prefix length",
2586 .call = parse_vc_spec,
2590 .help = "specify next pattern item",
2591 .next = NEXT(next_item),
2595 .help = "end list of pattern items",
2596 .priv = PRIV_ITEM(END, 0),
2597 .next = NEXT(NEXT_ENTRY(ACTIONS)),
2602 .help = "no-op pattern item",
2603 .priv = PRIV_ITEM(VOID, 0),
2604 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2609 .help = "perform actions when pattern does not match",
2610 .priv = PRIV_ITEM(INVERT, 0),
2611 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2616 .help = "match any protocol for the current layer",
2617 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
2618 .next = NEXT(item_any),
2623 .help = "number of layers covered",
2624 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2625 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
2629 .help = "match traffic from/to the physical function",
2630 .priv = PRIV_ITEM(PF, 0),
2631 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2636 .help = "match traffic from/to a virtual function ID",
2637 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
2638 .next = NEXT(item_vf),
2644 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2645 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
2649 .help = "match traffic from/to a specific physical port",
2650 .priv = PRIV_ITEM(PHY_PORT,
2651 sizeof(struct rte_flow_item_phy_port)),
2652 .next = NEXT(item_phy_port),
2655 [ITEM_PHY_PORT_INDEX] = {
2657 .help = "physical port index",
2658 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
2660 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
2664 .help = "match traffic from/to a given DPDK port ID",
2665 .priv = PRIV_ITEM(PORT_ID,
2666 sizeof(struct rte_flow_item_port_id)),
2667 .next = NEXT(item_port_id),
2670 [ITEM_PORT_ID_ID] = {
2672 .help = "DPDK port ID",
2673 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
2675 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
2679 .help = "match traffic against value set in previously matched rule",
2680 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
2681 .next = NEXT(item_mark),
2686 .help = "Integer value to match against",
2687 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
2689 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
2693 .help = "match an arbitrary byte string",
2694 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
2695 .next = NEXT(item_raw),
2698 [ITEM_RAW_RELATIVE] = {
2700 .help = "look for pattern after the previous item",
2701 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2702 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2705 [ITEM_RAW_SEARCH] = {
2707 .help = "search pattern from offset (see also limit)",
2708 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2709 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2712 [ITEM_RAW_OFFSET] = {
2714 .help = "absolute or relative offset for pattern",
2715 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
2716 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
2718 [ITEM_RAW_LIMIT] = {
2720 .help = "search area limit for start of pattern",
2721 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2722 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
2724 [ITEM_RAW_PATTERN] = {
2726 .help = "byte string to look for",
2727 .next = NEXT(item_raw,
2728 NEXT_ENTRY(COMMON_STRING),
2729 NEXT_ENTRY(ITEM_PARAM_IS,
2732 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2733 ARGS_ENTRY(struct rte_flow_item_raw, length),
2734 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2735 ITEM_RAW_PATTERN_SIZE)),
2737 [ITEM_RAW_PATTERN_HEX] = {
2738 .name = "pattern_hex",
2739 .help = "hex string to look for",
2740 .next = NEXT(item_raw,
2741 NEXT_ENTRY(COMMON_HEX),
2742 NEXT_ENTRY(ITEM_PARAM_IS,
2745 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2746 ARGS_ENTRY(struct rte_flow_item_raw, length),
2747 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2748 ITEM_RAW_PATTERN_SIZE)),
2752 .help = "match Ethernet header",
2753 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
2754 .next = NEXT(item_eth),
2759 .help = "destination MAC",
2760 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2761 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
2765 .help = "source MAC",
2766 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2767 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
2771 .help = "EtherType",
2772 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2773 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
2775 [ITEM_ETH_HAS_VLAN] = {
2777 .help = "packet header contains VLAN",
2778 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2779 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
2784 .help = "match 802.1Q/ad VLAN tag",
2785 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
2786 .next = NEXT(item_vlan),
2791 .help = "tag control information",
2792 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2794 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
2798 .help = "priority code point",
2799 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2801 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2806 .help = "drop eligible indicator",
2807 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2809 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2814 .help = "VLAN identifier",
2815 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2817 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2820 [ITEM_VLAN_INNER_TYPE] = {
2821 .name = "inner_type",
2822 .help = "inner EtherType",
2823 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2825 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2828 [ITEM_VLAN_HAS_MORE_VLAN] = {
2829 .name = "has_more_vlan",
2830 .help = "packet header contains another VLAN",
2831 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2833 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
2838 .help = "match IPv4 header",
2839 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
2840 .next = NEXT(item_ipv4),
2843 [ITEM_IPV4_VER_IHL] = {
2844 .name = "version_ihl",
2845 .help = "match header length",
2846 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2848 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
2853 .help = "type of service",
2854 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2856 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2857 hdr.type_of_service)),
2860 .name = "packet_id",
2861 .help = "fragment packet id",
2862 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2864 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2867 [ITEM_IPV4_FRAGMENT_OFFSET] = {
2868 .name = "fragment_offset",
2869 .help = "fragmentation flags and fragment offset",
2870 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2872 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2873 hdr.fragment_offset)),
2877 .help = "time to live",
2878 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2880 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2883 [ITEM_IPV4_PROTO] = {
2885 .help = "next protocol ID",
2886 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2888 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2889 hdr.next_proto_id)),
2893 .help = "source address",
2894 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2896 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2901 .help = "destination address",
2902 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2904 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2909 .help = "match IPv6 header",
2910 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
2911 .next = NEXT(item_ipv6),
2916 .help = "traffic class",
2917 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2919 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2921 "\x0f\xf0\x00\x00")),
2923 [ITEM_IPV6_FLOW] = {
2925 .help = "flow label",
2926 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2928 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2930 "\x00\x0f\xff\xff")),
2932 [ITEM_IPV6_PROTO] = {
2934 .help = "protocol (next header)",
2935 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2937 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2942 .help = "hop limit",
2943 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2945 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2950 .help = "source address",
2951 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2953 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2958 .help = "destination address",
2959 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2961 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2964 [ITEM_IPV6_HAS_FRAG_EXT] = {
2965 .name = "has_frag_ext",
2966 .help = "fragment packet attribute",
2967 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2969 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
2974 .help = "match ICMP header",
2975 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
2976 .next = NEXT(item_icmp),
2979 [ITEM_ICMP_TYPE] = {
2981 .help = "ICMP packet type",
2982 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2984 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2987 [ITEM_ICMP_CODE] = {
2989 .help = "ICMP packet code",
2990 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2992 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2995 [ITEM_ICMP_IDENT] = {
2997 .help = "ICMP packet identifier",
2998 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3000 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3005 .help = "ICMP packet sequence number",
3006 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3008 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3013 .help = "match UDP header",
3014 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
3015 .next = NEXT(item_udp),
3020 .help = "UDP source port",
3021 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
3023 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3028 .help = "UDP destination port",
3029 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3030 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3035 .help = "match TCP header",
3036 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
3037 .next = NEXT(item_tcp),
3042 .help = "TCP source port",
3043 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3044 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3049 .help = "TCP destination port",
3050 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3051 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3054 [ITEM_TCP_FLAGS] = {
3056 .help = "TCP flags",
3057 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3058 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3063 .help = "match SCTP header",
3064 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
3065 .next = NEXT(item_sctp),
3070 .help = "SCTP source port",
3071 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3073 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3078 .help = "SCTP destination port",
3079 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3081 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3086 .help = "validation tag",
3087 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3089 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3092 [ITEM_SCTP_CKSUM] = {
3095 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3097 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3102 .help = "match VXLAN header",
3103 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
3104 .next = NEXT(item_vxlan),
3107 [ITEM_VXLAN_VNI] = {
3109 .help = "VXLAN identifier",
3110 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3112 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
3114 [ITEM_VXLAN_LAST_RSVD] = {
3115 .name = "last_rsvd",
3116 .help = "VXLAN last reserved bits",
3117 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3119 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
3124 .help = "match E-Tag header",
3125 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
3126 .next = NEXT(item_e_tag),
3129 [ITEM_E_TAG_GRP_ECID_B] = {
3130 .name = "grp_ecid_b",
3131 .help = "GRP and E-CID base",
3132 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3134 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
3140 .help = "match NVGRE header",
3141 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
3142 .next = NEXT(item_nvgre),
3145 [ITEM_NVGRE_TNI] = {
3147 .help = "virtual subnet ID",
3148 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
3150 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
3154 .help = "match MPLS header",
3155 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
3156 .next = NEXT(item_mpls),
3159 [ITEM_MPLS_LABEL] = {
3161 .help = "MPLS label",
3162 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3164 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3170 .help = "MPLS Traffic Class",
3171 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3173 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3179 .help = "MPLS Bottom-of-Stack",
3180 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3182 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3188 .help = "match GRE header",
3189 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
3190 .next = NEXT(item_gre),
3193 [ITEM_GRE_PROTO] = {
3195 .help = "GRE protocol type",
3196 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3198 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3201 [ITEM_GRE_C_RSVD0_VER] = {
3202 .name = "c_rsvd0_ver",
3204 "checksum (1b), undefined (1b), key bit (1b),"
3205 " sequence number (1b), reserved 0 (9b),"
3207 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3209 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3212 [ITEM_GRE_C_BIT] = {
3214 .help = "checksum bit (C)",
3215 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
3217 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3219 "\x80\x00\x00\x00")),
3221 [ITEM_GRE_S_BIT] = {
3223 .help = "sequence number bit (S)",
3224 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3225 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3227 "\x10\x00\x00\x00")),
3229 [ITEM_GRE_K_BIT] = {
3231 .help = "key bit (K)",
3232 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3233 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3235 "\x20\x00\x00\x00")),
3239 .help = "fuzzy pattern match, expect faster than default",
3240 .priv = PRIV_ITEM(FUZZY,
3241 sizeof(struct rte_flow_item_fuzzy)),
3242 .next = NEXT(item_fuzzy),
3245 [ITEM_FUZZY_THRESH] = {
3247 .help = "match accuracy threshold",
3248 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
3250 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
3255 .help = "match GTP header",
3256 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
3257 .next = NEXT(item_gtp),
3260 [ITEM_GTP_FLAGS] = {
3261 .name = "v_pt_rsv_flags",
3262 .help = "GTP flags",
3263 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3264 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3267 [ITEM_GTP_MSG_TYPE] = {
3269 .help = "GTP message type",
3270 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3271 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3275 .help = "tunnel endpoint identifier",
3276 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3277 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3281 .help = "match GTP header",
3282 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3283 .next = NEXT(item_gtp),
3288 .help = "match GTP header",
3289 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3290 .next = NEXT(item_gtp),
3295 .help = "match GENEVE header",
3296 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3297 .next = NEXT(item_geneve),
3300 [ITEM_GENEVE_VNI] = {
3302 .help = "virtual network identifier",
3303 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3305 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3307 [ITEM_GENEVE_PROTO] = {
3309 .help = "GENEVE protocol type",
3310 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3312 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3315 [ITEM_GENEVE_OPTLEN] = {
3317 .help = "GENEVE options length in dwords",
3318 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3320 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3321 ver_opt_len_o_c_rsvd0,
3324 [ITEM_VXLAN_GPE] = {
3325 .name = "vxlan-gpe",
3326 .help = "match VXLAN-GPE header",
3327 .priv = PRIV_ITEM(VXLAN_GPE,
3328 sizeof(struct rte_flow_item_vxlan_gpe)),
3329 .next = NEXT(item_vxlan_gpe),
3332 [ITEM_VXLAN_GPE_VNI] = {
3334 .help = "VXLAN-GPE identifier",
3335 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3337 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
3340 [ITEM_ARP_ETH_IPV4] = {
3341 .name = "arp_eth_ipv4",
3342 .help = "match ARP header for Ethernet/IPv4",
3343 .priv = PRIV_ITEM(ARP_ETH_IPV4,
3344 sizeof(struct rte_flow_item_arp_eth_ipv4)),
3345 .next = NEXT(item_arp_eth_ipv4),
3348 [ITEM_ARP_ETH_IPV4_SHA] = {
3350 .help = "sender hardware address",
3351 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3353 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3356 [ITEM_ARP_ETH_IPV4_SPA] = {
3358 .help = "sender IPv4 address",
3359 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3361 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3364 [ITEM_ARP_ETH_IPV4_THA] = {
3366 .help = "target hardware address",
3367 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3369 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3372 [ITEM_ARP_ETH_IPV4_TPA] = {
3374 .help = "target IPv4 address",
3375 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3377 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3382 .help = "match presence of any IPv6 extension header",
3383 .priv = PRIV_ITEM(IPV6_EXT,
3384 sizeof(struct rte_flow_item_ipv6_ext)),
3385 .next = NEXT(item_ipv6_ext),
3388 [ITEM_IPV6_EXT_NEXT_HDR] = {
3390 .help = "next header",
3391 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3393 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
3396 [ITEM_IPV6_FRAG_EXT] = {
3397 .name = "ipv6_frag_ext",
3398 .help = "match presence of IPv6 fragment extension header",
3399 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
3400 sizeof(struct rte_flow_item_ipv6_frag_ext)),
3401 .next = NEXT(item_ipv6_frag_ext),
3404 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
3406 .help = "next header",
3407 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3409 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
3412 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
3413 .name = "frag_data",
3414 .help = "fragment flags and offset",
3415 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3417 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3420 [ITEM_IPV6_FRAG_EXT_ID] = {
3421 .name = "packet_id",
3422 .help = "fragment packet id",
3423 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3425 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3430 .help = "match any ICMPv6 header",
3431 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
3432 .next = NEXT(item_icmp6),
3435 [ITEM_ICMP6_TYPE] = {
3437 .help = "ICMPv6 type",
3438 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3440 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3443 [ITEM_ICMP6_CODE] = {
3445 .help = "ICMPv6 code",
3446 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3448 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3451 [ITEM_ICMP6_ND_NS] = {
3452 .name = "icmp6_nd_ns",
3453 .help = "match ICMPv6 neighbor discovery solicitation",
3454 .priv = PRIV_ITEM(ICMP6_ND_NS,
3455 sizeof(struct rte_flow_item_icmp6_nd_ns)),
3456 .next = NEXT(item_icmp6_nd_ns),
3459 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
3460 .name = "target_addr",
3461 .help = "target address",
3462 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
3464 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
3467 [ITEM_ICMP6_ND_NA] = {
3468 .name = "icmp6_nd_na",
3469 .help = "match ICMPv6 neighbor discovery advertisement",
3470 .priv = PRIV_ITEM(ICMP6_ND_NA,
3471 sizeof(struct rte_flow_item_icmp6_nd_na)),
3472 .next = NEXT(item_icmp6_nd_na),
3475 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
3476 .name = "target_addr",
3477 .help = "target address",
3478 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
3480 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
3483 [ITEM_ICMP6_ND_OPT] = {
3484 .name = "icmp6_nd_opt",
3485 .help = "match presence of any ICMPv6 neighbor discovery"
3487 .priv = PRIV_ITEM(ICMP6_ND_OPT,
3488 sizeof(struct rte_flow_item_icmp6_nd_opt)),
3489 .next = NEXT(item_icmp6_nd_opt),
3492 [ITEM_ICMP6_ND_OPT_TYPE] = {
3494 .help = "ND option type",
3495 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3497 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
3500 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
3501 .name = "icmp6_nd_opt_sla_eth",
3502 .help = "match ICMPv6 neighbor discovery source Ethernet"
3503 " link-layer address option",
3505 (ICMP6_ND_OPT_SLA_ETH,
3506 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
3507 .next = NEXT(item_icmp6_nd_opt_sla_eth),
3510 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
3512 .help = "source Ethernet LLA",
3513 .next = NEXT(item_icmp6_nd_opt_sla_eth,
3514 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3515 .args = ARGS(ARGS_ENTRY_HTON
3516 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
3518 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
3519 .name = "icmp6_nd_opt_tla_eth",
3520 .help = "match ICMPv6 neighbor discovery target Ethernet"
3521 " link-layer address option",
3523 (ICMP6_ND_OPT_TLA_ETH,
3524 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
3525 .next = NEXT(item_icmp6_nd_opt_tla_eth),
3528 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
3530 .help = "target Ethernet LLA",
3531 .next = NEXT(item_icmp6_nd_opt_tla_eth,
3532 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3533 .args = ARGS(ARGS_ENTRY_HTON
3534 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
3538 .help = "match metadata header",
3539 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
3540 .next = NEXT(item_meta),
3543 [ITEM_META_DATA] = {
3545 .help = "metadata value",
3546 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
3548 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
3549 data, "\xff\xff\xff\xff")),
3553 .help = "match GRE key",
3554 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
3555 .next = NEXT(item_gre_key),
3558 [ITEM_GRE_KEY_VALUE] = {
3560 .help = "key value",
3561 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
3563 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3567 .help = "match GTP extension header with type 0x85",
3568 .priv = PRIV_ITEM(GTP_PSC,
3569 sizeof(struct rte_flow_item_gtp_psc)),
3570 .next = NEXT(item_gtp_psc),
3573 [ITEM_GTP_PSC_QFI] = {
3575 .help = "QoS flow identifier",
3576 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3578 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3581 [ITEM_GTP_PSC_PDU_T] = {
3584 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3586 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3591 .help = "match PPPoE session header",
3592 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
3593 .next = NEXT(item_pppoes),
3598 .help = "match PPPoE discovery header",
3599 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
3600 .next = NEXT(item_pppoed),
3603 [ITEM_PPPOE_SEID] = {
3605 .help = "session identifier",
3606 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
3608 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
3611 [ITEM_PPPOE_PROTO_ID] = {
3612 .name = "pppoe_proto_id",
3613 .help = "match PPPoE session protocol identifier",
3614 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
3615 sizeof(struct rte_flow_item_pppoe_proto_id)),
3616 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
3618 .args = ARGS(ARGS_ENTRY_HTON
3619 (struct rte_flow_item_pppoe_proto_id, proto_id)),
3624 .help = "matches higig2 header",
3625 .priv = PRIV_ITEM(HIGIG2,
3626 sizeof(struct rte_flow_item_higig2_hdr)),
3627 .next = NEXT(item_higig2),
3630 [ITEM_HIGIG2_CLASSIFICATION] = {
3631 .name = "classification",
3632 .help = "matches classification of higig2 header",
3633 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3635 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3636 hdr.ppt1.classification)),
3638 [ITEM_HIGIG2_VID] = {
3640 .help = "matches vid of higig2 header",
3641 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3643 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3648 .help = "match tag value",
3649 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
3650 .next = NEXT(item_tag),
3655 .help = "tag value to match",
3656 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3657 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
3659 [ITEM_TAG_INDEX] = {
3661 .help = "index of tag array to match",
3662 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3663 NEXT_ENTRY(ITEM_PARAM_IS)),
3664 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
3666 [ITEM_L2TPV3OIP] = {
3667 .name = "l2tpv3oip",
3668 .help = "match L2TPv3 over IP header",
3669 .priv = PRIV_ITEM(L2TPV3OIP,
3670 sizeof(struct rte_flow_item_l2tpv3oip)),
3671 .next = NEXT(item_l2tpv3oip),
3674 [ITEM_L2TPV3OIP_SESSION_ID] = {
3675 .name = "session_id",
3676 .help = "session identifier",
3677 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
3679 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
3684 .help = "match ESP header",
3685 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
3686 .next = NEXT(item_esp),
3691 .help = "security policy index",
3692 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3693 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
3698 .help = "match AH header",
3699 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
3700 .next = NEXT(item_ah),
3705 .help = "security parameters index",
3706 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3707 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
3711 .help = "match pfcp header",
3712 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
3713 .next = NEXT(item_pfcp),
3716 [ITEM_PFCP_S_FIELD] = {
3719 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3721 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
3724 [ITEM_PFCP_SEID] = {
3726 .help = "session endpoint identifier",
3727 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3729 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
3733 .help = "match eCPRI header",
3734 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
3735 .next = NEXT(item_ecpri),
3738 [ITEM_ECPRI_COMMON] = {
3740 .help = "eCPRI common header",
3741 .next = NEXT(item_ecpri_common),
3743 [ITEM_ECPRI_COMMON_TYPE] = {
3745 .help = "type of common header",
3746 .next = NEXT(item_ecpri_common_type),
3747 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
3749 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
3751 .help = "Type #0: IQ Data",
3752 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3754 .call = parse_vc_item_ecpri_type,
3756 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
3758 .help = "Physical Channel ID",
3759 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3760 ITEM_ECPRI_COMMON, ITEM_NEXT),
3761 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3762 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3765 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
3767 .help = "Type #2: Real-Time Control Data",
3768 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3770 .call = parse_vc_item_ecpri_type,
3772 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
3774 .help = "Real-Time Control Data ID",
3775 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3776 ITEM_ECPRI_COMMON, ITEM_NEXT),
3777 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3778 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3781 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
3782 .name = "delay_measure",
3783 .help = "Type #5: One-Way Delay Measurement",
3784 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3786 .call = parse_vc_item_ecpri_type,
3788 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
3790 .help = "Measurement ID",
3791 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3792 ITEM_ECPRI_COMMON, ITEM_NEXT),
3793 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3794 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3797 [ITEM_GENEVE_OPT] = {
3798 .name = "geneve-opt",
3799 .help = "GENEVE header option",
3800 .priv = PRIV_ITEM(GENEVE_OPT,
3801 sizeof(struct rte_flow_item_geneve_opt) +
3802 ITEM_GENEVE_OPT_DATA_SIZE),
3803 .next = NEXT(item_geneve_opt),
3806 [ITEM_GENEVE_OPT_CLASS] = {
3808 .help = "GENEVE option class",
3809 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3811 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
3814 [ITEM_GENEVE_OPT_TYPE] = {
3816 .help = "GENEVE option type",
3817 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3819 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
3822 [ITEM_GENEVE_OPT_LENGTH] = {
3824 .help = "GENEVE option data length (in 32b words)",
3825 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3827 .args = ARGS(ARGS_ENTRY_BOUNDED(
3828 struct rte_flow_item_geneve_opt, option_len,
3831 [ITEM_GENEVE_OPT_DATA] = {
3833 .help = "GENEVE option data pattern",
3834 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
3836 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
3837 ARGS_ENTRY_ARB(0, 0),
3839 (sizeof(struct rte_flow_item_geneve_opt),
3840 ITEM_GENEVE_OPT_DATA_SIZE)),
3842 [ITEM_INTEGRITY] = {
3843 .name = "integrity",
3844 .help = "match packet integrity",
3845 .priv = PRIV_ITEM(INTEGRITY,
3846 sizeof(struct rte_flow_item_integrity)),
3847 .next = NEXT(item_integrity),
3850 [ITEM_INTEGRITY_LEVEL] = {
3852 .help = "integrity level",
3853 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3855 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
3857 [ITEM_INTEGRITY_VALUE] = {
3859 .help = "integrity value",
3860 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3862 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
3864 [ITEM_CONNTRACK] = {
3865 .name = "conntrack",
3866 .help = "conntrack state",
3867 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
3869 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
3871 [ITEM_PORT_REPRESENTOR] = {
3872 .name = "port_representor",
3873 .help = "match traffic entering the embedded switch from the given ethdev",
3874 .priv = PRIV_ITEM(PORT_REPRESENTOR,
3875 sizeof(struct rte_flow_item_ethdev)),
3876 .next = NEXT(item_port_representor),
3879 [ITEM_PORT_REPRESENTOR_PORT_ID] = {
3881 .help = "ethdev port ID",
3882 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
3884 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
3886 [ITEM_REPRESENTED_PORT] = {
3887 .name = "represented_port",
3888 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
3889 .priv = PRIV_ITEM(REPRESENTED_PORT,
3890 sizeof(struct rte_flow_item_ethdev)),
3891 .next = NEXT(item_represented_port),
3894 [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
3895 .name = "ethdev_port_id",
3896 .help = "ethdev port ID",
3897 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
3899 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
3903 .help = "match flex header",
3904 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
3905 .next = NEXT(item_flex),
3908 [ITEM_FLEX_ITEM_HANDLE] = {
3910 .help = "flex item handle",
3911 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
3912 NEXT_ENTRY(ITEM_PARAM_IS)),
3913 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
3915 [ITEM_FLEX_PATTERN_HANDLE] = {
3917 .help = "flex pattern handle",
3918 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
3919 NEXT_ENTRY(ITEM_PARAM_IS)),
3920 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
3924 .help = "match L2TPv2 header",
3925 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
3926 .next = NEXT(item_l2tpv2),
3929 [ITEM_L2TPV2_TYPE] = {
3931 .help = "type of l2tpv2",
3932 .next = NEXT(item_l2tpv2_type),
3933 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
3935 [ITEM_L2TPV2_TYPE_DATA] = {
3937 .help = "Type #7: data message without any options",
3938 .next = NEXT(item_l2tpv2_type_data),
3939 .call = parse_vc_item_l2tpv2_type,
3941 [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
3942 .name = "tunnel_id",
3943 .help = "tunnel identifier",
3944 .next = NEXT(item_l2tpv2_type_data,
3945 NEXT_ENTRY(COMMON_UNSIGNED),
3947 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
3948 hdr.type7.tunnel_id)),
3950 [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
3951 .name = "session_id",
3952 .help = "session identifier",
3953 .next = NEXT(item_l2tpv2_type_data,
3954 NEXT_ENTRY(COMMON_UNSIGNED),
3956 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
3957 hdr.type7.session_id)),
3959 [ITEM_L2TPV2_TYPE_DATA_L] = {
3961 .help = "Type #6: data message with length option",
3962 .next = NEXT(item_l2tpv2_type_data_l),
3963 .call = parse_vc_item_l2tpv2_type,
3965 [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
3967 .help = "message length",
3968 .next = NEXT(item_l2tpv2_type_data_l,
3969 NEXT_ENTRY(COMMON_UNSIGNED),
3971 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
3974 [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
3975 .name = "tunnel_id",
3976 .help = "tunnel identifier",
3977 .next = NEXT(item_l2tpv2_type_data_l,
3978 NEXT_ENTRY(COMMON_UNSIGNED),
3980 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
3981 hdr.type6.tunnel_id)),
3983 [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
3984 .name = "session_id",
3985 .help = "session identifier",
3986 .next = NEXT(item_l2tpv2_type_data_l,
3987 NEXT_ENTRY(COMMON_UNSIGNED),
3989 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
3990 hdr.type6.session_id)),
3992 [ITEM_L2TPV2_TYPE_DATA_S] = {
3994 .help = "Type #5: data message with ns, nr option",
3995 .next = NEXT(item_l2tpv2_type_data_s),
3996 .call = parse_vc_item_l2tpv2_type,
3998 [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
3999 .name = "tunnel_id",
4000 .help = "tunnel identifier",
4001 .next = NEXT(item_l2tpv2_type_data_s,
4002 NEXT_ENTRY(COMMON_UNSIGNED),
4004 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4005 hdr.type5.tunnel_id)),
4007 [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
4008 .name = "session_id",
4009 .help = "session identifier",
4010 .next = NEXT(item_l2tpv2_type_data_s,
4011 NEXT_ENTRY(COMMON_UNSIGNED),
4013 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4014 hdr.type5.session_id)),
4016 [ITEM_L2TPV2_MSG_DATA_S_NS] = {
4018 .help = "sequence number for message",
4019 .next = NEXT(item_l2tpv2_type_data_s,
4020 NEXT_ENTRY(COMMON_UNSIGNED),
4022 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4025 [ITEM_L2TPV2_MSG_DATA_S_NR] = {
4027 .help = "sequence number for next receive message",
4028 .next = NEXT(item_l2tpv2_type_data_s,
4029 NEXT_ENTRY(COMMON_UNSIGNED),
4031 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4034 [ITEM_L2TPV2_TYPE_DATA_O] = {
4036 .help = "Type #4: data message with offset option",
4037 .next = NEXT(item_l2tpv2_type_data_o),
4038 .call = parse_vc_item_l2tpv2_type,
4040 [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
4041 .name = "tunnel_id",
4042 .help = "tunnel identifier",
4043 .next = NEXT(item_l2tpv2_type_data_o,
4044 NEXT_ENTRY(COMMON_UNSIGNED),
4046 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4047 hdr.type4.tunnel_id)),
4049 [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
4050 .name = "session_id",
4051 .help = "session identifier",
4052 .next = NEXT(item_l2tpv2_type_data_o,
4053 NEXT_ENTRY(COMMON_UNSIGNED),
4055 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4056 hdr.type5.session_id)),
4058 [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
4059 .name = "offset_size",
4060 .help = "the size of offset padding",
4061 .next = NEXT(item_l2tpv2_type_data_o,
4062 NEXT_ENTRY(COMMON_UNSIGNED),
4064 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4065 hdr.type4.offset_size)),
4067 [ITEM_L2TPV2_TYPE_DATA_L_S] = {
4069 .help = "Type #3: data message contains length, ns, nr "
4071 .next = NEXT(item_l2tpv2_type_data_l_s),
4072 .call = parse_vc_item_l2tpv2_type,
4074 [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
4076 .help = "message length",
4077 .next = NEXT(item_l2tpv2_type_data_l_s,
4078 NEXT_ENTRY(COMMON_UNSIGNED),
4080 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4083 [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
4084 .name = "tunnel_id",
4085 .help = "tunnel identifier",
4086 .next = NEXT(item_l2tpv2_type_data_l_s,
4087 NEXT_ENTRY(COMMON_UNSIGNED),
4089 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4090 hdr.type3.tunnel_id)),
4092 [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
4093 .name = "session_id",
4094 .help = "session identifier",
4095 .next = NEXT(item_l2tpv2_type_data_l_s,
4096 NEXT_ENTRY(COMMON_UNSIGNED),
4098 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4099 hdr.type3.session_id)),
4101 [ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
4103 .help = "sequence number for message",
4104 .next = NEXT(item_l2tpv2_type_data_l_s,
4105 NEXT_ENTRY(COMMON_UNSIGNED),
4107 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4110 [ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
4112 .help = "sequence number for next receive message",
4113 .next = NEXT(item_l2tpv2_type_data_l_s,
4114 NEXT_ENTRY(COMMON_UNSIGNED),
4116 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4119 [ITEM_L2TPV2_TYPE_CTRL] = {
4121 .help = "Type #3: conrtol message contains length, ns, nr "
4123 .next = NEXT(item_l2tpv2_type_ctrl),
4124 .call = parse_vc_item_l2tpv2_type,
4126 [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
4128 .help = "message length",
4129 .next = NEXT(item_l2tpv2_type_ctrl,
4130 NEXT_ENTRY(COMMON_UNSIGNED),
4132 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4135 [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
4136 .name = "tunnel_id",
4137 .help = "tunnel identifier",
4138 .next = NEXT(item_l2tpv2_type_ctrl,
4139 NEXT_ENTRY(COMMON_UNSIGNED),
4141 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4142 hdr.type3.tunnel_id)),
4144 [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
4145 .name = "session_id",
4146 .help = "session identifier",
4147 .next = NEXT(item_l2tpv2_type_ctrl,
4148 NEXT_ENTRY(COMMON_UNSIGNED),
4150 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4151 hdr.type3.session_id)),
4153 [ITEM_L2TPV2_MSG_CTRL_NS] = {
4155 .help = "sequence number for message",
4156 .next = NEXT(item_l2tpv2_type_ctrl,
4157 NEXT_ENTRY(COMMON_UNSIGNED),
4159 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4162 [ITEM_L2TPV2_MSG_CTRL_NR] = {
4164 .help = "sequence number for next receive message",
4165 .next = NEXT(item_l2tpv2_type_ctrl,
4166 NEXT_ENTRY(COMMON_UNSIGNED),
4168 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4173 .help = "match PPP header",
4174 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
4175 .next = NEXT(item_ppp),
4180 .help = "PPP address",
4181 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4183 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
4187 .help = "PPP control",
4188 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4190 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
4192 [ITEM_PPP_PROTO_ID] = {
4194 .help = "PPP protocol identifier",
4195 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4197 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
4200 /* Validate/create actions. */
4203 .help = "submit a list of associated actions",
4204 .next = NEXT(next_action),
4209 .help = "specify next action",
4210 .next = NEXT(next_action),
4214 .help = "end list of actions",
4215 .priv = PRIV_ACTION(END, 0),
4220 .help = "no-op action",
4221 .priv = PRIV_ACTION(VOID, 0),
4222 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4225 [ACTION_PASSTHRU] = {
4227 .help = "let subsequent rule process matched packets",
4228 .priv = PRIV_ACTION(PASSTHRU, 0),
4229 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4234 .help = "redirect traffic to a given group",
4235 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
4236 .next = NEXT(action_jump),
4239 [ACTION_JUMP_GROUP] = {
4241 .help = "group to redirect traffic to",
4242 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
4243 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
4244 .call = parse_vc_conf,
4248 .help = "attach 32 bit value to packets",
4249 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
4250 .next = NEXT(action_mark),
4253 [ACTION_MARK_ID] = {
4255 .help = "32 bit value to return with packets",
4256 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
4257 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
4258 .call = parse_vc_conf,
4262 .help = "flag packets",
4263 .priv = PRIV_ACTION(FLAG, 0),
4264 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4269 .help = "assign packets to a given queue index",
4270 .priv = PRIV_ACTION(QUEUE,
4271 sizeof(struct rte_flow_action_queue)),
4272 .next = NEXT(action_queue),
4275 [ACTION_QUEUE_INDEX] = {
4277 .help = "queue index to use",
4278 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
4279 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
4280 .call = parse_vc_conf,
4284 .help = "drop packets (note: passthru has priority)",
4285 .priv = PRIV_ACTION(DROP, 0),
4286 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4291 .help = "enable counters for this rule",
4292 .priv = PRIV_ACTION(COUNT,
4293 sizeof(struct rte_flow_action_count)),
4294 .next = NEXT(action_count),
4297 [ACTION_COUNT_ID] = {
4298 .name = "identifier",
4299 .help = "counter identifier to use",
4300 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
4301 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
4302 .call = parse_vc_conf,
4306 .help = "spread packets among several queues",
4307 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
4308 .next = NEXT(action_rss),
4309 .call = parse_vc_action_rss,
4311 [ACTION_RSS_FUNC] = {
4313 .help = "RSS hash function to apply",
4314 .next = NEXT(action_rss,
4315 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
4316 ACTION_RSS_FUNC_TOEPLITZ,
4317 ACTION_RSS_FUNC_SIMPLE_XOR,
4318 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
4320 [ACTION_RSS_FUNC_DEFAULT] = {
4322 .help = "default hash function",
4323 .call = parse_vc_action_rss_func,
4325 [ACTION_RSS_FUNC_TOEPLITZ] = {
4327 .help = "Toeplitz hash function",
4328 .call = parse_vc_action_rss_func,
4330 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
4331 .name = "simple_xor",
4332 .help = "simple XOR hash function",
4333 .call = parse_vc_action_rss_func,
4335 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
4336 .name = "symmetric_toeplitz",
4337 .help = "Symmetric Toeplitz hash function",
4338 .call = parse_vc_action_rss_func,
4340 [ACTION_RSS_LEVEL] = {
4342 .help = "encapsulation level for \"types\"",
4343 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
4344 .args = ARGS(ARGS_ENTRY_ARB
4345 (offsetof(struct action_rss_data, conf) +
4346 offsetof(struct rte_flow_action_rss, level),
4347 sizeof(((struct rte_flow_action_rss *)0)->
4350 [ACTION_RSS_TYPES] = {
4352 .help = "specific RSS hash types",
4353 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
4355 [ACTION_RSS_TYPE] = {
4357 .help = "RSS hash type",
4358 .call = parse_vc_action_rss_type,
4359 .comp = comp_vc_action_rss_type,
4361 [ACTION_RSS_KEY] = {
4363 .help = "RSS hash key",
4364 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
4365 .args = ARGS(ARGS_ENTRY_ARB
4366 (offsetof(struct action_rss_data, conf) +
4367 offsetof(struct rte_flow_action_rss, key),
4368 sizeof(((struct rte_flow_action_rss *)0)->key)),
4370 (offsetof(struct action_rss_data, conf) +
4371 offsetof(struct rte_flow_action_rss, key_len),
4372 sizeof(((struct rte_flow_action_rss *)0)->
4374 ARGS_ENTRY(struct action_rss_data, key)),
4376 [ACTION_RSS_KEY_LEN] = {
4378 .help = "RSS hash key length in bytes",
4379 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
4380 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4381 (offsetof(struct action_rss_data, conf) +
4382 offsetof(struct rte_flow_action_rss, key_len),
4383 sizeof(((struct rte_flow_action_rss *)0)->
4386 RSS_HASH_KEY_LENGTH)),
4388 [ACTION_RSS_QUEUES] = {
4390 .help = "queue indices to use",
4391 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
4392 .call = parse_vc_conf,
4394 [ACTION_RSS_QUEUE] = {
4396 .help = "queue index",
4397 .call = parse_vc_action_rss_queue,
4398 .comp = comp_vc_action_rss_queue,
4402 .help = "direct traffic to physical function",
4403 .priv = PRIV_ACTION(PF, 0),
4404 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4409 .help = "direct traffic to a virtual function ID",
4410 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
4411 .next = NEXT(action_vf),
4414 [ACTION_VF_ORIGINAL] = {
4416 .help = "use original VF ID if possible",
4417 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
4418 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
4420 .call = parse_vc_conf,
4425 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
4426 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
4427 .call = parse_vc_conf,
4429 [ACTION_PHY_PORT] = {
4431 .help = "direct packets to physical port index",
4432 .priv = PRIV_ACTION(PHY_PORT,
4433 sizeof(struct rte_flow_action_phy_port)),
4434 .next = NEXT(action_phy_port),
4437 [ACTION_PHY_PORT_ORIGINAL] = {
4439 .help = "use original port index if possible",
4440 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
4441 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
4443 .call = parse_vc_conf,
4445 [ACTION_PHY_PORT_INDEX] = {
4447 .help = "physical port index",
4448 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
4449 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
4451 .call = parse_vc_conf,
4453 [ACTION_PORT_ID] = {
4455 .help = "direct matching traffic to a given DPDK port ID",
4456 .priv = PRIV_ACTION(PORT_ID,
4457 sizeof(struct rte_flow_action_port_id)),
4458 .next = NEXT(action_port_id),
4461 [ACTION_PORT_ID_ORIGINAL] = {
4463 .help = "use original DPDK port ID if possible",
4464 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
4465 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
4467 .call = parse_vc_conf,
4469 [ACTION_PORT_ID_ID] = {
4471 .help = "DPDK port ID",
4472 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
4473 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
4474 .call = parse_vc_conf,
4478 .help = "meter the directed packets at given id",
4479 .priv = PRIV_ACTION(METER,
4480 sizeof(struct rte_flow_action_meter)),
4481 .next = NEXT(action_meter),
4484 [ACTION_METER_COLOR] = {
4486 .help = "meter color for the packets",
4487 .priv = PRIV_ACTION(METER_COLOR,
4488 sizeof(struct rte_flow_action_meter_color)),
4489 .next = NEXT(action_meter_color),
4492 [ACTION_METER_COLOR_TYPE] = {
4494 .help = "specific meter color",
4495 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
4496 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
4497 ACTION_METER_COLOR_YELLOW,
4498 ACTION_METER_COLOR_RED)),
4500 [ACTION_METER_COLOR_GREEN] = {
4502 .help = "meter color green",
4503 .call = parse_vc_action_meter_color_type,
4505 [ACTION_METER_COLOR_YELLOW] = {
4507 .help = "meter color yellow",
4508 .call = parse_vc_action_meter_color_type,
4510 [ACTION_METER_COLOR_RED] = {
4512 .help = "meter color red",
4513 .call = parse_vc_action_meter_color_type,
4515 [ACTION_METER_ID] = {
4517 .help = "meter id to use",
4518 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
4519 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
4520 .call = parse_vc_conf,
4522 [ACTION_OF_SET_MPLS_TTL] = {
4523 .name = "of_set_mpls_ttl",
4524 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
4527 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
4528 .next = NEXT(action_of_set_mpls_ttl),
4531 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
4534 .next = NEXT(action_of_set_mpls_ttl,
4535 NEXT_ENTRY(COMMON_UNSIGNED)),
4536 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
4538 .call = parse_vc_conf,
4540 [ACTION_OF_DEC_MPLS_TTL] = {
4541 .name = "of_dec_mpls_ttl",
4542 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
4543 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
4544 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4547 [ACTION_OF_SET_NW_TTL] = {
4548 .name = "of_set_nw_ttl",
4549 .help = "OpenFlow's OFPAT_SET_NW_TTL",
4552 sizeof(struct rte_flow_action_of_set_nw_ttl)),
4553 .next = NEXT(action_of_set_nw_ttl),
4556 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
4559 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4560 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
4562 .call = parse_vc_conf,
4564 [ACTION_OF_DEC_NW_TTL] = {
4565 .name = "of_dec_nw_ttl",
4566 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
4567 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
4568 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4571 [ACTION_OF_COPY_TTL_OUT] = {
4572 .name = "of_copy_ttl_out",
4573 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
4574 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
4575 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4578 [ACTION_OF_COPY_TTL_IN] = {
4579 .name = "of_copy_ttl_in",
4580 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
4581 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
4582 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4585 [ACTION_OF_POP_VLAN] = {
4586 .name = "of_pop_vlan",
4587 .help = "OpenFlow's OFPAT_POP_VLAN",
4588 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
4589 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4592 [ACTION_OF_PUSH_VLAN] = {
4593 .name = "of_push_vlan",
4594 .help = "OpenFlow's OFPAT_PUSH_VLAN",
4597 sizeof(struct rte_flow_action_of_push_vlan)),
4598 .next = NEXT(action_of_push_vlan),
4601 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
4602 .name = "ethertype",
4603 .help = "EtherType",
4604 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
4605 .args = ARGS(ARGS_ENTRY_HTON
4606 (struct rte_flow_action_of_push_vlan,
4608 .call = parse_vc_conf,
4610 [ACTION_OF_SET_VLAN_VID] = {
4611 .name = "of_set_vlan_vid",
4612 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
4615 sizeof(struct rte_flow_action_of_set_vlan_vid)),
4616 .next = NEXT(action_of_set_vlan_vid),
4619 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
4622 .next = NEXT(action_of_set_vlan_vid,
4623 NEXT_ENTRY(COMMON_UNSIGNED)),
4624 .args = ARGS(ARGS_ENTRY_HTON
4625 (struct rte_flow_action_of_set_vlan_vid,
4627 .call = parse_vc_conf,
4629 [ACTION_OF_SET_VLAN_PCP] = {
4630 .name = "of_set_vlan_pcp",
4631 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
4634 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
4635 .next = NEXT(action_of_set_vlan_pcp),
4638 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
4640 .help = "VLAN priority",
4641 .next = NEXT(action_of_set_vlan_pcp,
4642 NEXT_ENTRY(COMMON_UNSIGNED)),
4643 .args = ARGS(ARGS_ENTRY_HTON
4644 (struct rte_flow_action_of_set_vlan_pcp,
4646 .call = parse_vc_conf,
4648 [ACTION_OF_POP_MPLS] = {
4649 .name = "of_pop_mpls",
4650 .help = "OpenFlow's OFPAT_POP_MPLS",
4651 .priv = PRIV_ACTION(OF_POP_MPLS,
4652 sizeof(struct rte_flow_action_of_pop_mpls)),
4653 .next = NEXT(action_of_pop_mpls),
4656 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
4657 .name = "ethertype",
4658 .help = "EtherType",
4659 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4660 .args = ARGS(ARGS_ENTRY_HTON
4661 (struct rte_flow_action_of_pop_mpls,
4663 .call = parse_vc_conf,
4665 [ACTION_OF_PUSH_MPLS] = {
4666 .name = "of_push_mpls",
4667 .help = "OpenFlow's OFPAT_PUSH_MPLS",
4670 sizeof(struct rte_flow_action_of_push_mpls)),
4671 .next = NEXT(action_of_push_mpls),
4674 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
4675 .name = "ethertype",
4676 .help = "EtherType",
4677 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4678 .args = ARGS(ARGS_ENTRY_HTON
4679 (struct rte_flow_action_of_push_mpls,
4681 .call = parse_vc_conf,
4683 [ACTION_VXLAN_ENCAP] = {
4684 .name = "vxlan_encap",
4685 .help = "VXLAN encapsulation, uses configuration set by \"set"
4687 .priv = PRIV_ACTION(VXLAN_ENCAP,
4688 sizeof(struct action_vxlan_encap_data)),
4689 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4690 .call = parse_vc_action_vxlan_encap,
4692 [ACTION_VXLAN_DECAP] = {
4693 .name = "vxlan_decap",
4694 .help = "Performs a decapsulation action by stripping all"
4695 " headers of the VXLAN tunnel network overlay from the"
4697 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
4698 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4701 [ACTION_NVGRE_ENCAP] = {
4702 .name = "nvgre_encap",
4703 .help = "NVGRE encapsulation, uses configuration set by \"set"
4705 .priv = PRIV_ACTION(NVGRE_ENCAP,
4706 sizeof(struct action_nvgre_encap_data)),
4707 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4708 .call = parse_vc_action_nvgre_encap,
4710 [ACTION_NVGRE_DECAP] = {
4711 .name = "nvgre_decap",
4712 .help = "Performs a decapsulation action by stripping all"
4713 " headers of the NVGRE tunnel network overlay from the"
4715 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
4716 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4719 [ACTION_L2_ENCAP] = {
4721 .help = "l2 encap, uses configuration set by"
4722 " \"set l2_encap\"",
4723 .priv = PRIV_ACTION(RAW_ENCAP,
4724 sizeof(struct action_raw_encap_data)),
4725 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4726 .call = parse_vc_action_l2_encap,
4728 [ACTION_L2_DECAP] = {
4730 .help = "l2 decap, uses configuration set by"
4731 " \"set l2_decap\"",
4732 .priv = PRIV_ACTION(RAW_DECAP,
4733 sizeof(struct action_raw_decap_data)),
4734 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4735 .call = parse_vc_action_l2_decap,
4737 [ACTION_MPLSOGRE_ENCAP] = {
4738 .name = "mplsogre_encap",
4739 .help = "mplsogre encapsulation, uses configuration set by"
4740 " \"set mplsogre_encap\"",
4741 .priv = PRIV_ACTION(RAW_ENCAP,
4742 sizeof(struct action_raw_encap_data)),
4743 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4744 .call = parse_vc_action_mplsogre_encap,
4746 [ACTION_MPLSOGRE_DECAP] = {
4747 .name = "mplsogre_decap",
4748 .help = "mplsogre decapsulation, uses configuration set by"
4749 " \"set mplsogre_decap\"",
4750 .priv = PRIV_ACTION(RAW_DECAP,
4751 sizeof(struct action_raw_decap_data)),
4752 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4753 .call = parse_vc_action_mplsogre_decap,
4755 [ACTION_MPLSOUDP_ENCAP] = {
4756 .name = "mplsoudp_encap",
4757 .help = "mplsoudp encapsulation, uses configuration set by"
4758 " \"set mplsoudp_encap\"",
4759 .priv = PRIV_ACTION(RAW_ENCAP,
4760 sizeof(struct action_raw_encap_data)),
4761 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4762 .call = parse_vc_action_mplsoudp_encap,
4764 [ACTION_MPLSOUDP_DECAP] = {
4765 .name = "mplsoudp_decap",
4766 .help = "mplsoudp decapsulation, uses configuration set by"
4767 " \"set mplsoudp_decap\"",
4768 .priv = PRIV_ACTION(RAW_DECAP,
4769 sizeof(struct action_raw_decap_data)),
4770 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4771 .call = parse_vc_action_mplsoudp_decap,
4773 [ACTION_SET_IPV4_SRC] = {
4774 .name = "set_ipv4_src",
4775 .help = "Set a new IPv4 source address in the outermost"
4777 .priv = PRIV_ACTION(SET_IPV4_SRC,
4778 sizeof(struct rte_flow_action_set_ipv4)),
4779 .next = NEXT(action_set_ipv4_src),
4782 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
4783 .name = "ipv4_addr",
4784 .help = "new IPv4 source address to set",
4785 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4786 .args = ARGS(ARGS_ENTRY_HTON
4787 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4788 .call = parse_vc_conf,
4790 [ACTION_SET_IPV4_DST] = {
4791 .name = "set_ipv4_dst",
4792 .help = "Set a new IPv4 destination address in the outermost"
4794 .priv = PRIV_ACTION(SET_IPV4_DST,
4795 sizeof(struct rte_flow_action_set_ipv4)),
4796 .next = NEXT(action_set_ipv4_dst),
4799 [ACTION_SET_IPV4_DST_IPV4_DST] = {
4800 .name = "ipv4_addr",
4801 .help = "new IPv4 destination address to set",
4802 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4803 .args = ARGS(ARGS_ENTRY_HTON
4804 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4805 .call = parse_vc_conf,
4807 [ACTION_SET_IPV6_SRC] = {
4808 .name = "set_ipv6_src",
4809 .help = "Set a new IPv6 source address in the outermost"
4811 .priv = PRIV_ACTION(SET_IPV6_SRC,
4812 sizeof(struct rte_flow_action_set_ipv6)),
4813 .next = NEXT(action_set_ipv6_src),
4816 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
4817 .name = "ipv6_addr",
4818 .help = "new IPv6 source address to set",
4819 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4820 .args = ARGS(ARGS_ENTRY_HTON
4821 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4822 .call = parse_vc_conf,
4824 [ACTION_SET_IPV6_DST] = {
4825 .name = "set_ipv6_dst",
4826 .help = "Set a new IPv6 destination address in the outermost"
4828 .priv = PRIV_ACTION(SET_IPV6_DST,
4829 sizeof(struct rte_flow_action_set_ipv6)),
4830 .next = NEXT(action_set_ipv6_dst),
4833 [ACTION_SET_IPV6_DST_IPV6_DST] = {
4834 .name = "ipv6_addr",
4835 .help = "new IPv6 destination address to set",
4836 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4837 .args = ARGS(ARGS_ENTRY_HTON
4838 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4839 .call = parse_vc_conf,
4841 [ACTION_SET_TP_SRC] = {
4842 .name = "set_tp_src",
4843 .help = "set a new source port number in the outermost"
4845 .priv = PRIV_ACTION(SET_TP_SRC,
4846 sizeof(struct rte_flow_action_set_tp)),
4847 .next = NEXT(action_set_tp_src),
4850 [ACTION_SET_TP_SRC_TP_SRC] = {
4852 .help = "new source port number to set",
4853 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
4854 .args = ARGS(ARGS_ENTRY_HTON
4855 (struct rte_flow_action_set_tp, port)),
4856 .call = parse_vc_conf,
4858 [ACTION_SET_TP_DST] = {
4859 .name = "set_tp_dst",
4860 .help = "set a new destination port number in the outermost"
4862 .priv = PRIV_ACTION(SET_TP_DST,
4863 sizeof(struct rte_flow_action_set_tp)),
4864 .next = NEXT(action_set_tp_dst),
4867 [ACTION_SET_TP_DST_TP_DST] = {
4869 .help = "new destination port number to set",
4870 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
4871 .args = ARGS(ARGS_ENTRY_HTON
4872 (struct rte_flow_action_set_tp, port)),
4873 .call = parse_vc_conf,
4875 [ACTION_MAC_SWAP] = {
4877 .help = "Swap the source and destination MAC addresses"
4878 " in the outermost Ethernet header",
4879 .priv = PRIV_ACTION(MAC_SWAP, 0),
4880 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4883 [ACTION_DEC_TTL] = {
4885 .help = "decrease network TTL if available",
4886 .priv = PRIV_ACTION(DEC_TTL, 0),
4887 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4890 [ACTION_SET_TTL] = {
4892 .help = "set ttl value",
4893 .priv = PRIV_ACTION(SET_TTL,
4894 sizeof(struct rte_flow_action_set_ttl)),
4895 .next = NEXT(action_set_ttl),
4898 [ACTION_SET_TTL_TTL] = {
4899 .name = "ttl_value",
4900 .help = "new ttl value to set",
4901 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4902 .args = ARGS(ARGS_ENTRY_HTON
4903 (struct rte_flow_action_set_ttl, ttl_value)),
4904 .call = parse_vc_conf,
4906 [ACTION_SET_MAC_SRC] = {
4907 .name = "set_mac_src",
4908 .help = "set source mac address",
4909 .priv = PRIV_ACTION(SET_MAC_SRC,
4910 sizeof(struct rte_flow_action_set_mac)),
4911 .next = NEXT(action_set_mac_src),
4914 [ACTION_SET_MAC_SRC_MAC_SRC] = {
4916 .help = "new source mac address",
4917 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
4918 .args = ARGS(ARGS_ENTRY_HTON
4919 (struct rte_flow_action_set_mac, mac_addr)),
4920 .call = parse_vc_conf,
4922 [ACTION_SET_MAC_DST] = {
4923 .name = "set_mac_dst",
4924 .help = "set destination mac address",
4925 .priv = PRIV_ACTION(SET_MAC_DST,
4926 sizeof(struct rte_flow_action_set_mac)),
4927 .next = NEXT(action_set_mac_dst),
4930 [ACTION_SET_MAC_DST_MAC_DST] = {
4932 .help = "new destination mac address to set",
4933 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
4934 .args = ARGS(ARGS_ENTRY_HTON
4935 (struct rte_flow_action_set_mac, mac_addr)),
4936 .call = parse_vc_conf,
4938 [ACTION_INC_TCP_SEQ] = {
4939 .name = "inc_tcp_seq",
4940 .help = "increase TCP sequence number",
4941 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
4942 .next = NEXT(action_inc_tcp_seq),
4945 [ACTION_INC_TCP_SEQ_VALUE] = {
4947 .help = "the value to increase TCP sequence number by",
4948 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4949 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4950 .call = parse_vc_conf,
4952 [ACTION_DEC_TCP_SEQ] = {
4953 .name = "dec_tcp_seq",
4954 .help = "decrease TCP sequence number",
4955 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
4956 .next = NEXT(action_dec_tcp_seq),
4959 [ACTION_DEC_TCP_SEQ_VALUE] = {
4961 .help = "the value to decrease TCP sequence number by",
4962 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4963 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4964 .call = parse_vc_conf,
4966 [ACTION_INC_TCP_ACK] = {
4967 .name = "inc_tcp_ack",
4968 .help = "increase TCP acknowledgment number",
4969 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
4970 .next = NEXT(action_inc_tcp_ack),
4973 [ACTION_INC_TCP_ACK_VALUE] = {
4975 .help = "the value to increase TCP acknowledgment number by",
4976 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4977 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4978 .call = parse_vc_conf,
4980 [ACTION_DEC_TCP_ACK] = {
4981 .name = "dec_tcp_ack",
4982 .help = "decrease TCP acknowledgment number",
4983 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
4984 .next = NEXT(action_dec_tcp_ack),
4987 [ACTION_DEC_TCP_ACK_VALUE] = {
4989 .help = "the value to decrease TCP acknowledgment number by",
4990 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4991 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4992 .call = parse_vc_conf,
4994 [ACTION_RAW_ENCAP] = {
4995 .name = "raw_encap",
4996 .help = "encapsulation data, defined by set raw_encap",
4997 .priv = PRIV_ACTION(RAW_ENCAP,
4998 sizeof(struct action_raw_encap_data)),
4999 .next = NEXT(action_raw_encap),
5000 .call = parse_vc_action_raw_encap,
5002 [ACTION_RAW_ENCAP_INDEX] = {
5004 .help = "the index of raw_encap_confs",
5005 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
5007 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
5010 .help = "unsigned integer value",
5011 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5012 .call = parse_vc_action_raw_encap_index,
5013 .comp = comp_set_raw_index,
5015 [ACTION_RAW_DECAP] = {
5016 .name = "raw_decap",
5017 .help = "decapsulation data, defined by set raw_encap",
5018 .priv = PRIV_ACTION(RAW_DECAP,
5019 sizeof(struct action_raw_decap_data)),
5020 .next = NEXT(action_raw_decap),
5021 .call = parse_vc_action_raw_decap,
5023 [ACTION_RAW_DECAP_INDEX] = {
5025 .help = "the index of raw_encap_confs",
5026 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
5028 [ACTION_RAW_DECAP_INDEX_VALUE] = {
5031 .help = "unsigned integer value",
5032 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5033 .call = parse_vc_action_raw_decap_index,
5034 .comp = comp_set_raw_index,
5036 [ACTION_MODIFY_FIELD] = {
5037 .name = "modify_field",
5038 .help = "modify destination field with data from source field",
5039 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
5040 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
5043 [ACTION_MODIFY_FIELD_OP] = {
5045 .help = "operation type",
5046 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
5047 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
5048 .call = parse_vc_conf,
5050 [ACTION_MODIFY_FIELD_OP_VALUE] = {
5051 .name = "{operation}",
5052 .help = "operation type value",
5053 .call = parse_vc_modify_field_op,
5054 .comp = comp_set_modify_field_op,
5056 [ACTION_MODIFY_FIELD_DST_TYPE] = {
5058 .help = "destination field type",
5059 .next = NEXT(action_modify_field_dst,
5060 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
5061 .call = parse_vc_conf,
5063 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
5064 .name = "{dst_type}",
5065 .help = "destination field type value",
5066 .call = parse_vc_modify_field_id,
5067 .comp = comp_set_modify_field_id,
5069 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
5070 .name = "dst_level",
5071 .help = "destination field level",
5072 .next = NEXT(action_modify_field_dst,
5073 NEXT_ENTRY(COMMON_UNSIGNED)),
5074 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5076 .call = parse_vc_conf,
5078 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
5079 .name = "dst_offset",
5080 .help = "destination field bit offset",
5081 .next = NEXT(action_modify_field_dst,
5082 NEXT_ENTRY(COMMON_UNSIGNED)),
5083 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5085 .call = parse_vc_conf,
5087 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
5089 .help = "source field type",
5090 .next = NEXT(action_modify_field_src,
5091 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
5092 .call = parse_vc_conf,
5094 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
5095 .name = "{src_type}",
5096 .help = "source field type value",
5097 .call = parse_vc_modify_field_id,
5098 .comp = comp_set_modify_field_id,
5100 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
5101 .name = "src_level",
5102 .help = "source field level",
5103 .next = NEXT(action_modify_field_src,
5104 NEXT_ENTRY(COMMON_UNSIGNED)),
5105 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5107 .call = parse_vc_conf,
5109 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
5110 .name = "src_offset",
5111 .help = "source field bit offset",
5112 .next = NEXT(action_modify_field_src,
5113 NEXT_ENTRY(COMMON_UNSIGNED)),
5114 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5116 .call = parse_vc_conf,
5118 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
5119 .name = "src_value",
5120 .help = "source immediate value",
5121 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5122 NEXT_ENTRY(COMMON_HEX)),
5123 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
5124 ARGS_ENTRY_ARB(0, 0),
5125 ARGS_ENTRY(struct rte_flow_action_modify_field,
5127 .call = parse_vc_conf,
5129 [ACTION_MODIFY_FIELD_SRC_POINTER] = {
5131 .help = "pointer to source immediate value",
5132 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5133 NEXT_ENTRY(COMMON_HEX)),
5134 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5136 ARGS_ENTRY_ARB(0, 0),
5138 (sizeof(struct rte_flow_action_modify_field),
5139 ACTION_MODIFY_PATTERN_SIZE)),
5140 .call = parse_vc_conf,
5142 [ACTION_MODIFY_FIELD_WIDTH] = {
5144 .help = "number of bits to copy",
5145 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5146 NEXT_ENTRY(COMMON_UNSIGNED)),
5147 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5149 .call = parse_vc_conf,
5151 /* Top level command. */
5154 .help = "set raw encap/decap/sample data",
5155 .type = "set raw_encap|raw_decap <index> <pattern>"
5156 " or set sample_actions <index> <action>",
5157 .next = NEXT(NEXT_ENTRY
5160 SET_SAMPLE_ACTIONS)),
5161 .call = parse_set_init,
5163 /* Sub-level commands. */
5165 .name = "raw_encap",
5166 .help = "set raw encap data",
5167 .next = NEXT(next_set_raw),
5168 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5169 (offsetof(struct buffer, port),
5170 sizeof(((struct buffer *)0)->port),
5171 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5172 .call = parse_set_raw_encap_decap,
5175 .name = "raw_decap",
5176 .help = "set raw decap data",
5177 .next = NEXT(next_set_raw),
5178 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5179 (offsetof(struct buffer, port),
5180 sizeof(((struct buffer *)0)->port),
5181 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5182 .call = parse_set_raw_encap_decap,
5186 .type = "COMMON_UNSIGNED",
5187 .help = "index of raw_encap/raw_decap data",
5188 .next = NEXT(next_item),
5191 [SET_SAMPLE_INDEX] = {
5194 .help = "index of sample actions",
5195 .next = NEXT(next_action_sample),
5198 [SET_SAMPLE_ACTIONS] = {
5199 .name = "sample_actions",
5200 .help = "set sample actions list",
5201 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
5202 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5203 (offsetof(struct buffer, port),
5204 sizeof(((struct buffer *)0)->port),
5205 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
5206 .call = parse_set_sample_action,
5208 [ACTION_SET_TAG] = {
5211 .priv = PRIV_ACTION(SET_TAG,
5212 sizeof(struct rte_flow_action_set_tag)),
5213 .next = NEXT(action_set_tag),
5216 [ACTION_SET_TAG_INDEX] = {
5218 .help = "index of tag array",
5219 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5220 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
5221 .call = parse_vc_conf,
5223 [ACTION_SET_TAG_DATA] = {
5225 .help = "tag value",
5226 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5227 .args = ARGS(ARGS_ENTRY
5228 (struct rte_flow_action_set_tag, data)),
5229 .call = parse_vc_conf,
5231 [ACTION_SET_TAG_MASK] = {
5233 .help = "mask for tag value",
5234 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5235 .args = ARGS(ARGS_ENTRY
5236 (struct rte_flow_action_set_tag, mask)),
5237 .call = parse_vc_conf,
5239 [ACTION_SET_META] = {
5241 .help = "set metadata",
5242 .priv = PRIV_ACTION(SET_META,
5243 sizeof(struct rte_flow_action_set_meta)),
5244 .next = NEXT(action_set_meta),
5245 .call = parse_vc_action_set_meta,
5247 [ACTION_SET_META_DATA] = {
5249 .help = "metadata value",
5250 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5251 .args = ARGS(ARGS_ENTRY
5252 (struct rte_flow_action_set_meta, data)),
5253 .call = parse_vc_conf,
5255 [ACTION_SET_META_MASK] = {
5257 .help = "mask for metadata value",
5258 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5259 .args = ARGS(ARGS_ENTRY
5260 (struct rte_flow_action_set_meta, mask)),
5261 .call = parse_vc_conf,
5263 [ACTION_SET_IPV4_DSCP] = {
5264 .name = "set_ipv4_dscp",
5265 .help = "set DSCP value",
5266 .priv = PRIV_ACTION(SET_IPV4_DSCP,
5267 sizeof(struct rte_flow_action_set_dscp)),
5268 .next = NEXT(action_set_ipv4_dscp),
5271 [ACTION_SET_IPV4_DSCP_VALUE] = {
5272 .name = "dscp_value",
5273 .help = "new IPv4 DSCP value to set",
5274 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5275 .args = ARGS(ARGS_ENTRY
5276 (struct rte_flow_action_set_dscp, dscp)),
5277 .call = parse_vc_conf,
5279 [ACTION_SET_IPV6_DSCP] = {
5280 .name = "set_ipv6_dscp",
5281 .help = "set DSCP value",
5282 .priv = PRIV_ACTION(SET_IPV6_DSCP,
5283 sizeof(struct rte_flow_action_set_dscp)),
5284 .next = NEXT(action_set_ipv6_dscp),
5287 [ACTION_SET_IPV6_DSCP_VALUE] = {
5288 .name = "dscp_value",
5289 .help = "new IPv6 DSCP value to set",
5290 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5291 .args = ARGS(ARGS_ENTRY
5292 (struct rte_flow_action_set_dscp, dscp)),
5293 .call = parse_vc_conf,
5297 .help = "set a specific metadata header",
5298 .next = NEXT(action_age),
5299 .priv = PRIV_ACTION(AGE,
5300 sizeof(struct rte_flow_action_age)),
5303 [ACTION_AGE_TIMEOUT] = {
5305 .help = "flow age timeout value",
5306 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
5308 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
5309 .call = parse_vc_conf,
5313 .help = "set a sample action",
5314 .next = NEXT(action_sample),
5315 .priv = PRIV_ACTION(SAMPLE,
5316 sizeof(struct action_sample_data)),
5317 .call = parse_vc_action_sample,
5319 [ACTION_SAMPLE_RATIO] = {
5321 .help = "flow sample ratio value",
5322 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
5323 .args = ARGS(ARGS_ENTRY_ARB
5324 (offsetof(struct action_sample_data, conf) +
5325 offsetof(struct rte_flow_action_sample, ratio),
5326 sizeof(((struct rte_flow_action_sample *)0)->
5329 [ACTION_SAMPLE_INDEX] = {
5331 .help = "the index of sample actions list",
5332 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
5334 [ACTION_SAMPLE_INDEX_VALUE] = {
5336 .type = "COMMON_UNSIGNED",
5337 .help = "unsigned integer value",
5338 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5339 .call = parse_vc_action_sample_index,
5340 .comp = comp_set_sample_index,
5342 [ACTION_CONNTRACK] = {
5343 .name = "conntrack",
5344 .help = "create a conntrack object",
5345 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5346 .priv = PRIV_ACTION(CONNTRACK,
5347 sizeof(struct rte_flow_action_conntrack)),
5350 [ACTION_CONNTRACK_UPDATE] = {
5351 .name = "conntrack_update",
5352 .help = "update a conntrack object",
5353 .next = NEXT(action_update_conntrack),
5354 .priv = PRIV_ACTION(CONNTRACK,
5355 sizeof(struct rte_flow_modify_conntrack)),
5358 [ACTION_CONNTRACK_UPDATE_DIR] = {
5360 .help = "update a conntrack object direction",
5361 .next = NEXT(action_update_conntrack),
5362 .call = parse_vc_action_conntrack_update,
5364 [ACTION_CONNTRACK_UPDATE_CTX] = {
5366 .help = "update a conntrack object context",
5367 .next = NEXT(action_update_conntrack),
5368 .call = parse_vc_action_conntrack_update,
5370 [ACTION_PORT_REPRESENTOR] = {
5371 .name = "port_representor",
5372 .help = "at embedded switch level, send matching traffic to the given ethdev",
5373 .priv = PRIV_ACTION(PORT_REPRESENTOR,
5374 sizeof(struct rte_flow_action_ethdev)),
5375 .next = NEXT(action_port_representor),
5378 [ACTION_PORT_REPRESENTOR_PORT_ID] = {
5380 .help = "ethdev port ID",
5381 .next = NEXT(action_port_representor,
5382 NEXT_ENTRY(COMMON_UNSIGNED)),
5383 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
5385 .call = parse_vc_conf,
5387 [ACTION_REPRESENTED_PORT] = {
5388 .name = "represented_port",
5389 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
5390 .priv = PRIV_ACTION(REPRESENTED_PORT,
5391 sizeof(struct rte_flow_action_ethdev)),
5392 .next = NEXT(action_represented_port),
5395 [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5396 .name = "ethdev_port_id",
5397 .help = "ethdev port ID",
5398 .next = NEXT(action_represented_port,
5399 NEXT_ENTRY(COMMON_UNSIGNED)),
5400 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
5402 .call = parse_vc_conf,
5404 /* Indirect action destroy arguments. */
5405 [INDIRECT_ACTION_DESTROY_ID] = {
5406 .name = "action_id",
5407 .help = "specify a indirect action id to destroy",
5408 .next = NEXT(next_ia_destroy_attr,
5409 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
5410 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
5411 args.ia_destroy.action_id)),
5412 .call = parse_ia_destroy,
5414 /* Indirect action create arguments. */
5415 [INDIRECT_ACTION_CREATE_ID] = {
5416 .name = "action_id",
5417 .help = "specify a indirect action id to create",
5418 .next = NEXT(next_ia_create_attr,
5419 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
5420 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
5422 [ACTION_INDIRECT] = {
5424 .help = "apply indirect action by id",
5425 .priv = PRIV_ACTION(INDIRECT, 0),
5426 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
5427 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
5430 [INDIRECT_ACTION_ID2PTR] = {
5431 .name = "{action_id}",
5432 .type = "INDIRECT_ACTION_ID",
5433 .help = "indirect action id",
5434 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5435 .call = parse_ia_id2ptr,
5438 [INDIRECT_ACTION_INGRESS] = {
5440 .help = "affect rule to ingress",
5441 .next = NEXT(next_ia_create_attr),
5444 [INDIRECT_ACTION_EGRESS] = {
5446 .help = "affect rule to egress",
5447 .next = NEXT(next_ia_create_attr),
5450 [INDIRECT_ACTION_TRANSFER] = {
5452 .help = "affect rule to transfer",
5453 .next = NEXT(next_ia_create_attr),
5456 [INDIRECT_ACTION_SPEC] = {
5458 .help = "specify action to create indirect handle",
5459 .next = NEXT(next_action),
5462 .name = "g_actions",
5463 .help = "submit a list of associated actions for green",
5464 .next = NEXT(next_action),
5468 .name = "y_actions",
5469 .help = "submit a list of associated actions for yellow",
5470 .next = NEXT(next_action),
5473 .name = "r_actions",
5474 .help = "submit a list of associated actions for red",
5475 .next = NEXT(next_action),
5478 /* Top-level command. */
5481 .type = "port meter policy {port_id} {arg}",
5482 .help = "add port meter policy",
5483 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
5486 /* Sub-level commands. */
5489 .help = "add port meter policy",
5490 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
5492 [ITEM_POL_METER] = {
5494 .help = "add port meter policy",
5495 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
5497 [ITEM_POL_POLICY] = {
5499 .help = "add port meter policy",
5500 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
5501 NEXT_ENTRY(ACTION_POL_Y),
5502 NEXT_ENTRY(ACTION_POL_G),
5503 NEXT_ENTRY(COMMON_POLICY_ID),
5504 NEXT_ENTRY(COMMON_PORT_ID)),
5505 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
5506 ARGS_ENTRY(struct buffer, port)),
5511 /** Remove and return last entry from argument stack. */
5512 static const struct arg *
5513 pop_args(struct context *ctx)
5515 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
5518 /** Add entry on top of the argument stack. */
5520 push_args(struct context *ctx, const struct arg *arg)
5522 if (ctx->args_num == CTX_STACK_SIZE)
5524 ctx->args[ctx->args_num++] = arg;
5528 /** Spread value into buffer according to bit-mask. */
5530 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
5532 uint32_t i = arg->size;
5540 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5549 unsigned int shift = 0;
5550 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
5552 for (shift = 0; arg->mask[i] >> shift; ++shift) {
5553 if (!(arg->mask[i] & (1 << shift)))
5558 *buf &= ~(1 << shift);
5559 *buf |= (val & 1) << shift;
5567 /** Compare a string with a partial one of a given length. */
5569 strcmp_partial(const char *full, const char *partial, size_t partial_len)
5571 int r = strncmp(full, partial, partial_len);
5575 if (strlen(full) <= partial_len)
5577 return full[partial_len];
5581 * Parse a prefix length and generate a bit-mask.
5583 * Last argument (ctx->args) is retrieved to determine mask size, storage
5584 * location and whether the result must use network byte ordering.
5587 parse_prefix(struct context *ctx, const struct token *token,
5588 const char *str, unsigned int len,
5589 void *buf, unsigned int size)
5591 const struct arg *arg = pop_args(ctx);
5592 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
5599 /* Argument is expected. */
5603 u = strtoumax(str, &end, 0);
5604 if (errno || (size_t)(end - str) != len)
5609 extra = arg_entry_bf_fill(NULL, 0, arg);
5618 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
5619 !arg_entry_bf_fill(ctx->objmask, -1, arg))
5626 if (bytes > size || bytes + !!extra > size)
5630 buf = (uint8_t *)ctx->object + arg->offset;
5631 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5633 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
5634 memset(buf, 0x00, size - bytes);
5636 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
5640 memset(buf, 0xff, bytes);
5641 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
5643 ((uint8_t *)buf)[bytes] = conv[extra];
5646 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5649 push_args(ctx, arg);
5653 /** Default parsing function for token name matching. */
5655 parse_default(struct context *ctx, const struct token *token,
5656 const char *str, unsigned int len,
5657 void *buf, unsigned int size)
5662 if (strcmp_partial(token->name, str, len))
5667 /** Parse flow command, initialize output buffer for subsequent tokens. */
5669 parse_init(struct context *ctx, const struct token *token,
5670 const char *str, unsigned int len,
5671 void *buf, unsigned int size)
5673 struct buffer *out = buf;
5675 /* Token name must match. */
5676 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5678 /* Nothing else to do if there is no buffer. */
5681 /* Make sure buffer is large enough. */
5682 if (size < sizeof(*out))
5684 /* Initialize buffer. */
5685 memset(out, 0x00, sizeof(*out));
5686 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5689 ctx->objmask = NULL;
5693 /** Parse tokens for indirect action commands. */
5695 parse_ia(struct context *ctx, const struct token *token,
5696 const char *str, unsigned int len,
5697 void *buf, unsigned int size)
5699 struct buffer *out = buf;
5701 /* Token name must match. */
5702 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5704 /* Nothing else to do if there is no buffer. */
5707 if (!out->command) {
5708 if (ctx->curr != INDIRECT_ACTION)
5710 if (sizeof(*out) > size)
5712 out->command = ctx->curr;
5715 ctx->objmask = NULL;
5716 out->args.vc.data = (uint8_t *)out + size;
5719 switch (ctx->curr) {
5720 case INDIRECT_ACTION_CREATE:
5721 case INDIRECT_ACTION_UPDATE:
5722 out->args.vc.actions =
5723 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5725 out->args.vc.attr.group = UINT32_MAX;
5727 case INDIRECT_ACTION_QUERY:
5728 out->command = ctx->curr;
5731 ctx->objmask = NULL;
5733 case INDIRECT_ACTION_EGRESS:
5734 out->args.vc.attr.egress = 1;
5736 case INDIRECT_ACTION_INGRESS:
5737 out->args.vc.attr.ingress = 1;
5739 case INDIRECT_ACTION_TRANSFER:
5740 out->args.vc.attr.transfer = 1;
5748 /** Parse tokens for indirect action destroy command. */
5750 parse_ia_destroy(struct context *ctx, const struct token *token,
5751 const char *str, unsigned int len,
5752 void *buf, unsigned int size)
5754 struct buffer *out = buf;
5755 uint32_t *action_id;
5757 /* Token name must match. */
5758 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5760 /* Nothing else to do if there is no buffer. */
5763 if (!out->command || out->command == INDIRECT_ACTION) {
5764 if (ctx->curr != INDIRECT_ACTION_DESTROY)
5766 if (sizeof(*out) > size)
5768 out->command = ctx->curr;
5771 ctx->objmask = NULL;
5772 out->args.ia_destroy.action_id =
5773 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5777 action_id = out->args.ia_destroy.action_id
5778 + out->args.ia_destroy.action_id_n++;
5779 if ((uint8_t *)action_id > (uint8_t *)out + size)
5782 ctx->object = action_id;
5783 ctx->objmask = NULL;
5787 /** Parse tokens for meter policy action commands. */
5789 parse_mp(struct context *ctx, const struct token *token,
5790 const char *str, unsigned int len,
5791 void *buf, unsigned int size)
5793 struct buffer *out = buf;
5795 /* Token name must match. */
5796 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5798 /* Nothing else to do if there is no buffer. */
5801 if (!out->command) {
5802 if (ctx->curr != ITEM_POL_POLICY)
5804 if (sizeof(*out) > size)
5806 out->command = ctx->curr;
5809 ctx->objmask = NULL;
5810 out->args.vc.data = (uint8_t *)out + size;
5813 switch (ctx->curr) {
5815 out->args.vc.actions =
5816 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5818 out->command = ctx->curr;
5821 ctx->objmask = NULL;
5828 /** Parse tokens for validate/create commands. */
5830 parse_vc(struct context *ctx, const struct token *token,
5831 const char *str, unsigned int len,
5832 void *buf, unsigned int size)
5834 struct buffer *out = buf;
5838 /* Token name must match. */
5839 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5841 /* Nothing else to do if there is no buffer. */
5844 if (!out->command) {
5845 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
5847 if (sizeof(*out) > size)
5849 out->command = ctx->curr;
5852 ctx->objmask = NULL;
5853 out->args.vc.data = (uint8_t *)out + size;
5857 switch (ctx->curr) {
5859 ctx->object = &out->args.vc.attr;
5862 case VC_TUNNEL_MATCH:
5863 ctx->object = &out->args.vc.tunnel_ops;
5866 ctx->objmask = NULL;
5867 switch (ctx->curr) {
5872 out->args.vc.tunnel_ops.enabled = 1;
5873 out->args.vc.tunnel_ops.actions = 1;
5875 case VC_TUNNEL_MATCH:
5876 out->args.vc.tunnel_ops.enabled = 1;
5877 out->args.vc.tunnel_ops.items = 1;
5880 out->args.vc.attr.ingress = 1;
5883 out->args.vc.attr.egress = 1;
5886 out->args.vc.attr.transfer = 1;
5889 out->args.vc.pattern =
5890 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5892 ctx->object = out->args.vc.pattern;
5893 ctx->objmask = NULL;
5896 out->args.vc.actions =
5897 (void *)RTE_ALIGN_CEIL((uintptr_t)
5898 (out->args.vc.pattern +
5899 out->args.vc.pattern_n),
5901 ctx->object = out->args.vc.actions;
5902 ctx->objmask = NULL;
5909 if (!out->args.vc.actions) {
5910 const struct parse_item_priv *priv = token->priv;
5911 struct rte_flow_item *item =
5912 out->args.vc.pattern + out->args.vc.pattern_n;
5914 data_size = priv->size * 3; /* spec, last, mask */
5915 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5916 (out->args.vc.data - data_size),
5918 if ((uint8_t *)item + sizeof(*item) > data)
5920 *item = (struct rte_flow_item){
5923 ++out->args.vc.pattern_n;
5925 ctx->objmask = NULL;
5927 const struct parse_action_priv *priv = token->priv;
5928 struct rte_flow_action *action =
5929 out->args.vc.actions + out->args.vc.actions_n;
5931 data_size = priv->size; /* configuration */
5932 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5933 (out->args.vc.data - data_size),
5935 if ((uint8_t *)action + sizeof(*action) > data)
5937 *action = (struct rte_flow_action){
5939 .conf = data_size ? data : NULL,
5941 ++out->args.vc.actions_n;
5942 ctx->object = action;
5943 ctx->objmask = NULL;
5945 memset(data, 0, data_size);
5946 out->args.vc.data = data;
5947 ctx->objdata = data_size;
5951 /** Parse pattern item parameter type. */
5953 parse_vc_spec(struct context *ctx, const struct token *token,
5954 const char *str, unsigned int len,
5955 void *buf, unsigned int size)
5957 struct buffer *out = buf;
5958 struct rte_flow_item *item;
5964 /* Token name must match. */
5965 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5967 /* Parse parameter types. */
5968 switch (ctx->curr) {
5969 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
5975 case ITEM_PARAM_SPEC:
5978 case ITEM_PARAM_LAST:
5981 case ITEM_PARAM_PREFIX:
5982 /* Modify next token to expect a prefix. */
5983 if (ctx->next_num < 2)
5985 ctx->next[ctx->next_num - 2] = prefix;
5987 case ITEM_PARAM_MASK:
5993 /* Nothing else to do if there is no buffer. */
5996 if (!out->args.vc.pattern_n)
5998 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
5999 data_size = ctx->objdata / 3; /* spec, last, mask */
6000 /* Point to selected object. */
6001 ctx->object = out->args.vc.data + (data_size * index);
6003 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
6004 item->mask = ctx->objmask;
6006 ctx->objmask = NULL;
6007 /* Update relevant item pointer. */
6008 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
6013 /** Parse action configuration field. */
6015 parse_vc_conf(struct context *ctx, const struct token *token,
6016 const char *str, unsigned int len,
6017 void *buf, unsigned int size)
6019 struct buffer *out = buf;
6022 /* Token name must match. */
6023 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6025 /* Nothing else to do if there is no buffer. */
6028 /* Point to selected object. */
6029 ctx->object = out->args.vc.data;
6030 ctx->objmask = NULL;
6034 /** Parse eCPRI common header type field. */
6036 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
6037 const char *str, unsigned int len,
6038 void *buf, unsigned int size)
6040 struct rte_flow_item_ecpri *ecpri;
6041 struct rte_flow_item_ecpri *ecpri_mask;
6042 struct rte_flow_item *item;
6045 struct buffer *out = buf;
6046 const struct arg *arg;
6049 /* Token name must match. */
6050 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6052 switch (ctx->curr) {
6053 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
6054 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
6056 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
6057 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
6059 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
6060 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
6067 arg = pop_args(ctx);
6070 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
6071 ecpri->hdr.common.type = msg_type;
6072 data_size = ctx->objdata / 3; /* spec, last, mask */
6073 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
6075 ecpri_mask->hdr.common.type = 0xFF;
6077 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
6078 ecpri_mask->hdr.common.u32 =
6079 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
6081 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6083 item->mask = ecpri_mask;
6087 /** Parse L2TPv2 common header type field. */
6089 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
6090 const char *str, unsigned int len,
6091 void *buf, unsigned int size)
6093 struct rte_flow_item_l2tpv2 *l2tpv2;
6094 struct rte_flow_item_l2tpv2 *l2tpv2_mask;
6095 struct rte_flow_item *item;
6097 uint16_t msg_type = 0;
6098 struct buffer *out = buf;
6099 const struct arg *arg;
6102 /* Token name must match. */
6103 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6105 switch (ctx->curr) {
6106 case ITEM_L2TPV2_TYPE_DATA:
6107 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
6109 case ITEM_L2TPV2_TYPE_DATA_L:
6110 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
6112 case ITEM_L2TPV2_TYPE_DATA_S:
6113 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
6115 case ITEM_L2TPV2_TYPE_DATA_O:
6116 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
6118 case ITEM_L2TPV2_TYPE_DATA_L_S:
6119 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
6121 case ITEM_L2TPV2_TYPE_CTRL:
6122 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
6129 arg = pop_args(ctx);
6132 l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
6133 l2tpv2->hdr.common.flags_version |= msg_type;
6134 data_size = ctx->objdata / 3; /* spec, last, mask */
6135 l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
6137 l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
6139 l2tpv2->hdr.common.flags_version =
6140 rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
6141 l2tpv2_mask->hdr.common.flags_version =
6142 rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
6144 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6145 item->spec = l2tpv2;
6146 item->mask = l2tpv2_mask;
6150 /** Parse meter color action type. */
6152 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
6153 const char *str, unsigned int len,
6154 void *buf, unsigned int size)
6156 struct rte_flow_action *action_data;
6157 struct rte_flow_action_meter_color *conf;
6158 enum rte_color color;
6162 /* Token name must match. */
6163 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6165 switch (ctx->curr) {
6166 case ACTION_METER_COLOR_GREEN:
6167 color = RTE_COLOR_GREEN;
6169 case ACTION_METER_COLOR_YELLOW:
6170 color = RTE_COLOR_YELLOW;
6172 case ACTION_METER_COLOR_RED:
6173 color = RTE_COLOR_RED;
6181 action_data = ctx->object;
6182 conf = (struct rte_flow_action_meter_color *)
6183 (uintptr_t)(action_data->conf);
6184 conf->color = color;
6188 /** Parse RSS action. */
6190 parse_vc_action_rss(struct context *ctx, const struct token *token,
6191 const char *str, unsigned int len,
6192 void *buf, unsigned int size)
6194 struct buffer *out = buf;
6195 struct rte_flow_action *action;
6196 struct action_rss_data *action_rss_data;
6200 ret = parse_vc(ctx, token, str, len, buf, size);
6203 /* Nothing else to do if there is no buffer. */
6206 if (!out->args.vc.actions_n)
6208 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6209 /* Point to selected object. */
6210 ctx->object = out->args.vc.data;
6211 ctx->objmask = NULL;
6212 /* Set up default configuration. */
6213 action_rss_data = ctx->object;
6214 *action_rss_data = (struct action_rss_data){
6215 .conf = (struct rte_flow_action_rss){
6216 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
6220 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
6222 .queue = action_rss_data->queue,
6226 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
6227 action_rss_data->queue[i] = i;
6228 action->conf = &action_rss_data->conf;
6233 * Parse func field for RSS action.
6235 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
6236 * ACTION_RSS_FUNC_* index that called this function.
6239 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
6240 const char *str, unsigned int len,
6241 void *buf, unsigned int size)
6243 struct action_rss_data *action_rss_data;
6244 enum rte_eth_hash_function func;
6248 /* Token name must match. */
6249 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6251 switch (ctx->curr) {
6252 case ACTION_RSS_FUNC_DEFAULT:
6253 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
6255 case ACTION_RSS_FUNC_TOEPLITZ:
6256 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
6258 case ACTION_RSS_FUNC_SIMPLE_XOR:
6259 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
6261 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
6262 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
6269 action_rss_data = ctx->object;
6270 action_rss_data->conf.func = func;
6275 * Parse type field for RSS action.
6277 * Valid tokens are type field names and the "end" token.
6280 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
6281 const char *str, unsigned int len,
6282 void *buf, unsigned int size)
6284 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
6285 struct action_rss_data *action_rss_data;
6291 if (ctx->curr != ACTION_RSS_TYPE)
6293 if (!(ctx->objdata >> 16) && ctx->object) {
6294 action_rss_data = ctx->object;
6295 action_rss_data->conf.types = 0;
6297 if (!strcmp_partial("end", str, len)) {
6298 ctx->objdata &= 0xffff;
6301 for (i = 0; rss_type_table[i].str; ++i)
6302 if (!strcmp_partial(rss_type_table[i].str, str, len))
6304 if (!rss_type_table[i].str)
6306 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
6308 if (ctx->next_num == RTE_DIM(ctx->next))
6310 ctx->next[ctx->next_num++] = next;
6313 action_rss_data = ctx->object;
6314 action_rss_data->conf.types |= rss_type_table[i].rss_type;
6319 * Parse queue field for RSS action.
6321 * Valid tokens are queue indices and the "end" token.
6324 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
6325 const char *str, unsigned int len,
6326 void *buf, unsigned int size)
6328 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
6329 struct action_rss_data *action_rss_data;
6330 const struct arg *arg;
6337 if (ctx->curr != ACTION_RSS_QUEUE)
6339 i = ctx->objdata >> 16;
6340 if (!strcmp_partial("end", str, len)) {
6341 ctx->objdata &= 0xffff;
6344 if (i >= ACTION_RSS_QUEUE_NUM)
6346 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
6347 i * sizeof(action_rss_data->queue[i]),
6348 sizeof(action_rss_data->queue[i]));
6349 if (push_args(ctx, arg))
6351 ret = parse_int(ctx, token, str, len, NULL, 0);
6357 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
6359 if (ctx->next_num == RTE_DIM(ctx->next))
6361 ctx->next[ctx->next_num++] = next;
6365 action_rss_data = ctx->object;
6366 action_rss_data->conf.queue_num = i;
6367 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
6371 /** Setup VXLAN encap configuration. */
6373 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
6375 /* Set up default configuration. */
6376 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
6377 .conf = (struct rte_flow_action_vxlan_encap){
6378 .definition = action_vxlan_encap_data->items,
6382 .type = RTE_FLOW_ITEM_TYPE_ETH,
6383 .spec = &action_vxlan_encap_data->item_eth,
6384 .mask = &rte_flow_item_eth_mask,
6387 .type = RTE_FLOW_ITEM_TYPE_VLAN,
6388 .spec = &action_vxlan_encap_data->item_vlan,
6389 .mask = &rte_flow_item_vlan_mask,
6392 .type = RTE_FLOW_ITEM_TYPE_IPV4,
6393 .spec = &action_vxlan_encap_data->item_ipv4,
6394 .mask = &rte_flow_item_ipv4_mask,
6397 .type = RTE_FLOW_ITEM_TYPE_UDP,
6398 .spec = &action_vxlan_encap_data->item_udp,
6399 .mask = &rte_flow_item_udp_mask,
6402 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
6403 .spec = &action_vxlan_encap_data->item_vxlan,
6404 .mask = &rte_flow_item_vxlan_mask,
6407 .type = RTE_FLOW_ITEM_TYPE_END,
6412 .tci = vxlan_encap_conf.vlan_tci,
6416 .src_addr = vxlan_encap_conf.ipv4_src,
6417 .dst_addr = vxlan_encap_conf.ipv4_dst,
6420 .src_port = vxlan_encap_conf.udp_src,
6421 .dst_port = vxlan_encap_conf.udp_dst,
6423 .item_vxlan.flags = 0,
6425 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
6426 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6427 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
6428 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6429 if (!vxlan_encap_conf.select_ipv4) {
6430 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
6431 &vxlan_encap_conf.ipv6_src,
6432 sizeof(vxlan_encap_conf.ipv6_src));
6433 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
6434 &vxlan_encap_conf.ipv6_dst,
6435 sizeof(vxlan_encap_conf.ipv6_dst));
6436 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
6437 .type = RTE_FLOW_ITEM_TYPE_IPV6,
6438 .spec = &action_vxlan_encap_data->item_ipv6,
6439 .mask = &rte_flow_item_ipv6_mask,
6442 if (!vxlan_encap_conf.select_vlan)
6443 action_vxlan_encap_data->items[1].type =
6444 RTE_FLOW_ITEM_TYPE_VOID;
6445 if (vxlan_encap_conf.select_tos_ttl) {
6446 if (vxlan_encap_conf.select_ipv4) {
6447 static struct rte_flow_item_ipv4 ipv4_mask_tos;
6449 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
6450 sizeof(ipv4_mask_tos));
6451 ipv4_mask_tos.hdr.type_of_service = 0xff;
6452 ipv4_mask_tos.hdr.time_to_live = 0xff;
6453 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
6454 vxlan_encap_conf.ip_tos;
6455 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
6456 vxlan_encap_conf.ip_ttl;
6457 action_vxlan_encap_data->items[2].mask =
6460 static struct rte_flow_item_ipv6 ipv6_mask_tos;
6462 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
6463 sizeof(ipv6_mask_tos));
6464 ipv6_mask_tos.hdr.vtc_flow |=
6465 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
6466 ipv6_mask_tos.hdr.hop_limits = 0xff;
6467 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
6469 ((uint32_t)vxlan_encap_conf.ip_tos <<
6470 RTE_IPV6_HDR_TC_SHIFT);
6471 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
6472 vxlan_encap_conf.ip_ttl;
6473 action_vxlan_encap_data->items[2].mask =
6477 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
6478 RTE_DIM(vxlan_encap_conf.vni));
6482 /** Parse VXLAN encap action. */
6484 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
6485 const char *str, unsigned int len,
6486 void *buf, unsigned int size)
6488 struct buffer *out = buf;
6489 struct rte_flow_action *action;
6490 struct action_vxlan_encap_data *action_vxlan_encap_data;
6493 ret = parse_vc(ctx, token, str, len, buf, size);
6496 /* Nothing else to do if there is no buffer. */
6499 if (!out->args.vc.actions_n)
6501 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6502 /* Point to selected object. */
6503 ctx->object = out->args.vc.data;
6504 ctx->objmask = NULL;
6505 action_vxlan_encap_data = ctx->object;
6506 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
6507 action->conf = &action_vxlan_encap_data->conf;
6511 /** Setup NVGRE encap configuration. */
6513 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
6515 /* Set up default configuration. */
6516 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
6517 .conf = (struct rte_flow_action_nvgre_encap){
6518 .definition = action_nvgre_encap_data->items,
6522 .type = RTE_FLOW_ITEM_TYPE_ETH,
6523 .spec = &action_nvgre_encap_data->item_eth,
6524 .mask = &rte_flow_item_eth_mask,
6527 .type = RTE_FLOW_ITEM_TYPE_VLAN,
6528 .spec = &action_nvgre_encap_data->item_vlan,
6529 .mask = &rte_flow_item_vlan_mask,
6532 .type = RTE_FLOW_ITEM_TYPE_IPV4,
6533 .spec = &action_nvgre_encap_data->item_ipv4,
6534 .mask = &rte_flow_item_ipv4_mask,
6537 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
6538 .spec = &action_nvgre_encap_data->item_nvgre,
6539 .mask = &rte_flow_item_nvgre_mask,
6542 .type = RTE_FLOW_ITEM_TYPE_END,
6547 .tci = nvgre_encap_conf.vlan_tci,
6551 .src_addr = nvgre_encap_conf.ipv4_src,
6552 .dst_addr = nvgre_encap_conf.ipv4_dst,
6554 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
6555 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
6556 .item_nvgre.flow_id = 0,
6558 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
6559 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6560 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
6561 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6562 if (!nvgre_encap_conf.select_ipv4) {
6563 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
6564 &nvgre_encap_conf.ipv6_src,
6565 sizeof(nvgre_encap_conf.ipv6_src));
6566 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
6567 &nvgre_encap_conf.ipv6_dst,
6568 sizeof(nvgre_encap_conf.ipv6_dst));
6569 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
6570 .type = RTE_FLOW_ITEM_TYPE_IPV6,
6571 .spec = &action_nvgre_encap_data->item_ipv6,
6572 .mask = &rte_flow_item_ipv6_mask,
6575 if (!nvgre_encap_conf.select_vlan)
6576 action_nvgre_encap_data->items[1].type =
6577 RTE_FLOW_ITEM_TYPE_VOID;
6578 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
6579 RTE_DIM(nvgre_encap_conf.tni));
6583 /** Parse NVGRE encap action. */
6585 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
6586 const char *str, unsigned int len,
6587 void *buf, unsigned int size)
6589 struct buffer *out = buf;
6590 struct rte_flow_action *action;
6591 struct action_nvgre_encap_data *action_nvgre_encap_data;
6594 ret = parse_vc(ctx, token, str, len, buf, size);
6597 /* Nothing else to do if there is no buffer. */
6600 if (!out->args.vc.actions_n)
6602 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6603 /* Point to selected object. */
6604 ctx->object = out->args.vc.data;
6605 ctx->objmask = NULL;
6606 action_nvgre_encap_data = ctx->object;
6607 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
6608 action->conf = &action_nvgre_encap_data->conf;
6612 /** Parse l2 encap action. */
6614 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
6615 const char *str, unsigned int len,
6616 void *buf, unsigned int size)
6618 struct buffer *out = buf;
6619 struct rte_flow_action *action;
6620 struct action_raw_encap_data *action_encap_data;
6621 struct rte_flow_item_eth eth = { .type = 0, };
6622 struct rte_flow_item_vlan vlan = {
6623 .tci = mplsoudp_encap_conf.vlan_tci,
6629 ret = parse_vc(ctx, token, str, len, buf, size);
6632 /* Nothing else to do if there is no buffer. */
6635 if (!out->args.vc.actions_n)
6637 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6638 /* Point to selected object. */
6639 ctx->object = out->args.vc.data;
6640 ctx->objmask = NULL;
6641 /* Copy the headers to the buffer. */
6642 action_encap_data = ctx->object;
6643 *action_encap_data = (struct action_raw_encap_data) {
6644 .conf = (struct rte_flow_action_raw_encap){
6645 .data = action_encap_data->data,
6649 header = action_encap_data->data;
6650 if (l2_encap_conf.select_vlan)
6651 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6652 else if (l2_encap_conf.select_ipv4)
6653 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6655 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6656 memcpy(eth.dst.addr_bytes,
6657 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6658 memcpy(eth.src.addr_bytes,
6659 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6660 memcpy(header, ð, sizeof(eth));
6661 header += sizeof(eth);
6662 if (l2_encap_conf.select_vlan) {
6663 if (l2_encap_conf.select_ipv4)
6664 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6666 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6667 memcpy(header, &vlan, sizeof(vlan));
6668 header += sizeof(vlan);
6670 action_encap_data->conf.size = header -
6671 action_encap_data->data;
6672 action->conf = &action_encap_data->conf;
6676 /** Parse l2 decap action. */
6678 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
6679 const char *str, unsigned int len,
6680 void *buf, unsigned int size)
6682 struct buffer *out = buf;
6683 struct rte_flow_action *action;
6684 struct action_raw_decap_data *action_decap_data;
6685 struct rte_flow_item_eth eth = { .type = 0, };
6686 struct rte_flow_item_vlan vlan = {
6687 .tci = mplsoudp_encap_conf.vlan_tci,
6693 ret = parse_vc(ctx, token, str, len, buf, size);
6696 /* Nothing else to do if there is no buffer. */
6699 if (!out->args.vc.actions_n)
6701 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6702 /* Point to selected object. */
6703 ctx->object = out->args.vc.data;
6704 ctx->objmask = NULL;
6705 /* Copy the headers to the buffer. */
6706 action_decap_data = ctx->object;
6707 *action_decap_data = (struct action_raw_decap_data) {
6708 .conf = (struct rte_flow_action_raw_decap){
6709 .data = action_decap_data->data,
6713 header = action_decap_data->data;
6714 if (l2_decap_conf.select_vlan)
6715 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6716 memcpy(header, ð, sizeof(eth));
6717 header += sizeof(eth);
6718 if (l2_decap_conf.select_vlan) {
6719 memcpy(header, &vlan, sizeof(vlan));
6720 header += sizeof(vlan);
6722 action_decap_data->conf.size = header -
6723 action_decap_data->data;
6724 action->conf = &action_decap_data->conf;
6728 #define ETHER_TYPE_MPLS_UNICAST 0x8847
6730 /** Parse MPLSOGRE encap action. */
6732 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
6733 const char *str, unsigned int len,
6734 void *buf, unsigned int size)
6736 struct buffer *out = buf;
6737 struct rte_flow_action *action;
6738 struct action_raw_encap_data *action_encap_data;
6739 struct rte_flow_item_eth eth = { .type = 0, };
6740 struct rte_flow_item_vlan vlan = {
6741 .tci = mplsogre_encap_conf.vlan_tci,
6744 struct rte_flow_item_ipv4 ipv4 = {
6746 .src_addr = mplsogre_encap_conf.ipv4_src,
6747 .dst_addr = mplsogre_encap_conf.ipv4_dst,
6748 .next_proto_id = IPPROTO_GRE,
6749 .version_ihl = RTE_IPV4_VHL_DEF,
6750 .time_to_live = IPDEFTTL,
6753 struct rte_flow_item_ipv6 ipv6 = {
6755 .proto = IPPROTO_GRE,
6756 .hop_limits = IPDEFTTL,
6759 struct rte_flow_item_gre gre = {
6760 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6762 struct rte_flow_item_mpls mpls = {
6768 ret = parse_vc(ctx, token, str, len, buf, size);
6771 /* Nothing else to do if there is no buffer. */
6774 if (!out->args.vc.actions_n)
6776 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6777 /* Point to selected object. */
6778 ctx->object = out->args.vc.data;
6779 ctx->objmask = NULL;
6780 /* Copy the headers to the buffer. */
6781 action_encap_data = ctx->object;
6782 *action_encap_data = (struct action_raw_encap_data) {
6783 .conf = (struct rte_flow_action_raw_encap){
6784 .data = action_encap_data->data,
6789 header = action_encap_data->data;
6790 if (mplsogre_encap_conf.select_vlan)
6791 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6792 else if (mplsogre_encap_conf.select_ipv4)
6793 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6795 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6796 memcpy(eth.dst.addr_bytes,
6797 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6798 memcpy(eth.src.addr_bytes,
6799 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6800 memcpy(header, ð, sizeof(eth));
6801 header += sizeof(eth);
6802 if (mplsogre_encap_conf.select_vlan) {
6803 if (mplsogre_encap_conf.select_ipv4)
6804 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6806 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6807 memcpy(header, &vlan, sizeof(vlan));
6808 header += sizeof(vlan);
6810 if (mplsogre_encap_conf.select_ipv4) {
6811 memcpy(header, &ipv4, sizeof(ipv4));
6812 header += sizeof(ipv4);
6814 memcpy(&ipv6.hdr.src_addr,
6815 &mplsogre_encap_conf.ipv6_src,
6816 sizeof(mplsogre_encap_conf.ipv6_src));
6817 memcpy(&ipv6.hdr.dst_addr,
6818 &mplsogre_encap_conf.ipv6_dst,
6819 sizeof(mplsogre_encap_conf.ipv6_dst));
6820 memcpy(header, &ipv6, sizeof(ipv6));
6821 header += sizeof(ipv6);
6823 memcpy(header, &gre, sizeof(gre));
6824 header += sizeof(gre);
6825 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
6826 RTE_DIM(mplsogre_encap_conf.label));
6827 mpls.label_tc_s[2] |= 0x1;
6828 memcpy(header, &mpls, sizeof(mpls));
6829 header += sizeof(mpls);
6830 action_encap_data->conf.size = header -
6831 action_encap_data->data;
6832 action->conf = &action_encap_data->conf;
6836 /** Parse MPLSOGRE decap action. */
6838 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
6839 const char *str, unsigned int len,
6840 void *buf, unsigned int size)
6842 struct buffer *out = buf;
6843 struct rte_flow_action *action;
6844 struct action_raw_decap_data *action_decap_data;
6845 struct rte_flow_item_eth eth = { .type = 0, };
6846 struct rte_flow_item_vlan vlan = {.tci = 0};
6847 struct rte_flow_item_ipv4 ipv4 = {
6849 .next_proto_id = IPPROTO_GRE,
6852 struct rte_flow_item_ipv6 ipv6 = {
6854 .proto = IPPROTO_GRE,
6857 struct rte_flow_item_gre gre = {
6858 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6860 struct rte_flow_item_mpls mpls;
6864 ret = parse_vc(ctx, token, str, len, buf, size);
6867 /* Nothing else to do if there is no buffer. */
6870 if (!out->args.vc.actions_n)
6872 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6873 /* Point to selected object. */
6874 ctx->object = out->args.vc.data;
6875 ctx->objmask = NULL;
6876 /* Copy the headers to the buffer. */
6877 action_decap_data = ctx->object;
6878 *action_decap_data = (struct action_raw_decap_data) {
6879 .conf = (struct rte_flow_action_raw_decap){
6880 .data = action_decap_data->data,
6884 header = action_decap_data->data;
6885 if (mplsogre_decap_conf.select_vlan)
6886 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6887 else if (mplsogre_encap_conf.select_ipv4)
6888 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6890 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6891 memcpy(eth.dst.addr_bytes,
6892 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6893 memcpy(eth.src.addr_bytes,
6894 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6895 memcpy(header, ð, sizeof(eth));
6896 header += sizeof(eth);
6897 if (mplsogre_encap_conf.select_vlan) {
6898 if (mplsogre_encap_conf.select_ipv4)
6899 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6901 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6902 memcpy(header, &vlan, sizeof(vlan));
6903 header += sizeof(vlan);
6905 if (mplsogre_encap_conf.select_ipv4) {
6906 memcpy(header, &ipv4, sizeof(ipv4));
6907 header += sizeof(ipv4);
6909 memcpy(header, &ipv6, sizeof(ipv6));
6910 header += sizeof(ipv6);
6912 memcpy(header, &gre, sizeof(gre));
6913 header += sizeof(gre);
6914 memset(&mpls, 0, sizeof(mpls));
6915 memcpy(header, &mpls, sizeof(mpls));
6916 header += sizeof(mpls);
6917 action_decap_data->conf.size = header -
6918 action_decap_data->data;
6919 action->conf = &action_decap_data->conf;
6923 /** Parse MPLSOUDP encap action. */
6925 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
6926 const char *str, unsigned int len,
6927 void *buf, unsigned int size)
6929 struct buffer *out = buf;
6930 struct rte_flow_action *action;
6931 struct action_raw_encap_data *action_encap_data;
6932 struct rte_flow_item_eth eth = { .type = 0, };
6933 struct rte_flow_item_vlan vlan = {
6934 .tci = mplsoudp_encap_conf.vlan_tci,
6937 struct rte_flow_item_ipv4 ipv4 = {
6939 .src_addr = mplsoudp_encap_conf.ipv4_src,
6940 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
6941 .next_proto_id = IPPROTO_UDP,
6942 .version_ihl = RTE_IPV4_VHL_DEF,
6943 .time_to_live = IPDEFTTL,
6946 struct rte_flow_item_ipv6 ipv6 = {
6948 .proto = IPPROTO_UDP,
6949 .hop_limits = IPDEFTTL,
6952 struct rte_flow_item_udp udp = {
6954 .src_port = mplsoudp_encap_conf.udp_src,
6955 .dst_port = mplsoudp_encap_conf.udp_dst,
6958 struct rte_flow_item_mpls mpls;
6962 ret = parse_vc(ctx, token, str, len, buf, size);
6965 /* Nothing else to do if there is no buffer. */
6968 if (!out->args.vc.actions_n)
6970 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6971 /* Point to selected object. */
6972 ctx->object = out->args.vc.data;
6973 ctx->objmask = NULL;
6974 /* Copy the headers to the buffer. */
6975 action_encap_data = ctx->object;
6976 *action_encap_data = (struct action_raw_encap_data) {
6977 .conf = (struct rte_flow_action_raw_encap){
6978 .data = action_encap_data->data,
6983 header = action_encap_data->data;
6984 if (mplsoudp_encap_conf.select_vlan)
6985 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6986 else if (mplsoudp_encap_conf.select_ipv4)
6987 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6989 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6990 memcpy(eth.dst.addr_bytes,
6991 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6992 memcpy(eth.src.addr_bytes,
6993 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6994 memcpy(header, ð, sizeof(eth));
6995 header += sizeof(eth);
6996 if (mplsoudp_encap_conf.select_vlan) {
6997 if (mplsoudp_encap_conf.select_ipv4)
6998 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7000 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7001 memcpy(header, &vlan, sizeof(vlan));
7002 header += sizeof(vlan);
7004 if (mplsoudp_encap_conf.select_ipv4) {
7005 memcpy(header, &ipv4, sizeof(ipv4));
7006 header += sizeof(ipv4);
7008 memcpy(&ipv6.hdr.src_addr,
7009 &mplsoudp_encap_conf.ipv6_src,
7010 sizeof(mplsoudp_encap_conf.ipv6_src));
7011 memcpy(&ipv6.hdr.dst_addr,
7012 &mplsoudp_encap_conf.ipv6_dst,
7013 sizeof(mplsoudp_encap_conf.ipv6_dst));
7014 memcpy(header, &ipv6, sizeof(ipv6));
7015 header += sizeof(ipv6);
7017 memcpy(header, &udp, sizeof(udp));
7018 header += sizeof(udp);
7019 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
7020 RTE_DIM(mplsoudp_encap_conf.label));
7021 mpls.label_tc_s[2] |= 0x1;
7022 memcpy(header, &mpls, sizeof(mpls));
7023 header += sizeof(mpls);
7024 action_encap_data->conf.size = header -
7025 action_encap_data->data;
7026 action->conf = &action_encap_data->conf;
7030 /** Parse MPLSOUDP decap action. */
7032 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
7033 const char *str, unsigned int len,
7034 void *buf, unsigned int size)
7036 struct buffer *out = buf;
7037 struct rte_flow_action *action;
7038 struct action_raw_decap_data *action_decap_data;
7039 struct rte_flow_item_eth eth = { .type = 0, };
7040 struct rte_flow_item_vlan vlan = {.tci = 0};
7041 struct rte_flow_item_ipv4 ipv4 = {
7043 .next_proto_id = IPPROTO_UDP,
7046 struct rte_flow_item_ipv6 ipv6 = {
7048 .proto = IPPROTO_UDP,
7051 struct rte_flow_item_udp udp = {
7053 .dst_port = rte_cpu_to_be_16(6635),
7056 struct rte_flow_item_mpls mpls;
7060 ret = parse_vc(ctx, token, str, len, buf, size);
7063 /* Nothing else to do if there is no buffer. */
7066 if (!out->args.vc.actions_n)
7068 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7069 /* Point to selected object. */
7070 ctx->object = out->args.vc.data;
7071 ctx->objmask = NULL;
7072 /* Copy the headers to the buffer. */
7073 action_decap_data = ctx->object;
7074 *action_decap_data = (struct action_raw_decap_data) {
7075 .conf = (struct rte_flow_action_raw_decap){
7076 .data = action_decap_data->data,
7080 header = action_decap_data->data;
7081 if (mplsoudp_decap_conf.select_vlan)
7082 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7083 else if (mplsoudp_encap_conf.select_ipv4)
7084 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7086 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7087 memcpy(eth.dst.addr_bytes,
7088 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7089 memcpy(eth.src.addr_bytes,
7090 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7091 memcpy(header, ð, sizeof(eth));
7092 header += sizeof(eth);
7093 if (mplsoudp_encap_conf.select_vlan) {
7094 if (mplsoudp_encap_conf.select_ipv4)
7095 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7097 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7098 memcpy(header, &vlan, sizeof(vlan));
7099 header += sizeof(vlan);
7101 if (mplsoudp_encap_conf.select_ipv4) {
7102 memcpy(header, &ipv4, sizeof(ipv4));
7103 header += sizeof(ipv4);
7105 memcpy(header, &ipv6, sizeof(ipv6));
7106 header += sizeof(ipv6);
7108 memcpy(header, &udp, sizeof(udp));
7109 header += sizeof(udp);
7110 memset(&mpls, 0, sizeof(mpls));
7111 memcpy(header, &mpls, sizeof(mpls));
7112 header += sizeof(mpls);
7113 action_decap_data->conf.size = header -
7114 action_decap_data->data;
7115 action->conf = &action_decap_data->conf;
7120 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
7121 const char *str, unsigned int len, void *buf,
7124 struct action_raw_decap_data *action_raw_decap_data;
7125 struct rte_flow_action *action;
7126 const struct arg *arg;
7127 struct buffer *out = buf;
7131 RTE_SET_USED(token);
7134 arg = ARGS_ENTRY_ARB_BOUNDED
7135 (offsetof(struct action_raw_decap_data, idx),
7136 sizeof(((struct action_raw_decap_data *)0)->idx),
7137 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7138 if (push_args(ctx, arg))
7140 ret = parse_int(ctx, token, str, len, NULL, 0);
7147 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7148 action_raw_decap_data = ctx->object;
7149 idx = action_raw_decap_data->idx;
7150 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
7151 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
7152 action->conf = &action_raw_decap_data->conf;
7158 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
7159 const char *str, unsigned int len, void *buf,
7162 struct action_raw_encap_data *action_raw_encap_data;
7163 struct rte_flow_action *action;
7164 const struct arg *arg;
7165 struct buffer *out = buf;
7169 RTE_SET_USED(token);
7172 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
7174 arg = ARGS_ENTRY_ARB_BOUNDED
7175 (offsetof(struct action_raw_encap_data, idx),
7176 sizeof(((struct action_raw_encap_data *)0)->idx),
7177 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7178 if (push_args(ctx, arg))
7180 ret = parse_int(ctx, token, str, len, NULL, 0);
7187 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7188 action_raw_encap_data = ctx->object;
7189 idx = action_raw_encap_data->idx;
7190 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
7191 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
7192 action_raw_encap_data->conf.preserve = NULL;
7193 action->conf = &action_raw_encap_data->conf;
7198 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
7199 const char *str, unsigned int len, void *buf,
7202 struct buffer *out = buf;
7203 struct rte_flow_action *action;
7204 struct action_raw_encap_data *action_raw_encap_data = NULL;
7207 ret = parse_vc(ctx, token, str, len, buf, size);
7210 /* Nothing else to do if there is no buffer. */
7213 if (!out->args.vc.actions_n)
7215 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7216 /* Point to selected object. */
7217 ctx->object = out->args.vc.data;
7218 ctx->objmask = NULL;
7219 /* Copy the headers to the buffer. */
7220 action_raw_encap_data = ctx->object;
7221 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
7222 action_raw_encap_data->conf.preserve = NULL;
7223 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
7224 action->conf = &action_raw_encap_data->conf;
7229 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
7230 const char *str, unsigned int len, void *buf,
7233 struct buffer *out = buf;
7234 struct rte_flow_action *action;
7235 struct action_raw_decap_data *action_raw_decap_data = NULL;
7238 ret = parse_vc(ctx, token, str, len, buf, size);
7241 /* Nothing else to do if there is no buffer. */
7244 if (!out->args.vc.actions_n)
7246 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7247 /* Point to selected object. */
7248 ctx->object = out->args.vc.data;
7249 ctx->objmask = NULL;
7250 /* Copy the headers to the buffer. */
7251 action_raw_decap_data = ctx->object;
7252 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
7253 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
7254 action->conf = &action_raw_decap_data->conf;
7259 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
7260 const char *str, unsigned int len, void *buf,
7265 ret = parse_vc(ctx, token, str, len, buf, size);
7268 ret = rte_flow_dynf_metadata_register();
7275 parse_vc_action_sample(struct context *ctx, const struct token *token,
7276 const char *str, unsigned int len, void *buf,
7279 struct buffer *out = buf;
7280 struct rte_flow_action *action;
7281 struct action_sample_data *action_sample_data = NULL;
7282 static struct rte_flow_action end_action = {
7283 RTE_FLOW_ACTION_TYPE_END, 0
7287 ret = parse_vc(ctx, token, str, len, buf, size);
7290 /* Nothing else to do if there is no buffer. */
7293 if (!out->args.vc.actions_n)
7295 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7296 /* Point to selected object. */
7297 ctx->object = out->args.vc.data;
7298 ctx->objmask = NULL;
7299 /* Copy the headers to the buffer. */
7300 action_sample_data = ctx->object;
7301 action_sample_data->conf.actions = &end_action;
7302 action->conf = &action_sample_data->conf;
7307 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
7308 const char *str, unsigned int len, void *buf,
7311 struct action_sample_data *action_sample_data;
7312 struct rte_flow_action *action;
7313 const struct arg *arg;
7314 struct buffer *out = buf;
7318 RTE_SET_USED(token);
7321 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
7323 arg = ARGS_ENTRY_ARB_BOUNDED
7324 (offsetof(struct action_sample_data, idx),
7325 sizeof(((struct action_sample_data *)0)->idx),
7326 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
7327 if (push_args(ctx, arg))
7329 ret = parse_int(ctx, token, str, len, NULL, 0);
7336 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7337 action_sample_data = ctx->object;
7338 idx = action_sample_data->idx;
7339 action_sample_data->conf.actions = raw_sample_confs[idx].data;
7340 action->conf = &action_sample_data->conf;
7344 /** Parse operation for modify_field command. */
7346 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
7347 const char *str, unsigned int len, void *buf,
7350 struct rte_flow_action_modify_field *action_modify_field;
7356 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
7358 for (i = 0; modify_field_ops[i]; ++i)
7359 if (!strcmp_partial(modify_field_ops[i], str, len))
7361 if (!modify_field_ops[i])
7365 action_modify_field = ctx->object;
7366 action_modify_field->operation = (enum rte_flow_modify_op)i;
7370 /** Parse id for modify_field command. */
7372 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
7373 const char *str, unsigned int len, void *buf,
7376 struct rte_flow_action_modify_field *action_modify_field;
7382 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
7383 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
7385 for (i = 0; modify_field_ids[i]; ++i)
7386 if (!strcmp_partial(modify_field_ids[i], str, len))
7388 if (!modify_field_ids[i])
7392 action_modify_field = ctx->object;
7393 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
7394 action_modify_field->dst.field = (enum rte_flow_field_id)i;
7396 action_modify_field->src.field = (enum rte_flow_field_id)i;
7400 /** Parse the conntrack update, not a rte_flow_action. */
7402 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
7403 const char *str, unsigned int len, void *buf,
7406 struct buffer *out = buf;
7407 struct rte_flow_modify_conntrack *ct_modify = NULL;
7410 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
7411 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
7413 /* Token name must match. */
7414 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7416 /* Nothing else to do if there is no buffer. */
7419 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
7420 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
7421 ct_modify->new_ct.is_original_dir =
7422 conntrack_context.is_original_dir;
7423 ct_modify->direction = 1;
7427 old_dir = ct_modify->new_ct.is_original_dir;
7428 memcpy(&ct_modify->new_ct, &conntrack_context,
7429 sizeof(conntrack_context));
7430 ct_modify->new_ct.is_original_dir = old_dir;
7431 ct_modify->state = 1;
7436 /** Parse tokens for destroy command. */
7438 parse_destroy(struct context *ctx, const struct token *token,
7439 const char *str, unsigned int len,
7440 void *buf, unsigned int size)
7442 struct buffer *out = buf;
7444 /* Token name must match. */
7445 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7447 /* Nothing else to do if there is no buffer. */
7450 if (!out->command) {
7451 if (ctx->curr != DESTROY)
7453 if (sizeof(*out) > size)
7455 out->command = ctx->curr;
7458 ctx->objmask = NULL;
7459 out->args.destroy.rule =
7460 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7464 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
7465 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
7468 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
7469 ctx->objmask = NULL;
7473 /** Parse tokens for flush command. */
7475 parse_flush(struct context *ctx, const struct token *token,
7476 const char *str, unsigned int len,
7477 void *buf, unsigned int size)
7479 struct buffer *out = buf;
7481 /* Token name must match. */
7482 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7484 /* Nothing else to do if there is no buffer. */
7487 if (!out->command) {
7488 if (ctx->curr != FLUSH)
7490 if (sizeof(*out) > size)
7492 out->command = ctx->curr;
7495 ctx->objmask = NULL;
7500 /** Parse tokens for dump command. */
7502 parse_dump(struct context *ctx, const struct token *token,
7503 const char *str, unsigned int len,
7504 void *buf, unsigned int size)
7506 struct buffer *out = buf;
7508 /* Token name must match. */
7509 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7511 /* Nothing else to do if there is no buffer. */
7514 if (!out->command) {
7515 if (ctx->curr != DUMP)
7517 if (sizeof(*out) > size)
7519 out->command = ctx->curr;
7522 ctx->objmask = NULL;
7525 switch (ctx->curr) {
7528 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
7529 out->command = ctx->curr;
7532 ctx->objmask = NULL;
7539 /** Parse tokens for query command. */
7541 parse_query(struct context *ctx, const struct token *token,
7542 const char *str, unsigned int len,
7543 void *buf, unsigned int size)
7545 struct buffer *out = buf;
7547 /* Token name must match. */
7548 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7550 /* Nothing else to do if there is no buffer. */
7553 if (!out->command) {
7554 if (ctx->curr != QUERY)
7556 if (sizeof(*out) > size)
7558 out->command = ctx->curr;
7561 ctx->objmask = NULL;
7566 /** Parse action names. */
7568 parse_action(struct context *ctx, const struct token *token,
7569 const char *str, unsigned int len,
7570 void *buf, unsigned int size)
7572 struct buffer *out = buf;
7573 const struct arg *arg = pop_args(ctx);
7577 /* Argument is expected. */
7580 /* Parse action name. */
7581 for (i = 0; next_action[i]; ++i) {
7582 const struct parse_action_priv *priv;
7584 token = &token_list[next_action[i]];
7585 if (strcmp_partial(token->name, str, len))
7591 memcpy((uint8_t *)ctx->object + arg->offset,
7597 push_args(ctx, arg);
7601 /** Parse tokens for list command. */
7603 parse_list(struct context *ctx, const struct token *token,
7604 const char *str, unsigned int len,
7605 void *buf, unsigned int size)
7607 struct buffer *out = buf;
7609 /* Token name must match. */
7610 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7612 /* Nothing else to do if there is no buffer. */
7615 if (!out->command) {
7616 if (ctx->curr != LIST)
7618 if (sizeof(*out) > size)
7620 out->command = ctx->curr;
7623 ctx->objmask = NULL;
7624 out->args.list.group =
7625 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7629 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
7630 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
7633 ctx->object = out->args.list.group + out->args.list.group_n++;
7634 ctx->objmask = NULL;
7638 /** Parse tokens for list all aged flows command. */
7640 parse_aged(struct context *ctx, const struct token *token,
7641 const char *str, unsigned int len,
7642 void *buf, unsigned int size)
7644 struct buffer *out = buf;
7646 /* Token name must match. */
7647 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7649 /* Nothing else to do if there is no buffer. */
7652 if (!out->command) {
7653 if (ctx->curr != AGED)
7655 if (sizeof(*out) > size)
7657 out->command = ctx->curr;
7660 ctx->objmask = NULL;
7662 if (ctx->curr == AGED_DESTROY)
7663 out->args.aged.destroy = 1;
7667 /** Parse tokens for isolate command. */
7669 parse_isolate(struct context *ctx, const struct token *token,
7670 const char *str, unsigned int len,
7671 void *buf, unsigned int size)
7673 struct buffer *out = buf;
7675 /* Token name must match. */
7676 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7678 /* Nothing else to do if there is no buffer. */
7681 if (!out->command) {
7682 if (ctx->curr != ISOLATE)
7684 if (sizeof(*out) > size)
7686 out->command = ctx->curr;
7689 ctx->objmask = NULL;
7695 parse_flex(struct context *ctx, const struct token *token,
7696 const char *str, unsigned int len,
7697 void *buf, unsigned int size)
7699 struct buffer *out = buf;
7701 /* Token name must match. */
7702 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7704 /* Nothing else to do if there is no buffer. */
7707 if (out->command == ZERO) {
7708 if (ctx->curr != FLEX)
7710 if (sizeof(*out) > size)
7712 out->command = ctx->curr;
7715 ctx->objmask = NULL;
7717 switch (ctx->curr) {
7720 case FLEX_ITEM_INIT:
7721 case FLEX_ITEM_CREATE:
7722 case FLEX_ITEM_DESTROY:
7723 out->command = ctx->curr;
7732 parse_tunnel(struct context *ctx, const struct token *token,
7733 const char *str, unsigned int len,
7734 void *buf, unsigned int size)
7736 struct buffer *out = buf;
7738 /* Token name must match. */
7739 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7741 /* Nothing else to do if there is no buffer. */
7744 if (!out->command) {
7745 if (ctx->curr != TUNNEL)
7747 if (sizeof(*out) > size)
7749 out->command = ctx->curr;
7752 ctx->objmask = NULL;
7754 switch (ctx->curr) {
7758 case TUNNEL_DESTROY:
7760 out->command = ctx->curr;
7762 case TUNNEL_CREATE_TYPE:
7763 case TUNNEL_DESTROY_ID:
7764 ctx->object = &out->args.vc.tunnel_ops;
7773 * Parse signed/unsigned integers 8 to 64-bit long.
7775 * Last argument (ctx->args) is retrieved to determine integer type and
7779 parse_int(struct context *ctx, const struct token *token,
7780 const char *str, unsigned int len,
7781 void *buf, unsigned int size)
7783 const struct arg *arg = pop_args(ctx);
7788 /* Argument is expected. */
7793 (uintmax_t)strtoimax(str, &end, 0) :
7794 strtoumax(str, &end, 0);
7795 if (errno || (size_t)(end - str) != len)
7798 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
7799 (intmax_t)u > (intmax_t)arg->max)) ||
7800 (!arg->sign && (u < arg->min || u > arg->max))))
7805 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
7806 !arg_entry_bf_fill(ctx->objmask, -1, arg))
7810 buf = (uint8_t *)ctx->object + arg->offset;
7812 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
7816 case sizeof(uint8_t):
7817 *(uint8_t *)buf = u;
7819 case sizeof(uint16_t):
7820 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
7822 case sizeof(uint8_t [3]):
7823 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7825 ((uint8_t *)buf)[0] = u;
7826 ((uint8_t *)buf)[1] = u >> 8;
7827 ((uint8_t *)buf)[2] = u >> 16;
7831 ((uint8_t *)buf)[0] = u >> 16;
7832 ((uint8_t *)buf)[1] = u >> 8;
7833 ((uint8_t *)buf)[2] = u;
7835 case sizeof(uint32_t):
7836 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
7838 case sizeof(uint64_t):
7839 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
7844 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
7846 buf = (uint8_t *)ctx->objmask + arg->offset;
7851 push_args(ctx, arg);
7858 * Three arguments (ctx->args) are retrieved from the stack to store data,
7859 * its actual length and address (in that order).
7862 parse_string(struct context *ctx, const struct token *token,
7863 const char *str, unsigned int len,
7864 void *buf, unsigned int size)
7866 const struct arg *arg_data = pop_args(ctx);
7867 const struct arg *arg_len = pop_args(ctx);
7868 const struct arg *arg_addr = pop_args(ctx);
7869 char tmp[16]; /* Ought to be enough. */
7872 /* Arguments are expected. */
7876 push_args(ctx, arg_data);
7880 push_args(ctx, arg_len);
7881 push_args(ctx, arg_data);
7884 size = arg_data->size;
7885 /* Bit-mask fill is not supported. */
7886 if (arg_data->mask || size < len)
7890 /* Let parse_int() fill length information first. */
7891 ret = snprintf(tmp, sizeof(tmp), "%u", len);
7894 push_args(ctx, arg_len);
7895 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7900 buf = (uint8_t *)ctx->object + arg_data->offset;
7901 /* Output buffer is not necessarily NUL-terminated. */
7902 memcpy(buf, str, len);
7903 memset((uint8_t *)buf + len, 0x00, size - len);
7905 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7906 /* Save address if requested. */
7907 if (arg_addr->size) {
7908 memcpy((uint8_t *)ctx->object + arg_addr->offset,
7910 (uint8_t *)ctx->object + arg_data->offset
7914 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7916 (uint8_t *)ctx->objmask + arg_data->offset
7922 push_args(ctx, arg_addr);
7923 push_args(ctx, arg_len);
7924 push_args(ctx, arg_data);
7929 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
7931 const uint8_t *head = dst;
7934 /* Check input parameters */
7935 if ((src == NULL) ||
7943 /* Convert chars to bytes */
7945 char tmp[3], *end = tmp;
7946 uint32_t read_lim = left & 1 ? 1 : 2;
7948 snprintf(tmp, read_lim + 1, "%s", src);
7949 *dst = strtoul(tmp, &end, 16);
7952 *size = (uint32_t)(dst - head);
7960 *size = (uint32_t)(dst - head);
7965 parse_hex(struct context *ctx, const struct token *token,
7966 const char *str, unsigned int len,
7967 void *buf, unsigned int size)
7969 const struct arg *arg_data = pop_args(ctx);
7970 const struct arg *arg_len = pop_args(ctx);
7971 const struct arg *arg_addr = pop_args(ctx);
7972 char tmp[16]; /* Ought to be enough. */
7974 unsigned int hexlen = len;
7975 unsigned int length = 256;
7976 uint8_t hex_tmp[length];
7978 /* Arguments are expected. */
7982 push_args(ctx, arg_data);
7986 push_args(ctx, arg_len);
7987 push_args(ctx, arg_data);
7990 size = arg_data->size;
7991 /* Bit-mask fill is not supported. */
7997 /* translate bytes string to array. */
7998 if (str[0] == '0' && ((str[1] == 'x') ||
8003 if (hexlen > length)
8005 ret = parse_hex_string(str, hex_tmp, &hexlen);
8008 /* Check the converted binary fits into data buffer. */
8011 /* Let parse_int() fill length information first. */
8012 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
8015 /* Save length if requested. */
8016 if (arg_len->size) {
8017 push_args(ctx, arg_len);
8018 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
8024 buf = (uint8_t *)ctx->object + arg_data->offset;
8025 /* Output buffer is not necessarily NUL-terminated. */
8026 memcpy(buf, hex_tmp, hexlen);
8027 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
8029 memset((uint8_t *)ctx->objmask + arg_data->offset,
8031 /* Save address if requested. */
8032 if (arg_addr->size) {
8033 memcpy((uint8_t *)ctx->object + arg_addr->offset,
8035 (uint8_t *)ctx->object + arg_data->offset
8039 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
8041 (uint8_t *)ctx->objmask + arg_data->offset
8047 push_args(ctx, arg_addr);
8048 push_args(ctx, arg_len);
8049 push_args(ctx, arg_data);
8055 * Parse a zero-ended string.
8058 parse_string0(struct context *ctx, const struct token *token __rte_unused,
8059 const char *str, unsigned int len,
8060 void *buf, unsigned int size)
8062 const struct arg *arg_data = pop_args(ctx);
8064 /* Arguments are expected. */
8067 size = arg_data->size;
8068 /* Bit-mask fill is not supported. */
8069 if (arg_data->mask || size < len + 1)
8073 buf = (uint8_t *)ctx->object + arg_data->offset;
8074 strncpy(buf, str, len);
8076 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
8079 push_args(ctx, arg_data);
8084 * Parse a MAC address.
8086 * Last argument (ctx->args) is retrieved to determine storage size and
8090 parse_mac_addr(struct context *ctx, const struct token *token,
8091 const char *str, unsigned int len,
8092 void *buf, unsigned int size)
8094 const struct arg *arg = pop_args(ctx);
8095 struct rte_ether_addr tmp;
8099 /* Argument is expected. */
8103 /* Bit-mask fill is not supported. */
8104 if (arg->mask || size != sizeof(tmp))
8106 /* Only network endian is supported. */
8109 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
8110 if (ret < 0 || (unsigned int)ret != len)
8114 buf = (uint8_t *)ctx->object + arg->offset;
8115 memcpy(buf, &tmp, size);
8117 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8120 push_args(ctx, arg);
8125 * Parse an IPv4 address.
8127 * Last argument (ctx->args) is retrieved to determine storage size and
8131 parse_ipv4_addr(struct context *ctx, const struct token *token,
8132 const char *str, unsigned int len,
8133 void *buf, unsigned int size)
8135 const struct arg *arg = pop_args(ctx);
8140 /* Argument is expected. */
8144 /* Bit-mask fill is not supported. */
8145 if (arg->mask || size != sizeof(tmp))
8147 /* Only network endian is supported. */
8150 memcpy(str2, str, len);
8152 ret = inet_pton(AF_INET, str2, &tmp);
8154 /* Attempt integer parsing. */
8155 push_args(ctx, arg);
8156 return parse_int(ctx, token, str, len, buf, size);
8160 buf = (uint8_t *)ctx->object + arg->offset;
8161 memcpy(buf, &tmp, size);
8163 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8166 push_args(ctx, arg);
8171 * Parse an IPv6 address.
8173 * Last argument (ctx->args) is retrieved to determine storage size and
8177 parse_ipv6_addr(struct context *ctx, const struct token *token,
8178 const char *str, unsigned int len,
8179 void *buf, unsigned int size)
8181 const struct arg *arg = pop_args(ctx);
8183 struct in6_addr tmp;
8187 /* Argument is expected. */
8191 /* Bit-mask fill is not supported. */
8192 if (arg->mask || size != sizeof(tmp))
8194 /* Only network endian is supported. */
8197 memcpy(str2, str, len);
8199 ret = inet_pton(AF_INET6, str2, &tmp);
8204 buf = (uint8_t *)ctx->object + arg->offset;
8205 memcpy(buf, &tmp, size);
8207 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8210 push_args(ctx, arg);
8214 /** Boolean values (even indices stand for false). */
8215 static const char *const boolean_name[] = {
8225 * Parse a boolean value.
8227 * Last argument (ctx->args) is retrieved to determine storage size and
8231 parse_boolean(struct context *ctx, const struct token *token,
8232 const char *str, unsigned int len,
8233 void *buf, unsigned int size)
8235 const struct arg *arg = pop_args(ctx);
8239 /* Argument is expected. */
8242 for (i = 0; boolean_name[i]; ++i)
8243 if (!strcmp_partial(boolean_name[i], str, len))
8245 /* Process token as integer. */
8246 if (boolean_name[i])
8247 str = i & 1 ? "1" : "0";
8248 push_args(ctx, arg);
8249 ret = parse_int(ctx, token, str, strlen(str), buf, size);
8250 return ret > 0 ? (int)len : ret;
8253 /** Parse port and update context. */
8255 parse_port(struct context *ctx, const struct token *token,
8256 const char *str, unsigned int len,
8257 void *buf, unsigned int size)
8259 struct buffer *out = &(struct buffer){ .port = 0 };
8267 ctx->objmask = NULL;
8268 size = sizeof(*out);
8270 ret = parse_int(ctx, token, str, len, out, size);
8272 ctx->port = out->port;
8279 parse_ia_id2ptr(struct context *ctx, const struct token *token,
8280 const char *str, unsigned int len,
8281 void *buf, unsigned int size)
8283 struct rte_flow_action *action = ctx->object;
8291 ctx->objmask = NULL;
8292 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
8293 ctx->object = action;
8294 if (ret != (int)len)
8296 /* set indirect action */
8298 action->conf = port_action_handle_get_by_id(ctx->port, id);
8299 ret = (action->conf) ? ret : -1;
8304 /** Parse set command, initialize output buffer for subsequent tokens. */
8306 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
8307 const char *str, unsigned int len,
8308 void *buf, unsigned int size)
8310 struct buffer *out = buf;
8312 /* Token name must match. */
8313 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8315 /* Nothing else to do if there is no buffer. */
8318 /* Make sure buffer is large enough. */
8319 if (size < sizeof(*out))
8322 ctx->objmask = NULL;
8326 out->command = ctx->curr;
8327 /* For encap/decap we need is pattern */
8328 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8333 /** Parse set command, initialize output buffer for subsequent tokens. */
8335 parse_set_sample_action(struct context *ctx, const struct token *token,
8336 const char *str, unsigned int len,
8337 void *buf, unsigned int size)
8339 struct buffer *out = buf;
8341 /* Token name must match. */
8342 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8344 /* Nothing else to do if there is no buffer. */
8347 /* Make sure buffer is large enough. */
8348 if (size < sizeof(*out))
8351 ctx->objmask = NULL;
8355 out->command = ctx->curr;
8356 /* For sampler we need is actions */
8357 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8363 * Parse set raw_encap/raw_decap command,
8364 * initialize output buffer for subsequent tokens.
8367 parse_set_init(struct context *ctx, const struct token *token,
8368 const char *str, unsigned int len,
8369 void *buf, unsigned int size)
8371 struct buffer *out = buf;
8373 /* Token name must match. */
8374 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8376 /* Nothing else to do if there is no buffer. */
8379 /* Make sure buffer is large enough. */
8380 if (size < sizeof(*out))
8382 /* Initialize buffer. */
8383 memset(out, 0x00, sizeof(*out));
8384 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8387 ctx->objmask = NULL;
8388 if (!out->command) {
8389 if (ctx->curr != SET)
8391 if (sizeof(*out) > size)
8393 out->command = ctx->curr;
8394 out->args.vc.data = (uint8_t *)out + size;
8395 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8402 * Replace testpmd handles in a flex flow item with real values.
8405 parse_flex_handle(struct context *ctx, const struct token *token,
8406 const char *str, unsigned int len,
8407 void *buf, unsigned int size)
8409 struct rte_flow_item_flex *spec, *mask;
8410 const struct rte_flow_item_flex *src_spec, *src_mask;
8411 const struct arg *arg = pop_args(ctx);
8417 printf("Bad environment\n");
8420 offset = arg->offset;
8421 push_args(ctx, arg);
8422 ret = parse_int(ctx, token, str, len, buf, size);
8423 if (ret <= 0 || !ctx->object)
8425 if (ctx->port >= RTE_MAX_ETHPORTS) {
8426 printf("Bad port\n");
8429 if (offset == offsetof(struct rte_flow_item_flex, handle)) {
8430 const struct flex_item *fp;
8431 struct rte_flow_item_flex *item_flex = ctx->object;
8432 handle = (uint16_t)(uintptr_t)item_flex->handle;
8433 if (handle >= FLEX_MAX_PARSERS_NUM) {
8434 printf("Bad flex item handle\n");
8437 fp = flex_items[ctx->port][handle];
8439 printf("Bad flex item handle\n");
8442 item_flex->handle = fp->flex_handle;
8443 } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
8444 handle = (uint16_t)(uintptr_t)
8445 ((struct rte_flow_item_flex *)ctx->object)->pattern;
8446 if (handle >= FLEX_MAX_PATTERNS_NUM) {
8447 printf("Bad pattern handle\n");
8450 src_spec = &flex_patterns[handle].spec;
8451 src_mask = &flex_patterns[handle].mask;
8453 mask = spec + 2; /* spec, last, mask */
8454 /* fill flow rule spec and mask parameters */
8455 spec->length = src_spec->length;
8456 spec->pattern = src_spec->pattern;
8457 mask->length = src_mask->length;
8458 mask->pattern = src_mask->pattern;
8460 printf("Bad arguments - unknown flex item offset\n");
8466 /** No completion. */
8468 comp_none(struct context *ctx, const struct token *token,
8469 unsigned int ent, char *buf, unsigned int size)
8479 /** Complete boolean values. */
8481 comp_boolean(struct context *ctx, const struct token *token,
8482 unsigned int ent, char *buf, unsigned int size)
8488 for (i = 0; boolean_name[i]; ++i)
8489 if (buf && i == ent)
8490 return strlcpy(buf, boolean_name[i], size);
8496 /** Complete action names. */
8498 comp_action(struct context *ctx, const struct token *token,
8499 unsigned int ent, char *buf, unsigned int size)
8505 for (i = 0; next_action[i]; ++i)
8506 if (buf && i == ent)
8507 return strlcpy(buf, token_list[next_action[i]].name,
8514 /** Complete available ports. */
8516 comp_port(struct context *ctx, const struct token *token,
8517 unsigned int ent, char *buf, unsigned int size)
8524 RTE_ETH_FOREACH_DEV(p) {
8525 if (buf && i == ent)
8526 return snprintf(buf, size, "%u", p);
8534 /** Complete available rule IDs. */
8536 comp_rule_id(struct context *ctx, const struct token *token,
8537 unsigned int ent, char *buf, unsigned int size)
8540 struct rte_port *port;
8541 struct port_flow *pf;
8544 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
8545 ctx->port == (portid_t)RTE_PORT_ALL)
8547 port = &ports[ctx->port];
8548 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
8549 if (buf && i == ent)
8550 return snprintf(buf, size, "%u", pf->id);
8558 /** Complete type field for RSS action. */
8560 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
8561 unsigned int ent, char *buf, unsigned int size)
8567 for (i = 0; rss_type_table[i].str; ++i)
8572 return strlcpy(buf, rss_type_table[ent].str, size);
8574 return snprintf(buf, size, "end");
8578 /** Complete queue field for RSS action. */
8580 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
8581 unsigned int ent, char *buf, unsigned int size)
8588 return snprintf(buf, size, "%u", ent);
8590 return snprintf(buf, size, "end");
8594 /** Complete index number for set raw_encap/raw_decap commands. */
8596 comp_set_raw_index(struct context *ctx, const struct token *token,
8597 unsigned int ent, char *buf, unsigned int size)
8603 RTE_SET_USED(token);
8604 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
8605 if (buf && idx == ent)
8606 return snprintf(buf, size, "%u", idx);
8612 /** Complete index number for set raw_encap/raw_decap commands. */
8614 comp_set_sample_index(struct context *ctx, const struct token *token,
8615 unsigned int ent, char *buf, unsigned int size)
8621 RTE_SET_USED(token);
8622 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
8623 if (buf && idx == ent)
8624 return snprintf(buf, size, "%u", idx);
8630 /** Complete operation for modify_field command. */
8632 comp_set_modify_field_op(struct context *ctx, const struct token *token,
8633 unsigned int ent, char *buf, unsigned int size)
8636 RTE_SET_USED(token);
8638 return RTE_DIM(modify_field_ops);
8639 if (ent < RTE_DIM(modify_field_ops) - 1)
8640 return strlcpy(buf, modify_field_ops[ent], size);
8644 /** Complete field id for modify_field command. */
8646 comp_set_modify_field_id(struct context *ctx, const struct token *token,
8647 unsigned int ent, char *buf, unsigned int size)
8651 RTE_SET_USED(token);
8653 return RTE_DIM(modify_field_ids);
8654 if (ent >= RTE_DIM(modify_field_ids) - 1)
8656 name = modify_field_ids[ent];
8657 if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
8658 (strcmp(name, "pointer") && strcmp(name, "value")))
8659 return strlcpy(buf, name, size);
8663 /** Internal context. */
8664 static struct context cmd_flow_context;
8666 /** Global parser instance (cmdline API). */
8667 cmdline_parse_inst_t cmd_flow;
8668 cmdline_parse_inst_t cmd_set_raw;
8670 /** Initialize context. */
8672 cmd_flow_context_init(struct context *ctx)
8674 /* A full memset() is not necessary. */
8684 ctx->objmask = NULL;
8687 /** Parse a token (cmdline API). */
8689 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
8692 struct context *ctx = &cmd_flow_context;
8693 const struct token *token;
8694 const enum index *list;
8699 token = &token_list[ctx->curr];
8700 /* Check argument length. */
8703 for (len = 0; src[len]; ++len)
8704 if (src[len] == '#' || isspace(src[len]))
8708 /* Last argument and EOL detection. */
8709 for (i = len; src[i]; ++i)
8710 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
8712 else if (!isspace(src[i])) {
8717 if (src[i] == '\r' || src[i] == '\n') {
8721 /* Initialize context if necessary. */
8722 if (!ctx->next_num) {
8725 ctx->next[ctx->next_num++] = token->next[0];
8727 /* Process argument through candidates. */
8728 ctx->prev = ctx->curr;
8729 list = ctx->next[ctx->next_num - 1];
8730 for (i = 0; list[i]; ++i) {
8731 const struct token *next = &token_list[list[i]];
8734 ctx->curr = list[i];
8736 tmp = next->call(ctx, next, src, len, result, size);
8738 tmp = parse_default(ctx, next, src, len, result, size);
8739 if (tmp == -1 || tmp != len)
8747 /* Push subsequent tokens if any. */
8749 for (i = 0; token->next[i]; ++i) {
8750 if (ctx->next_num == RTE_DIM(ctx->next))
8752 ctx->next[ctx->next_num++] = token->next[i];
8754 /* Push arguments if any. */
8756 for (i = 0; token->args[i]; ++i) {
8757 if (ctx->args_num == RTE_DIM(ctx->args))
8759 ctx->args[ctx->args_num++] = token->args[i];
8765 flow_parse(const char *src, void *result, unsigned int size,
8766 struct rte_flow_attr **attr,
8767 struct rte_flow_item **pattern, struct rte_flow_action **actions)
8770 struct context saved_flow_ctx = cmd_flow_context;
8772 cmd_flow_context_init(&cmd_flow_context);
8774 ret = cmd_flow_parse(NULL, src, result, size);
8777 while (isspace(*src))
8780 } while (ret > 0 && strlen(src));
8781 cmd_flow_context = saved_flow_ctx;
8782 *attr = &((struct buffer *)result)->args.vc.attr;
8783 *pattern = ((struct buffer *)result)->args.vc.pattern;
8784 *actions = ((struct buffer *)result)->args.vc.actions;
8785 return (ret >= 0 && !strlen(src)) ? 0 : -1;
8788 /** Return number of completion entries (cmdline API). */
8790 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
8792 struct context *ctx = &cmd_flow_context;
8793 const struct token *token = &token_list[ctx->curr];
8794 const enum index *list;
8798 /* Count number of tokens in current list. */
8800 list = ctx->next[ctx->next_num - 1];
8802 list = token->next[0];
8803 for (i = 0; list[i]; ++i)
8808 * If there is a single token, use its completion callback, otherwise
8809 * return the number of entries.
8811 token = &token_list[list[0]];
8812 if (i == 1 && token->comp) {
8813 /* Save index for cmd_flow_get_help(). */
8814 ctx->prev = list[0];
8815 return token->comp(ctx, token, 0, NULL, 0);
8820 /** Return a completion entry (cmdline API). */
8822 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
8823 char *dst, unsigned int size)
8825 struct context *ctx = &cmd_flow_context;
8826 const struct token *token = &token_list[ctx->curr];
8827 const enum index *list;
8831 /* Count number of tokens in current list. */
8833 list = ctx->next[ctx->next_num - 1];
8835 list = token->next[0];
8836 for (i = 0; list[i]; ++i)
8840 /* If there is a single token, use its completion callback. */
8841 token = &token_list[list[0]];
8842 if (i == 1 && token->comp) {
8843 /* Save index for cmd_flow_get_help(). */
8844 ctx->prev = list[0];
8845 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
8847 /* Otherwise make sure the index is valid and use defaults. */
8850 token = &token_list[list[index]];
8851 strlcpy(dst, token->name, size);
8852 /* Save index for cmd_flow_get_help(). */
8853 ctx->prev = list[index];
8857 /** Populate help strings for current token (cmdline API). */
8859 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
8861 struct context *ctx = &cmd_flow_context;
8862 const struct token *token = &token_list[ctx->prev];
8867 /* Set token type and update global help with details. */
8868 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
8870 cmd_flow.help_str = token->help;
8872 cmd_flow.help_str = token->name;
8876 /** Token definition template (cmdline API). */
8877 static struct cmdline_token_hdr cmd_flow_token_hdr = {
8878 .ops = &(struct cmdline_token_ops){
8879 .parse = cmd_flow_parse,
8880 .complete_get_nb = cmd_flow_complete_get_nb,
8881 .complete_get_elt = cmd_flow_complete_get_elt,
8882 .get_help = cmd_flow_get_help,
8887 /** Populate the next dynamic token. */
8889 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
8890 cmdline_parse_token_hdr_t **hdr_inst)
8892 struct context *ctx = &cmd_flow_context;
8894 /* Always reinitialize context before requesting the first token. */
8895 if (!(hdr_inst - cmd_flow.tokens))
8896 cmd_flow_context_init(ctx);
8897 /* Return NULL when no more tokens are expected. */
8898 if (!ctx->next_num && ctx->curr) {
8902 /* Determine if command should end here. */
8903 if (ctx->eol && ctx->last && ctx->next_num) {
8904 const enum index *list = ctx->next[ctx->next_num - 1];
8907 for (i = 0; list[i]; ++i) {
8914 *hdr = &cmd_flow_token_hdr;
8917 /** Dispatch parsed buffer to function calls. */
8919 cmd_flow_parsed(const struct buffer *in)
8921 switch (in->command) {
8922 case INDIRECT_ACTION_CREATE:
8923 port_action_handle_create(
8924 in->port, in->args.vc.attr.group,
8925 &((const struct rte_flow_indir_action_conf) {
8926 .ingress = in->args.vc.attr.ingress,
8927 .egress = in->args.vc.attr.egress,
8928 .transfer = in->args.vc.attr.transfer,
8930 in->args.vc.actions);
8932 case INDIRECT_ACTION_DESTROY:
8933 port_action_handle_destroy(in->port,
8934 in->args.ia_destroy.action_id_n,
8935 in->args.ia_destroy.action_id);
8937 case INDIRECT_ACTION_UPDATE:
8938 port_action_handle_update(in->port, in->args.vc.attr.group,
8939 in->args.vc.actions);
8941 case INDIRECT_ACTION_QUERY:
8942 port_action_handle_query(in->port, in->args.ia.action_id);
8945 port_flow_validate(in->port, &in->args.vc.attr,
8946 in->args.vc.pattern, in->args.vc.actions,
8947 &in->args.vc.tunnel_ops);
8950 port_flow_create(in->port, &in->args.vc.attr,
8951 in->args.vc.pattern, in->args.vc.actions,
8952 &in->args.vc.tunnel_ops);
8955 port_flow_destroy(in->port, in->args.destroy.rule_n,
8956 in->args.destroy.rule);
8959 port_flow_flush(in->port);
8963 port_flow_dump(in->port, in->args.dump.mode,
8964 in->args.dump.rule, in->args.dump.file);
8967 port_flow_query(in->port, in->args.query.rule,
8968 &in->args.query.action);
8971 port_flow_list(in->port, in->args.list.group_n,
8972 in->args.list.group);
8975 port_flow_isolate(in->port, in->args.isolate.set);
8978 port_flow_aged(in->port, in->args.aged.destroy);
8981 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
8983 case TUNNEL_DESTROY:
8984 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
8987 port_flow_tunnel_list(in->port);
8990 port_meter_policy_add(in->port, in->args.policy.policy_id,
8991 in->args.vc.actions);
8993 case FLEX_ITEM_CREATE:
8994 flex_item_create(in->port, in->args.flex.token,
8995 in->args.flex.filename);
8997 case FLEX_ITEM_DESTROY:
8998 flex_item_destroy(in->port, in->args.flex.token);
9005 /** Token generator and output processing callback (cmdline API). */
9007 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
9010 cmd_flow_tok(arg0, arg2);
9012 cmd_flow_parsed(arg0);
9015 /** Global parser instance (cmdline API). */
9016 cmdline_parse_inst_t cmd_flow = {
9018 .data = NULL, /**< Unused. */
9019 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
9022 }, /**< Tokens are returned by cmd_flow_tok(). */
9025 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
9028 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
9030 struct rte_ipv4_hdr *ipv4;
9031 struct rte_ether_hdr *eth;
9032 struct rte_ipv6_hdr *ipv6;
9033 struct rte_vxlan_hdr *vxlan;
9034 struct rte_vxlan_gpe_hdr *gpe;
9035 struct rte_flow_item_nvgre *nvgre;
9036 uint32_t ipv6_vtc_flow;
9038 switch (item->type) {
9039 case RTE_FLOW_ITEM_TYPE_ETH:
9040 eth = (struct rte_ether_hdr *)buf;
9042 eth->ether_type = rte_cpu_to_be_16(next_proto);
9044 case RTE_FLOW_ITEM_TYPE_IPV4:
9045 ipv4 = (struct rte_ipv4_hdr *)buf;
9046 if (!ipv4->version_ihl)
9047 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
9048 if (next_proto && ipv4->next_proto_id == 0)
9049 ipv4->next_proto_id = (uint8_t)next_proto;
9051 case RTE_FLOW_ITEM_TYPE_IPV6:
9052 ipv6 = (struct rte_ipv6_hdr *)buf;
9053 if (next_proto && ipv6->proto == 0)
9054 ipv6->proto = (uint8_t)next_proto;
9055 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
9056 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
9057 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
9058 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
9060 case RTE_FLOW_ITEM_TYPE_VXLAN:
9061 vxlan = (struct rte_vxlan_hdr *)buf;
9062 vxlan->vx_flags = 0x08;
9064 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9065 gpe = (struct rte_vxlan_gpe_hdr *)buf;
9066 gpe->vx_flags = 0x0C;
9068 case RTE_FLOW_ITEM_TYPE_NVGRE:
9069 nvgre = (struct rte_flow_item_nvgre *)buf;
9070 nvgre->protocol = rte_cpu_to_be_16(0x6558);
9071 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
9078 /** Helper of get item's default mask. */
9080 flow_item_default_mask(const struct rte_flow_item *item)
9082 const void *mask = NULL;
9083 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
9085 switch (item->type) {
9086 case RTE_FLOW_ITEM_TYPE_ANY:
9087 mask = &rte_flow_item_any_mask;
9089 case RTE_FLOW_ITEM_TYPE_VF:
9090 mask = &rte_flow_item_vf_mask;
9092 case RTE_FLOW_ITEM_TYPE_PORT_ID:
9093 mask = &rte_flow_item_port_id_mask;
9095 case RTE_FLOW_ITEM_TYPE_RAW:
9096 mask = &rte_flow_item_raw_mask;
9098 case RTE_FLOW_ITEM_TYPE_ETH:
9099 mask = &rte_flow_item_eth_mask;
9101 case RTE_FLOW_ITEM_TYPE_VLAN:
9102 mask = &rte_flow_item_vlan_mask;
9104 case RTE_FLOW_ITEM_TYPE_IPV4:
9105 mask = &rte_flow_item_ipv4_mask;
9107 case RTE_FLOW_ITEM_TYPE_IPV6:
9108 mask = &rte_flow_item_ipv6_mask;
9110 case RTE_FLOW_ITEM_TYPE_ICMP:
9111 mask = &rte_flow_item_icmp_mask;
9113 case RTE_FLOW_ITEM_TYPE_UDP:
9114 mask = &rte_flow_item_udp_mask;
9116 case RTE_FLOW_ITEM_TYPE_TCP:
9117 mask = &rte_flow_item_tcp_mask;
9119 case RTE_FLOW_ITEM_TYPE_SCTP:
9120 mask = &rte_flow_item_sctp_mask;
9122 case RTE_FLOW_ITEM_TYPE_VXLAN:
9123 mask = &rte_flow_item_vxlan_mask;
9125 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9126 mask = &rte_flow_item_vxlan_gpe_mask;
9128 case RTE_FLOW_ITEM_TYPE_E_TAG:
9129 mask = &rte_flow_item_e_tag_mask;
9131 case RTE_FLOW_ITEM_TYPE_NVGRE:
9132 mask = &rte_flow_item_nvgre_mask;
9134 case RTE_FLOW_ITEM_TYPE_MPLS:
9135 mask = &rte_flow_item_mpls_mask;
9137 case RTE_FLOW_ITEM_TYPE_GRE:
9138 mask = &rte_flow_item_gre_mask;
9140 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
9141 mask = &gre_key_default_mask;
9143 case RTE_FLOW_ITEM_TYPE_META:
9144 mask = &rte_flow_item_meta_mask;
9146 case RTE_FLOW_ITEM_TYPE_FUZZY:
9147 mask = &rte_flow_item_fuzzy_mask;
9149 case RTE_FLOW_ITEM_TYPE_GTP:
9150 mask = &rte_flow_item_gtp_mask;
9152 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
9153 mask = &rte_flow_item_gtp_psc_mask;
9155 case RTE_FLOW_ITEM_TYPE_GENEVE:
9156 mask = &rte_flow_item_geneve_mask;
9158 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
9159 mask = &rte_flow_item_geneve_opt_mask;
9161 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
9162 mask = &rte_flow_item_pppoe_proto_id_mask;
9164 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
9165 mask = &rte_flow_item_l2tpv3oip_mask;
9167 case RTE_FLOW_ITEM_TYPE_ESP:
9168 mask = &rte_flow_item_esp_mask;
9170 case RTE_FLOW_ITEM_TYPE_AH:
9171 mask = &rte_flow_item_ah_mask;
9173 case RTE_FLOW_ITEM_TYPE_PFCP:
9174 mask = &rte_flow_item_pfcp_mask;
9176 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
9177 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
9178 mask = &rte_flow_item_ethdev_mask;
9180 case RTE_FLOW_ITEM_TYPE_L2TPV2:
9181 mask = &rte_flow_item_l2tpv2_mask;
9183 case RTE_FLOW_ITEM_TYPE_PPP:
9184 mask = &rte_flow_item_ppp_mask;
9192 /** Dispatch parsed buffer to function calls. */
9194 cmd_set_raw_parsed_sample(const struct buffer *in)
9196 uint32_t n = in->args.vc.actions_n;
9198 struct rte_flow_action *action = NULL;
9199 struct rte_flow_action *data = NULL;
9200 const struct rte_flow_action_rss *rss = NULL;
9202 uint16_t idx = in->port; /* We borrow port field as index */
9203 uint32_t max_size = sizeof(struct rte_flow_action) *
9204 ACTION_SAMPLE_ACTIONS_NUM;
9206 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
9207 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
9208 memset(data, 0x00, max_size);
9209 for (; i <= n - 1; i++) {
9210 action = in->args.vc.actions + i;
9211 if (action->type == RTE_FLOW_ACTION_TYPE_END)
9213 switch (action->type) {
9214 case RTE_FLOW_ACTION_TYPE_MARK:
9215 size = sizeof(struct rte_flow_action_mark);
9216 rte_memcpy(&sample_mark[idx],
9217 (const void *)action->conf, size);
9218 action->conf = &sample_mark[idx];
9220 case RTE_FLOW_ACTION_TYPE_COUNT:
9221 size = sizeof(struct rte_flow_action_count);
9222 rte_memcpy(&sample_count[idx],
9223 (const void *)action->conf, size);
9224 action->conf = &sample_count[idx];
9226 case RTE_FLOW_ACTION_TYPE_QUEUE:
9227 size = sizeof(struct rte_flow_action_queue);
9228 rte_memcpy(&sample_queue[idx],
9229 (const void *)action->conf, size);
9230 action->conf = &sample_queue[idx];
9232 case RTE_FLOW_ACTION_TYPE_RSS:
9233 size = sizeof(struct rte_flow_action_rss);
9235 rte_memcpy(&sample_rss_data[idx].conf,
9236 (const void *)rss, size);
9237 if (rss->key_len && rss->key) {
9238 sample_rss_data[idx].conf.key =
9239 sample_rss_data[idx].key;
9240 rte_memcpy((void *)((uintptr_t)
9241 sample_rss_data[idx].conf.key),
9242 (const void *)rss->key,
9243 sizeof(uint8_t) * rss->key_len);
9245 if (rss->queue_num && rss->queue) {
9246 sample_rss_data[idx].conf.queue =
9247 sample_rss_data[idx].queue;
9248 rte_memcpy((void *)((uintptr_t)
9249 sample_rss_data[idx].conf.queue),
9250 (const void *)rss->queue,
9251 sizeof(uint16_t) * rss->queue_num);
9253 action->conf = &sample_rss_data[idx].conf;
9255 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
9256 size = sizeof(struct rte_flow_action_raw_encap);
9257 rte_memcpy(&sample_encap[idx],
9258 (const void *)action->conf, size);
9259 action->conf = &sample_encap[idx];
9261 case RTE_FLOW_ACTION_TYPE_PORT_ID:
9262 size = sizeof(struct rte_flow_action_port_id);
9263 rte_memcpy(&sample_port_id[idx],
9264 (const void *)action->conf, size);
9265 action->conf = &sample_port_id[idx];
9267 case RTE_FLOW_ACTION_TYPE_PF:
9269 case RTE_FLOW_ACTION_TYPE_VF:
9270 size = sizeof(struct rte_flow_action_vf);
9271 rte_memcpy(&sample_vf[idx],
9272 (const void *)action->conf, size);
9273 action->conf = &sample_vf[idx];
9275 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
9276 size = sizeof(struct rte_flow_action_vxlan_encap);
9277 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
9278 action->conf = &sample_vxlan_encap[idx].conf;
9280 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
9281 size = sizeof(struct rte_flow_action_nvgre_encap);
9282 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
9283 action->conf = &sample_nvgre_encap[idx];
9286 fprintf(stderr, "Error - Not supported action\n");
9289 rte_memcpy(data, action, sizeof(struct rte_flow_action));
9294 /** Dispatch parsed buffer to function calls. */
9296 cmd_set_raw_parsed(const struct buffer *in)
9298 uint32_t n = in->args.vc.pattern_n;
9300 struct rte_flow_item *item = NULL;
9302 uint8_t *data = NULL;
9303 uint8_t *data_tail = NULL;
9304 size_t *total_size = NULL;
9305 uint16_t upper_layer = 0;
9307 uint16_t idx = in->port; /* We borrow port field as index */
9308 int gtp_psc = -1; /* GTP PSC option index. */
9310 if (in->command == SET_SAMPLE_ACTIONS)
9311 return cmd_set_raw_parsed_sample(in);
9312 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
9313 in->command == SET_RAW_DECAP);
9314 if (in->command == SET_RAW_ENCAP) {
9315 total_size = &raw_encap_confs[idx].size;
9316 data = (uint8_t *)&raw_encap_confs[idx].data;
9318 total_size = &raw_decap_confs[idx].size;
9319 data = (uint8_t *)&raw_decap_confs[idx].data;
9322 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
9323 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
9324 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
9325 for (i = n - 1 ; i >= 0; --i) {
9326 const struct rte_flow_item_gtp *gtp;
9327 const struct rte_flow_item_geneve_opt *opt;
9329 item = in->args.vc.pattern + i;
9330 if (item->spec == NULL)
9331 item->spec = flow_item_default_mask(item);
9332 switch (item->type) {
9333 case RTE_FLOW_ITEM_TYPE_ETH:
9334 size = sizeof(struct rte_ether_hdr);
9336 case RTE_FLOW_ITEM_TYPE_VLAN:
9337 size = sizeof(struct rte_vlan_hdr);
9338 proto = RTE_ETHER_TYPE_VLAN;
9340 case RTE_FLOW_ITEM_TYPE_IPV4:
9341 size = sizeof(struct rte_ipv4_hdr);
9342 proto = RTE_ETHER_TYPE_IPV4;
9344 case RTE_FLOW_ITEM_TYPE_IPV6:
9345 size = sizeof(struct rte_ipv6_hdr);
9346 proto = RTE_ETHER_TYPE_IPV6;
9348 case RTE_FLOW_ITEM_TYPE_UDP:
9349 size = sizeof(struct rte_udp_hdr);
9352 case RTE_FLOW_ITEM_TYPE_TCP:
9353 size = sizeof(struct rte_tcp_hdr);
9356 case RTE_FLOW_ITEM_TYPE_VXLAN:
9357 size = sizeof(struct rte_vxlan_hdr);
9359 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9360 size = sizeof(struct rte_vxlan_gpe_hdr);
9362 case RTE_FLOW_ITEM_TYPE_GRE:
9363 size = sizeof(struct rte_gre_hdr);
9366 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
9367 size = sizeof(rte_be32_t);
9370 case RTE_FLOW_ITEM_TYPE_MPLS:
9371 size = sizeof(struct rte_mpls_hdr);
9374 case RTE_FLOW_ITEM_TYPE_NVGRE:
9375 size = sizeof(struct rte_flow_item_nvgre);
9378 case RTE_FLOW_ITEM_TYPE_GENEVE:
9379 size = sizeof(struct rte_geneve_hdr);
9381 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
9382 opt = (const struct rte_flow_item_geneve_opt *)
9384 size = offsetof(struct rte_flow_item_geneve_opt, data);
9385 if (opt->option_len && opt->data) {
9386 *total_size += opt->option_len *
9388 rte_memcpy(data_tail - (*total_size),
9390 opt->option_len * sizeof(uint32_t));
9393 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
9394 size = sizeof(rte_be32_t);
9397 case RTE_FLOW_ITEM_TYPE_ESP:
9398 size = sizeof(struct rte_esp_hdr);
9401 case RTE_FLOW_ITEM_TYPE_AH:
9402 size = sizeof(struct rte_flow_item_ah);
9405 case RTE_FLOW_ITEM_TYPE_GTP:
9407 size = sizeof(struct rte_gtp_hdr);
9410 if (gtp_psc != i + 1) {
9412 "Error - GTP PSC does not follow GTP\n");
9416 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
9417 /* Only E flag should be set. */
9419 "Error - GTP unsupported flags\n");
9422 struct rte_gtp_hdr_ext_word ext_word = {
9426 /* We have to add GTP header extra word. */
9427 *total_size += sizeof(ext_word);
9428 rte_memcpy(data_tail - (*total_size),
9429 &ext_word, sizeof(ext_word));
9431 size = sizeof(struct rte_gtp_hdr);
9433 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
9436 "Error - Multiple GTP PSC items\n");
9439 const struct rte_flow_item_gtp_psc
9447 psc.len = sizeof(psc) / 4;
9448 psc.pdu_type = opt->hdr.type;
9449 psc.qfi = opt->hdr.qfi;
9451 *total_size += sizeof(psc);
9452 rte_memcpy(data_tail - (*total_size),
9458 case RTE_FLOW_ITEM_TYPE_PFCP:
9459 size = sizeof(struct rte_flow_item_pfcp);
9461 case RTE_FLOW_ITEM_TYPE_FLEX:
9463 ((const struct rte_flow_item_flex *)
9464 item->spec)->length : 0;
9467 fprintf(stderr, "Error - Not supported item\n");
9470 *total_size += size;
9471 rte_memcpy(data_tail - (*total_size), item->spec, size);
9472 /* update some fields which cannot be set by cmdline */
9473 update_fields((data_tail - (*total_size)), item,
9475 upper_layer = proto;
9477 if (verbose_level & 0x1)
9478 printf("total data size is %zu\n", (*total_size));
9479 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
9480 memmove(data, (data_tail - (*total_size)), *total_size);
9485 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
9488 /** Populate help strings for current token (cmdline API). */
9490 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
9493 struct context *ctx = &cmd_flow_context;
9494 const struct token *token = &token_list[ctx->prev];
9499 /* Set token type and update global help with details. */
9500 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
9502 cmd_set_raw.help_str = token->help;
9504 cmd_set_raw.help_str = token->name;
9508 /** Token definition template (cmdline API). */
9509 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
9510 .ops = &(struct cmdline_token_ops){
9511 .parse = cmd_flow_parse,
9512 .complete_get_nb = cmd_flow_complete_get_nb,
9513 .complete_get_elt = cmd_flow_complete_get_elt,
9514 .get_help = cmd_set_raw_get_help,
9519 /** Populate the next dynamic token. */
9521 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
9522 cmdline_parse_token_hdr_t **hdr_inst)
9524 struct context *ctx = &cmd_flow_context;
9526 /* Always reinitialize context before requesting the first token. */
9527 if (!(hdr_inst - cmd_set_raw.tokens)) {
9528 cmd_flow_context_init(ctx);
9529 ctx->curr = START_SET;
9531 /* Return NULL when no more tokens are expected. */
9532 if (!ctx->next_num && (ctx->curr != START_SET)) {
9536 /* Determine if command should end here. */
9537 if (ctx->eol && ctx->last && ctx->next_num) {
9538 const enum index *list = ctx->next[ctx->next_num - 1];
9541 for (i = 0; list[i]; ++i) {
9548 *hdr = &cmd_set_raw_token_hdr;
9551 /** Token generator and output processing callback (cmdline API). */
9553 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
9556 cmd_set_raw_tok(arg0, arg2);
9558 cmd_set_raw_parsed(arg0);
9561 /** Global parser instance (cmdline API). */
9562 cmdline_parse_inst_t cmd_set_raw = {
9563 .f = cmd_set_raw_cb,
9564 .data = NULL, /**< Unused. */
9565 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
9568 }, /**< Tokens are returned by cmd_flow_tok(). */
9571 /* *** display raw_encap/raw_decap buf */
9572 struct cmd_show_set_raw_result {
9573 cmdline_fixed_string_t cmd_show;
9574 cmdline_fixed_string_t cmd_what;
9575 cmdline_fixed_string_t cmd_all;
9580 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
9582 struct cmd_show_set_raw_result *res = parsed_result;
9583 uint16_t index = res->cmd_index;
9585 uint8_t *raw_data = NULL;
9586 size_t raw_size = 0;
9587 char title[16] = {0};
9591 if (!strcmp(res->cmd_all, "all")) {
9594 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
9595 fprintf(stderr, "index should be 0-%u\n",
9596 RAW_ENCAP_CONFS_MAX_NUM - 1);
9600 if (!strcmp(res->cmd_what, "raw_encap")) {
9601 raw_data = (uint8_t *)&raw_encap_confs[index].data;
9602 raw_size = raw_encap_confs[index].size;
9603 snprintf(title, 16, "\nindex: %u", index);
9604 rte_hexdump(stdout, title, raw_data, raw_size);
9606 raw_data = (uint8_t *)&raw_decap_confs[index].data;
9607 raw_size = raw_decap_confs[index].size;
9608 snprintf(title, 16, "\nindex: %u", index);
9609 rte_hexdump(stdout, title, raw_data, raw_size);
9611 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
9614 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
9615 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9617 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
9618 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9619 cmd_what, "raw_encap#raw_decap");
9620 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
9621 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
9622 cmd_index, RTE_UINT16);
9623 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
9624 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9626 cmdline_parse_inst_t cmd_show_set_raw = {
9627 .f = cmd_show_set_raw_parsed,
9629 .help_str = "show <raw_encap|raw_decap> <index>",
9631 (void *)&cmd_show_set_raw_cmd_show,
9632 (void *)&cmd_show_set_raw_cmd_what,
9633 (void *)&cmd_show_set_raw_cmd_index,
9637 cmdline_parse_inst_t cmd_show_set_raw_all = {
9638 .f = cmd_show_set_raw_parsed,
9640 .help_str = "show <raw_encap|raw_decap> all",
9642 (void *)&cmd_show_set_raw_cmd_show,
9643 (void *)&cmd_show_set_raw_cmd_what,
9644 (void *)&cmd_show_set_raw_cmd_all,