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,
59 COMMON_PATTERN_TEMPLATE_ID,
60 COMMON_ACTIONS_TEMPLATE_ID,
64 /* TOP-level command. */
67 /* Top-level command. */
69 /* Sub-leve commands. */
76 /* Top-level command. */
78 /* Sub-level commands. */
105 /* Pattern template arguments. */
106 PATTERN_TEMPLATE_CREATE,
107 PATTERN_TEMPLATE_DESTROY,
108 PATTERN_TEMPLATE_CREATE_ID,
109 PATTERN_TEMPLATE_DESTROY_ID,
110 PATTERN_TEMPLATE_RELAXED_MATCHING,
111 PATTERN_TEMPLATE_INGRESS,
112 PATTERN_TEMPLATE_EGRESS,
113 PATTERN_TEMPLATE_TRANSFER,
114 PATTERN_TEMPLATE_SPEC,
116 /* Actions template arguments. */
117 ACTIONS_TEMPLATE_CREATE,
118 ACTIONS_TEMPLATE_DESTROY,
119 ACTIONS_TEMPLATE_CREATE_ID,
120 ACTIONS_TEMPLATE_DESTROY_ID,
121 ACTIONS_TEMPLATE_INGRESS,
122 ACTIONS_TEMPLATE_EGRESS,
123 ACTIONS_TEMPLATE_TRANSFER,
124 ACTIONS_TEMPLATE_SPEC,
125 ACTIONS_TEMPLATE_MASK,
127 /* Queue arguments. */
131 /* Queue create arguments. */
133 QUEUE_CREATE_POSTPONE,
134 QUEUE_TEMPLATE_TABLE,
135 QUEUE_PATTERN_TEMPLATE,
136 QUEUE_ACTIONS_TEMPLATE,
139 /* Queue destroy arguments. */
141 QUEUE_DESTROY_POSTPONE,
143 /* Push arguments. */
146 /* Pull arguments. */
149 /* Table arguments. */
160 TABLE_PATTERN_TEMPLATE,
161 TABLE_ACTIONS_TEMPLATE,
163 /* Tunnel arguments. */
170 /* Destroy arguments. */
173 /* Query arguments. */
176 /* List arguments. */
179 /* Destroy aged flow arguments. */
182 /* Validate/create arguments. */
195 /* Configure arguments */
196 CONFIG_QUEUES_NUMBER,
198 CONFIG_COUNTERS_NUMBER,
199 CONFIG_AGING_OBJECTS_NUMBER,
200 CONFIG_METERS_NUMBER,
202 /* Indirect action arguments */
203 INDIRECT_ACTION_CREATE,
204 INDIRECT_ACTION_UPDATE,
205 INDIRECT_ACTION_DESTROY,
206 INDIRECT_ACTION_QUERY,
208 /* Indirect action create arguments */
209 INDIRECT_ACTION_CREATE_ID,
210 INDIRECT_ACTION_INGRESS,
211 INDIRECT_ACTION_EGRESS,
212 INDIRECT_ACTION_TRANSFER,
213 INDIRECT_ACTION_SPEC,
215 /* Indirect action destroy arguments */
216 INDIRECT_ACTION_DESTROY_ID,
218 /* Validate/create pattern. */
246 ITEM_RAW_PATTERN_HEX,
257 ITEM_VLAN_INNER_TYPE,
258 ITEM_VLAN_HAS_MORE_VLAN,
263 ITEM_IPV4_FRAGMENT_OFFSET,
275 ITEM_IPV6_HAS_FRAG_EXT,
295 ITEM_VXLAN_LAST_RSVD,
297 ITEM_E_TAG_GRP_ECID_B,
306 ITEM_GRE_C_RSVD0_VER,
325 ITEM_ARP_ETH_IPV4_SHA,
326 ITEM_ARP_ETH_IPV4_SPA,
327 ITEM_ARP_ETH_IPV4_THA,
328 ITEM_ARP_ETH_IPV4_TPA,
330 ITEM_IPV6_EXT_NEXT_HDR,
332 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
333 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
334 ITEM_IPV6_FRAG_EXT_ID,
339 ITEM_ICMP6_ND_NS_TARGET_ADDR,
341 ITEM_ICMP6_ND_NA_TARGET_ADDR,
343 ITEM_ICMP6_ND_OPT_TYPE,
344 ITEM_ICMP6_ND_OPT_SLA_ETH,
345 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
346 ITEM_ICMP6_ND_OPT_TLA_ETH,
347 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
353 ITEM_GRE_OPTION_CHECKSUM,
355 ITEM_GRE_OPTION_SEQUENCE,
364 ITEM_HIGIG2_CLASSIFICATION,
370 ITEM_L2TPV3OIP_SESSION_ID,
380 ITEM_ECPRI_COMMON_TYPE,
381 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
382 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
383 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
384 ITEM_ECPRI_MSG_IQ_DATA_PCID,
385 ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
386 ITEM_ECPRI_MSG_DLY_MSR_MSRID,
388 ITEM_GENEVE_OPT_CLASS,
389 ITEM_GENEVE_OPT_TYPE,
390 ITEM_GENEVE_OPT_LENGTH,
391 ITEM_GENEVE_OPT_DATA,
393 ITEM_INTEGRITY_LEVEL,
394 ITEM_INTEGRITY_VALUE,
399 ITEM_PORT_REPRESENTOR,
400 ITEM_PORT_REPRESENTOR_PORT_ID,
401 ITEM_REPRESENTED_PORT,
402 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
404 ITEM_FLEX_ITEM_HANDLE,
405 ITEM_FLEX_PATTERN_HANDLE,
408 ITEM_L2TPV2_TYPE_DATA,
409 ITEM_L2TPV2_TYPE_DATA_L,
410 ITEM_L2TPV2_TYPE_DATA_S,
411 ITEM_L2TPV2_TYPE_DATA_O,
412 ITEM_L2TPV2_TYPE_DATA_L_S,
413 ITEM_L2TPV2_TYPE_CTRL,
414 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
415 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
416 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
417 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
418 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
419 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
420 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
421 ITEM_L2TPV2_MSG_DATA_S_NS,
422 ITEM_L2TPV2_MSG_DATA_S_NR,
423 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
424 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
425 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
426 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
427 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
428 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
429 ITEM_L2TPV2_MSG_DATA_L_S_NS,
430 ITEM_L2TPV2_MSG_DATA_L_S_NR,
431 ITEM_L2TPV2_MSG_CTRL_LENGTH,
432 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
433 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
434 ITEM_L2TPV2_MSG_CTRL_NS,
435 ITEM_L2TPV2_MSG_CTRL_NR,
441 /* Validate/create actions. */
460 ACTION_RSS_FUNC_DEFAULT,
461 ACTION_RSS_FUNC_TOEPLITZ,
462 ACTION_RSS_FUNC_SIMPLE_XOR,
463 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
475 ACTION_PHY_PORT_ORIGINAL,
476 ACTION_PHY_PORT_INDEX,
478 ACTION_PORT_ID_ORIGINAL,
482 ACTION_METER_COLOR_TYPE,
483 ACTION_METER_COLOR_GREEN,
484 ACTION_METER_COLOR_YELLOW,
485 ACTION_METER_COLOR_RED,
487 ACTION_OF_SET_MPLS_TTL,
488 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
489 ACTION_OF_DEC_MPLS_TTL,
490 ACTION_OF_SET_NW_TTL,
491 ACTION_OF_SET_NW_TTL_NW_TTL,
492 ACTION_OF_DEC_NW_TTL,
493 ACTION_OF_COPY_TTL_OUT,
494 ACTION_OF_COPY_TTL_IN,
497 ACTION_OF_PUSH_VLAN_ETHERTYPE,
498 ACTION_OF_SET_VLAN_VID,
499 ACTION_OF_SET_VLAN_VID_VLAN_VID,
500 ACTION_OF_SET_VLAN_PCP,
501 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
503 ACTION_OF_POP_MPLS_ETHERTYPE,
505 ACTION_OF_PUSH_MPLS_ETHERTYPE,
512 ACTION_MPLSOGRE_ENCAP,
513 ACTION_MPLSOGRE_DECAP,
514 ACTION_MPLSOUDP_ENCAP,
515 ACTION_MPLSOUDP_DECAP,
517 ACTION_SET_IPV4_SRC_IPV4_SRC,
519 ACTION_SET_IPV4_DST_IPV4_DST,
521 ACTION_SET_IPV6_SRC_IPV6_SRC,
523 ACTION_SET_IPV6_DST_IPV6_DST,
525 ACTION_SET_TP_SRC_TP_SRC,
527 ACTION_SET_TP_DST_TP_DST,
533 ACTION_SET_MAC_SRC_MAC_SRC,
535 ACTION_SET_MAC_DST_MAC_DST,
537 ACTION_INC_TCP_SEQ_VALUE,
539 ACTION_DEC_TCP_SEQ_VALUE,
541 ACTION_INC_TCP_ACK_VALUE,
543 ACTION_DEC_TCP_ACK_VALUE,
546 ACTION_RAW_ENCAP_INDEX,
547 ACTION_RAW_ENCAP_INDEX_VALUE,
548 ACTION_RAW_DECAP_INDEX,
549 ACTION_RAW_DECAP_INDEX_VALUE,
552 ACTION_SET_TAG_INDEX,
555 ACTION_SET_META_DATA,
556 ACTION_SET_META_MASK,
557 ACTION_SET_IPV4_DSCP,
558 ACTION_SET_IPV4_DSCP_VALUE,
559 ACTION_SET_IPV6_DSCP,
560 ACTION_SET_IPV6_DSCP_VALUE,
566 ACTION_SAMPLE_INDEX_VALUE,
568 INDIRECT_ACTION_ID2PTR,
570 ACTION_MODIFY_FIELD_OP,
571 ACTION_MODIFY_FIELD_OP_VALUE,
572 ACTION_MODIFY_FIELD_DST_TYPE,
573 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
574 ACTION_MODIFY_FIELD_DST_LEVEL,
575 ACTION_MODIFY_FIELD_DST_OFFSET,
576 ACTION_MODIFY_FIELD_SRC_TYPE,
577 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
578 ACTION_MODIFY_FIELD_SRC_LEVEL,
579 ACTION_MODIFY_FIELD_SRC_OFFSET,
580 ACTION_MODIFY_FIELD_SRC_VALUE,
581 ACTION_MODIFY_FIELD_SRC_POINTER,
582 ACTION_MODIFY_FIELD_WIDTH,
584 ACTION_CONNTRACK_UPDATE,
585 ACTION_CONNTRACK_UPDATE_DIR,
586 ACTION_CONNTRACK_UPDATE_CTX,
590 ACTION_PORT_REPRESENTOR,
591 ACTION_PORT_REPRESENTOR_PORT_ID,
592 ACTION_REPRESENTED_PORT,
593 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
596 /** Maximum size for pattern in struct rte_flow_item_raw. */
597 #define ITEM_RAW_PATTERN_SIZE 512
599 /** Maximum size for GENEVE option data pattern in bytes. */
600 #define ITEM_GENEVE_OPT_DATA_SIZE 124
602 /** Storage size for struct rte_flow_item_raw including pattern. */
603 #define ITEM_RAW_SIZE \
604 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
606 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
607 #define ACTION_MODIFY_PATTERN_SIZE 32
609 /** Storage size for struct rte_flow_action_modify_field including pattern. */
610 #define ACTION_MODIFY_SIZE \
611 (sizeof(struct rte_flow_action_modify_field) + \
612 ACTION_MODIFY_PATTERN_SIZE)
614 /** Maximum number of queue indices in struct rte_flow_action_rss. */
615 #define ACTION_RSS_QUEUE_NUM 128
617 /** Storage for struct rte_flow_action_rss including external data. */
618 struct action_rss_data {
619 struct rte_flow_action_rss conf;
620 uint8_t key[RSS_HASH_KEY_LENGTH];
621 uint16_t queue[ACTION_RSS_QUEUE_NUM];
624 /** Maximum data size in struct rte_flow_action_raw_encap. */
625 #define ACTION_RAW_ENCAP_MAX_DATA 512
626 #define RAW_ENCAP_CONFS_MAX_NUM 8
628 /** Storage for struct rte_flow_action_raw_encap. */
629 struct raw_encap_conf {
630 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
631 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
635 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
637 /** Storage for struct rte_flow_action_raw_encap including external data. */
638 struct action_raw_encap_data {
639 struct rte_flow_action_raw_encap conf;
640 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
641 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
645 /** Storage for struct rte_flow_action_raw_decap. */
646 struct raw_decap_conf {
647 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
651 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
653 /** Storage for struct rte_flow_action_raw_decap including external data. */
654 struct action_raw_decap_data {
655 struct rte_flow_action_raw_decap conf;
656 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
660 struct vxlan_encap_conf vxlan_encap_conf = {
664 .vni = "\x00\x00\x00",
666 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
667 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
668 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
669 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
670 "\x00\x00\x00\x00\x00\x00\x00\x01",
671 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
672 "\x00\x00\x00\x00\x00\x00\x11\x11",
676 .eth_src = "\x00\x00\x00\x00\x00\x00",
677 .eth_dst = "\xff\xff\xff\xff\xff\xff",
680 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
681 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
683 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
684 struct action_vxlan_encap_data {
685 struct rte_flow_action_vxlan_encap conf;
686 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
687 struct rte_flow_item_eth item_eth;
688 struct rte_flow_item_vlan item_vlan;
690 struct rte_flow_item_ipv4 item_ipv4;
691 struct rte_flow_item_ipv6 item_ipv6;
693 struct rte_flow_item_udp item_udp;
694 struct rte_flow_item_vxlan item_vxlan;
697 struct nvgre_encap_conf nvgre_encap_conf = {
700 .tni = "\x00\x00\x00",
701 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
702 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
703 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
704 "\x00\x00\x00\x00\x00\x00\x00\x01",
705 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
706 "\x00\x00\x00\x00\x00\x00\x11\x11",
708 .eth_src = "\x00\x00\x00\x00\x00\x00",
709 .eth_dst = "\xff\xff\xff\xff\xff\xff",
712 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
713 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
715 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
716 struct action_nvgre_encap_data {
717 struct rte_flow_action_nvgre_encap conf;
718 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
719 struct rte_flow_item_eth item_eth;
720 struct rte_flow_item_vlan item_vlan;
722 struct rte_flow_item_ipv4 item_ipv4;
723 struct rte_flow_item_ipv6 item_ipv6;
725 struct rte_flow_item_nvgre item_nvgre;
728 struct l2_encap_conf l2_encap_conf;
730 struct l2_decap_conf l2_decap_conf;
732 struct mplsogre_encap_conf mplsogre_encap_conf;
734 struct mplsogre_decap_conf mplsogre_decap_conf;
736 struct mplsoudp_encap_conf mplsoudp_encap_conf;
738 struct mplsoudp_decap_conf mplsoudp_decap_conf;
740 struct rte_flow_action_conntrack conntrack_context;
742 #define ACTION_SAMPLE_ACTIONS_NUM 10
743 #define RAW_SAMPLE_CONFS_MAX_NUM 8
744 /** Storage for struct rte_flow_action_sample including external data. */
745 struct action_sample_data {
746 struct rte_flow_action_sample conf;
749 /** Storage for struct rte_flow_action_sample. */
750 struct raw_sample_conf {
751 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
753 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
754 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
755 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
756 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
757 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
758 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
759 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
760 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
761 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
762 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
764 static const char *const modify_field_ops[] = {
765 "set", "add", "sub", NULL
768 static const char *const modify_field_ids[] = {
769 "start", "mac_dst", "mac_src",
770 "vlan_type", "vlan_id", "mac_type",
771 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
772 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
773 "tcp_port_src", "tcp_port_dst",
774 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
775 "udp_port_src", "udp_port_dst",
776 "vxlan_vni", "geneve_vni", "gtp_teid",
777 "tag", "mark", "meta", "pointer", "value", NULL
780 /** Maximum number of subsequent tokens and arguments on the stack. */
781 #define CTX_STACK_SIZE 16
783 /** Parser context. */
785 /** Stack of subsequent token lists to process. */
786 const enum index *next[CTX_STACK_SIZE];
787 /** Arguments for stacked tokens. */
788 const void *args[CTX_STACK_SIZE];
789 enum index curr; /**< Current token index. */
790 enum index prev; /**< Index of the last token seen. */
791 int next_num; /**< Number of entries in next[]. */
792 int args_num; /**< Number of entries in args[]. */
793 uint32_t eol:1; /**< EOL has been detected. */
794 uint32_t last:1; /**< No more arguments. */
795 portid_t port; /**< Current port ID (for completions). */
796 uint32_t objdata; /**< Object-specific data. */
797 void *object; /**< Address of current object for relative offsets. */
798 void *objmask; /**< Object a full mask must be written to. */
801 /** Token argument. */
803 uint32_t hton:1; /**< Use network byte ordering. */
804 uint32_t sign:1; /**< Value is signed. */
805 uint32_t bounded:1; /**< Value is bounded. */
806 uintmax_t min; /**< Minimum value if bounded. */
807 uintmax_t max; /**< Maximum value if bounded. */
808 uint32_t offset; /**< Relative offset from ctx->object. */
809 uint32_t size; /**< Field size. */
810 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
813 /** Parser token definition. */
815 /** Type displayed during completion (defaults to "TOKEN"). */
817 /** Help displayed during completion (defaults to token name). */
819 /** Private data used by parser functions. */
822 * Lists of subsequent tokens to push on the stack. Each call to the
823 * parser consumes the last entry of that stack.
825 const enum index *const *next;
826 /** Arguments stack for subsequent tokens that need them. */
827 const struct arg *const *args;
829 * Token-processing callback, returns -1 in case of error, the
830 * length of the matched string otherwise. If NULL, attempts to
831 * match the token name.
833 * If buf is not NULL, the result should be stored in it according
834 * to context. An error is returned if not large enough.
836 int (*call)(struct context *ctx, const struct token *token,
837 const char *str, unsigned int len,
838 void *buf, unsigned int size);
840 * Callback that provides possible values for this token, used for
841 * completion. Returns -1 in case of error, the number of possible
842 * values otherwise. If NULL, the token name is used.
844 * If buf is not NULL, entry index ent is written to buf and the
845 * full length of the entry is returned (same behavior as
848 int (*comp)(struct context *ctx, const struct token *token,
849 unsigned int ent, char *buf, unsigned int size);
850 /** Mandatory token name, no default value. */
854 /** Static initializer for the next field. */
855 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
857 /** Static initializer for a NEXT() entry. */
858 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
860 /** Static initializer for the args field. */
861 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
863 /** Static initializer for ARGS() to target a field. */
864 #define ARGS_ENTRY(s, f) \
865 (&(const struct arg){ \
866 .offset = offsetof(s, f), \
867 .size = sizeof(((s *)0)->f), \
870 /** Static initializer for ARGS() to target a bit-field. */
871 #define ARGS_ENTRY_BF(s, f, b) \
872 (&(const struct arg){ \
874 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
877 /** Static initializer for ARGS() to target a field with limits. */
878 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
879 (&(const struct arg){ \
883 .offset = offsetof(s, f), \
884 .size = sizeof(((s *)0)->f), \
887 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
888 #define ARGS_ENTRY_MASK(s, f, m) \
889 (&(const struct arg){ \
890 .offset = offsetof(s, f), \
891 .size = sizeof(((s *)0)->f), \
892 .mask = (const void *)(m), \
895 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
896 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
897 (&(const struct arg){ \
899 .offset = offsetof(s, f), \
900 .size = sizeof(((s *)0)->f), \
901 .mask = (const void *)(m), \
904 /** Static initializer for ARGS() to target a pointer. */
905 #define ARGS_ENTRY_PTR(s, f) \
906 (&(const struct arg){ \
907 .size = sizeof(*((s *)0)->f), \
910 /** Static initializer for ARGS() with arbitrary offset and size. */
911 #define ARGS_ENTRY_ARB(o, s) \
912 (&(const struct arg){ \
917 /** Same as ARGS_ENTRY_ARB() with bounded values. */
918 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
919 (&(const struct arg){ \
927 /** Same as ARGS_ENTRY() using network byte ordering. */
928 #define ARGS_ENTRY_HTON(s, f) \
929 (&(const struct arg){ \
931 .offset = offsetof(s, f), \
932 .size = sizeof(((s *)0)->f), \
935 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
936 #define ARG_ENTRY_HTON(s) \
937 (&(const struct arg){ \
943 /** Parser output buffer layout expected by cmd_flow_parsed(). */
945 enum index command; /**< Flow command. */
946 portid_t port; /**< Affected port ID. */
947 queueid_t queue; /** Async queue ID. */
948 bool postpone; /** Postpone async operation */
951 struct rte_flow_port_attr port_attr;
953 struct rte_flow_queue_attr queue_attr;
954 } configure; /**< Configuration arguments. */
956 uint32_t *template_id;
957 uint32_t template_id_n;
958 } templ_destroy; /**< Template destroy arguments. */
961 struct rte_flow_template_table_attr attr;
962 uint32_t *pat_templ_id;
963 uint32_t pat_templ_id_n;
964 uint32_t *act_templ_id;
965 uint32_t act_templ_id_n;
966 } table; /**< Table arguments. */
970 } table_destroy; /**< Template destroy arguments. */
973 uint32_t action_id_n;
974 } ia_destroy; /**< Indirect action destroy arguments. */
977 } ia; /* Indirect action query arguments */
980 uint32_t pat_templ_id;
981 uint32_t act_templ_id;
982 struct rte_flow_attr attr;
983 struct tunnel_ops tunnel_ops;
984 struct rte_flow_item *pattern;
985 struct rte_flow_action *actions;
986 struct rte_flow_action *masks;
990 } vc; /**< Validate/create arguments. */
994 } destroy; /**< Destroy arguments. */
999 } dump; /**< Dump arguments. */
1002 struct rte_flow_action action;
1003 } query; /**< Query arguments. */
1007 } list; /**< List arguments. */
1010 } isolate; /**< Isolated mode arguments. */
1013 } aged; /**< Aged arguments. */
1016 } policy;/**< Policy arguments. */
1021 } flex; /**< Flex arguments*/
1022 } args; /**< Command arguments. */
1025 /** Private data for pattern items. */
1026 struct parse_item_priv {
1027 enum rte_flow_item_type type; /**< Item type. */
1028 uint32_t size; /**< Size of item specification structure. */
1031 #define PRIV_ITEM(t, s) \
1032 (&(const struct parse_item_priv){ \
1033 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
1037 /** Private data for actions. */
1038 struct parse_action_priv {
1039 enum rte_flow_action_type type; /**< Action type. */
1040 uint32_t size; /**< Size of action configuration structure. */
1043 #define PRIV_ACTION(t, s) \
1044 (&(const struct parse_action_priv){ \
1045 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
1049 static const enum index next_flex_item[] = {
1056 static const enum index next_config_attr[] = {
1057 CONFIG_QUEUES_NUMBER,
1059 CONFIG_COUNTERS_NUMBER,
1060 CONFIG_AGING_OBJECTS_NUMBER,
1061 CONFIG_METERS_NUMBER,
1066 static const enum index next_pt_subcmd[] = {
1067 PATTERN_TEMPLATE_CREATE,
1068 PATTERN_TEMPLATE_DESTROY,
1072 static const enum index next_pt_attr[] = {
1073 PATTERN_TEMPLATE_CREATE_ID,
1074 PATTERN_TEMPLATE_RELAXED_MATCHING,
1075 PATTERN_TEMPLATE_INGRESS,
1076 PATTERN_TEMPLATE_EGRESS,
1077 PATTERN_TEMPLATE_TRANSFER,
1078 PATTERN_TEMPLATE_SPEC,
1082 static const enum index next_pt_destroy_attr[] = {
1083 PATTERN_TEMPLATE_DESTROY_ID,
1088 static const enum index next_at_subcmd[] = {
1089 ACTIONS_TEMPLATE_CREATE,
1090 ACTIONS_TEMPLATE_DESTROY,
1094 static const enum index next_at_attr[] = {
1095 ACTIONS_TEMPLATE_CREATE_ID,
1096 ACTIONS_TEMPLATE_INGRESS,
1097 ACTIONS_TEMPLATE_EGRESS,
1098 ACTIONS_TEMPLATE_TRANSFER,
1099 ACTIONS_TEMPLATE_SPEC,
1103 static const enum index next_at_destroy_attr[] = {
1104 ACTIONS_TEMPLATE_DESTROY_ID,
1109 static const enum index next_table_subcmd[] = {
1115 static const enum index next_table_attr[] = {
1123 TABLE_PATTERN_TEMPLATE,
1124 TABLE_ACTIONS_TEMPLATE,
1129 static const enum index next_table_destroy_attr[] = {
1135 static const enum index next_queue_subcmd[] = {
1141 static const enum index next_queue_destroy_attr[] = {
1147 static const enum index next_ia_create_attr[] = {
1148 INDIRECT_ACTION_CREATE_ID,
1149 INDIRECT_ACTION_INGRESS,
1150 INDIRECT_ACTION_EGRESS,
1151 INDIRECT_ACTION_TRANSFER,
1152 INDIRECT_ACTION_SPEC,
1156 static const enum index next_dump_subcmd[] = {
1162 static const enum index next_ia_subcmd[] = {
1163 INDIRECT_ACTION_CREATE,
1164 INDIRECT_ACTION_UPDATE,
1165 INDIRECT_ACTION_DESTROY,
1166 INDIRECT_ACTION_QUERY,
1170 static const enum index next_vc_attr[] = {
1182 static const enum index next_destroy_attr[] = {
1188 static const enum index next_dump_attr[] = {
1194 static const enum index next_list_attr[] = {
1200 static const enum index next_aged_attr[] = {
1206 static const enum index next_ia_destroy_attr[] = {
1207 INDIRECT_ACTION_DESTROY_ID,
1212 static const enum index item_param[] = {
1221 static const enum index next_item[] = {
1258 ITEM_ICMP6_ND_OPT_SLA_ETH,
1259 ITEM_ICMP6_ND_OPT_TLA_ETH,
1266 ITEM_PPPOE_PROTO_ID,
1277 ITEM_PORT_REPRESENTOR,
1278 ITEM_REPRESENTED_PORT,
1286 static const enum index item_fuzzy[] = {
1292 static const enum index item_any[] = {
1298 static const enum index item_vf[] = {
1304 static const enum index item_phy_port[] = {
1305 ITEM_PHY_PORT_INDEX,
1310 static const enum index item_port_id[] = {
1316 static const enum index item_mark[] = {
1322 static const enum index item_raw[] = {
1328 ITEM_RAW_PATTERN_HEX,
1333 static const enum index item_eth[] = {
1342 static const enum index item_vlan[] = {
1347 ITEM_VLAN_INNER_TYPE,
1348 ITEM_VLAN_HAS_MORE_VLAN,
1353 static const enum index item_ipv4[] = {
1357 ITEM_IPV4_FRAGMENT_OFFSET,
1366 static const enum index item_ipv6[] = {
1373 ITEM_IPV6_HAS_FRAG_EXT,
1378 static const enum index item_icmp[] = {
1387 static const enum index item_udp[] = {
1394 static const enum index item_tcp[] = {
1402 static const enum index item_sctp[] = {
1411 static const enum index item_vxlan[] = {
1413 ITEM_VXLAN_LAST_RSVD,
1418 static const enum index item_e_tag[] = {
1419 ITEM_E_TAG_GRP_ECID_B,
1424 static const enum index item_nvgre[] = {
1430 static const enum index item_mpls[] = {
1438 static const enum index item_gre[] = {
1440 ITEM_GRE_C_RSVD0_VER,
1448 static const enum index item_gre_key[] = {
1454 static const enum index item_gre_option[] = {
1455 ITEM_GRE_OPTION_CHECKSUM,
1456 ITEM_GRE_OPTION_KEY,
1457 ITEM_GRE_OPTION_SEQUENCE,
1462 static const enum index item_gtp[] = {
1470 static const enum index item_geneve[] = {
1478 static const enum index item_vxlan_gpe[] = {
1484 static const enum index item_arp_eth_ipv4[] = {
1485 ITEM_ARP_ETH_IPV4_SHA,
1486 ITEM_ARP_ETH_IPV4_SPA,
1487 ITEM_ARP_ETH_IPV4_THA,
1488 ITEM_ARP_ETH_IPV4_TPA,
1493 static const enum index item_ipv6_ext[] = {
1494 ITEM_IPV6_EXT_NEXT_HDR,
1499 static const enum index item_ipv6_frag_ext[] = {
1500 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1501 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1502 ITEM_IPV6_FRAG_EXT_ID,
1507 static const enum index item_icmp6[] = {
1514 static const enum index item_icmp6_nd_ns[] = {
1515 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1520 static const enum index item_icmp6_nd_na[] = {
1521 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1526 static const enum index item_icmp6_nd_opt[] = {
1527 ITEM_ICMP6_ND_OPT_TYPE,
1532 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1533 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1538 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1539 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1544 static const enum index item_meta[] = {
1550 static const enum index item_gtp_psc[] = {
1557 static const enum index item_pppoed[] = {
1563 static const enum index item_pppoes[] = {
1569 static const enum index item_pppoe_proto_id[] = {
1574 static const enum index item_higig2[] = {
1575 ITEM_HIGIG2_CLASSIFICATION,
1581 static const enum index item_esp[] = {
1587 static const enum index item_ah[] = {
1593 static const enum index item_pfcp[] = {
1600 static const enum index next_set_raw[] = {
1606 static const enum index item_tag[] = {
1613 static const enum index item_l2tpv3oip[] = {
1614 ITEM_L2TPV3OIP_SESSION_ID,
1619 static const enum index item_ecpri[] = {
1625 static const enum index item_ecpri_common[] = {
1626 ITEM_ECPRI_COMMON_TYPE,
1630 static const enum index item_ecpri_common_type[] = {
1631 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1632 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1633 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1637 static const enum index item_geneve_opt[] = {
1638 ITEM_GENEVE_OPT_CLASS,
1639 ITEM_GENEVE_OPT_TYPE,
1640 ITEM_GENEVE_OPT_LENGTH,
1641 ITEM_GENEVE_OPT_DATA,
1646 static const enum index item_integrity[] = {
1647 ITEM_INTEGRITY_LEVEL,
1648 ITEM_INTEGRITY_VALUE,
1652 static const enum index item_integrity_lv[] = {
1653 ITEM_INTEGRITY_LEVEL,
1654 ITEM_INTEGRITY_VALUE,
1659 static const enum index item_port_representor[] = {
1660 ITEM_PORT_REPRESENTOR_PORT_ID,
1665 static const enum index item_represented_port[] = {
1666 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1671 static const enum index item_flex[] = {
1672 ITEM_FLEX_PATTERN_HANDLE,
1673 ITEM_FLEX_ITEM_HANDLE,
1678 static const enum index item_l2tpv2[] = {
1684 static const enum index item_l2tpv2_type[] = {
1685 ITEM_L2TPV2_TYPE_DATA,
1686 ITEM_L2TPV2_TYPE_DATA_L,
1687 ITEM_L2TPV2_TYPE_DATA_S,
1688 ITEM_L2TPV2_TYPE_DATA_O,
1689 ITEM_L2TPV2_TYPE_DATA_L_S,
1690 ITEM_L2TPV2_TYPE_CTRL,
1694 static const enum index item_l2tpv2_type_data[] = {
1695 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1696 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1701 static const enum index item_l2tpv2_type_data_l[] = {
1702 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1703 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1704 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1709 static const enum index item_l2tpv2_type_data_s[] = {
1710 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1711 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1712 ITEM_L2TPV2_MSG_DATA_S_NS,
1713 ITEM_L2TPV2_MSG_DATA_S_NR,
1718 static const enum index item_l2tpv2_type_data_o[] = {
1719 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1720 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1721 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1726 static const enum index item_l2tpv2_type_data_l_s[] = {
1727 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1728 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1729 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1730 ITEM_L2TPV2_MSG_DATA_L_S_NS,
1731 ITEM_L2TPV2_MSG_DATA_L_S_NR,
1736 static const enum index item_l2tpv2_type_ctrl[] = {
1737 ITEM_L2TPV2_MSG_CTRL_LENGTH,
1738 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1739 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1740 ITEM_L2TPV2_MSG_CTRL_NS,
1741 ITEM_L2TPV2_MSG_CTRL_NR,
1746 static const enum index item_ppp[] = {
1754 static const enum index next_action[] = {
1771 ACTION_OF_SET_MPLS_TTL,
1772 ACTION_OF_DEC_MPLS_TTL,
1773 ACTION_OF_SET_NW_TTL,
1774 ACTION_OF_DEC_NW_TTL,
1775 ACTION_OF_COPY_TTL_OUT,
1776 ACTION_OF_COPY_TTL_IN,
1778 ACTION_OF_PUSH_VLAN,
1779 ACTION_OF_SET_VLAN_VID,
1780 ACTION_OF_SET_VLAN_PCP,
1782 ACTION_OF_PUSH_MPLS,
1789 ACTION_MPLSOGRE_ENCAP,
1790 ACTION_MPLSOGRE_DECAP,
1791 ACTION_MPLSOUDP_ENCAP,
1792 ACTION_MPLSOUDP_DECAP,
1793 ACTION_SET_IPV4_SRC,
1794 ACTION_SET_IPV4_DST,
1795 ACTION_SET_IPV6_SRC,
1796 ACTION_SET_IPV6_DST,
1812 ACTION_SET_IPV4_DSCP,
1813 ACTION_SET_IPV6_DSCP,
1817 ACTION_MODIFY_FIELD,
1819 ACTION_CONNTRACK_UPDATE,
1820 ACTION_PORT_REPRESENTOR,
1821 ACTION_REPRESENTED_PORT,
1825 static const enum index action_mark[] = {
1831 static const enum index action_queue[] = {
1837 static const enum index action_count[] = {
1843 static const enum index action_rss[] = {
1854 static const enum index action_vf[] = {
1861 static const enum index action_phy_port[] = {
1862 ACTION_PHY_PORT_ORIGINAL,
1863 ACTION_PHY_PORT_INDEX,
1868 static const enum index action_port_id[] = {
1869 ACTION_PORT_ID_ORIGINAL,
1875 static const enum index action_meter[] = {
1881 static const enum index action_meter_color[] = {
1882 ACTION_METER_COLOR_TYPE,
1887 static const enum index action_of_set_mpls_ttl[] = {
1888 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1893 static const enum index action_of_set_nw_ttl[] = {
1894 ACTION_OF_SET_NW_TTL_NW_TTL,
1899 static const enum index action_of_push_vlan[] = {
1900 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1905 static const enum index action_of_set_vlan_vid[] = {
1906 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1911 static const enum index action_of_set_vlan_pcp[] = {
1912 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1917 static const enum index action_of_pop_mpls[] = {
1918 ACTION_OF_POP_MPLS_ETHERTYPE,
1923 static const enum index action_of_push_mpls[] = {
1924 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1929 static const enum index action_set_ipv4_src[] = {
1930 ACTION_SET_IPV4_SRC_IPV4_SRC,
1935 static const enum index action_set_mac_src[] = {
1936 ACTION_SET_MAC_SRC_MAC_SRC,
1941 static const enum index action_set_ipv4_dst[] = {
1942 ACTION_SET_IPV4_DST_IPV4_DST,
1947 static const enum index action_set_ipv6_src[] = {
1948 ACTION_SET_IPV6_SRC_IPV6_SRC,
1953 static const enum index action_set_ipv6_dst[] = {
1954 ACTION_SET_IPV6_DST_IPV6_DST,
1959 static const enum index action_set_tp_src[] = {
1960 ACTION_SET_TP_SRC_TP_SRC,
1965 static const enum index action_set_tp_dst[] = {
1966 ACTION_SET_TP_DST_TP_DST,
1971 static const enum index action_set_ttl[] = {
1977 static const enum index action_jump[] = {
1983 static const enum index action_set_mac_dst[] = {
1984 ACTION_SET_MAC_DST_MAC_DST,
1989 static const enum index action_inc_tcp_seq[] = {
1990 ACTION_INC_TCP_SEQ_VALUE,
1995 static const enum index action_dec_tcp_seq[] = {
1996 ACTION_DEC_TCP_SEQ_VALUE,
2001 static const enum index action_inc_tcp_ack[] = {
2002 ACTION_INC_TCP_ACK_VALUE,
2007 static const enum index action_dec_tcp_ack[] = {
2008 ACTION_DEC_TCP_ACK_VALUE,
2013 static const enum index action_raw_encap[] = {
2014 ACTION_RAW_ENCAP_INDEX,
2019 static const enum index action_raw_decap[] = {
2020 ACTION_RAW_DECAP_INDEX,
2025 static const enum index action_set_tag[] = {
2026 ACTION_SET_TAG_DATA,
2027 ACTION_SET_TAG_INDEX,
2028 ACTION_SET_TAG_MASK,
2033 static const enum index action_set_meta[] = {
2034 ACTION_SET_META_DATA,
2035 ACTION_SET_META_MASK,
2040 static const enum index action_set_ipv4_dscp[] = {
2041 ACTION_SET_IPV4_DSCP_VALUE,
2046 static const enum index action_set_ipv6_dscp[] = {
2047 ACTION_SET_IPV6_DSCP_VALUE,
2052 static const enum index action_age[] = {
2059 static const enum index action_sample[] = {
2061 ACTION_SAMPLE_RATIO,
2062 ACTION_SAMPLE_INDEX,
2067 static const enum index next_action_sample[] = {
2080 static const enum index action_modify_field_dst[] = {
2081 ACTION_MODIFY_FIELD_DST_LEVEL,
2082 ACTION_MODIFY_FIELD_DST_OFFSET,
2083 ACTION_MODIFY_FIELD_SRC_TYPE,
2087 static const enum index action_modify_field_src[] = {
2088 ACTION_MODIFY_FIELD_SRC_LEVEL,
2089 ACTION_MODIFY_FIELD_SRC_OFFSET,
2090 ACTION_MODIFY_FIELD_SRC_VALUE,
2091 ACTION_MODIFY_FIELD_SRC_POINTER,
2092 ACTION_MODIFY_FIELD_WIDTH,
2096 static const enum index action_update_conntrack[] = {
2097 ACTION_CONNTRACK_UPDATE_DIR,
2098 ACTION_CONNTRACK_UPDATE_CTX,
2103 static const enum index action_port_representor[] = {
2104 ACTION_PORT_REPRESENTOR_PORT_ID,
2109 static const enum index action_represented_port[] = {
2110 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2115 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2116 const char *, unsigned int,
2117 void *, unsigned int);
2118 static int parse_set_sample_action(struct context *, const struct token *,
2119 const char *, unsigned int,
2120 void *, unsigned int);
2121 static int parse_set_init(struct context *, const struct token *,
2122 const char *, unsigned int,
2123 void *, unsigned int);
2125 parse_flex_handle(struct context *, const struct token *,
2126 const char *, unsigned int, void *, unsigned int);
2127 static int parse_init(struct context *, const struct token *,
2128 const char *, unsigned int,
2129 void *, unsigned int);
2130 static int parse_vc(struct context *, const struct token *,
2131 const char *, unsigned int,
2132 void *, unsigned int);
2133 static int parse_vc_spec(struct context *, const struct token *,
2134 const char *, unsigned int, void *, unsigned int);
2135 static int parse_vc_conf(struct context *, const struct token *,
2136 const char *, unsigned int, void *, unsigned int);
2137 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2138 const char *, unsigned int,
2139 void *, unsigned int);
2140 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2141 const char *, unsigned int,
2142 void *, unsigned int);
2143 static int parse_vc_action_meter_color_type(struct context *,
2144 const struct token *,
2145 const char *, unsigned int, void *,
2147 static int parse_vc_action_rss(struct context *, const struct token *,
2148 const char *, unsigned int, void *,
2150 static int parse_vc_action_rss_func(struct context *, const struct token *,
2151 const char *, unsigned int, void *,
2153 static int parse_vc_action_rss_type(struct context *, const struct token *,
2154 const char *, unsigned int, void *,
2156 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2157 const char *, unsigned int, void *,
2159 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2160 const char *, unsigned int, void *,
2162 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2163 const char *, unsigned int, void *,
2165 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2166 const char *, unsigned int, void *,
2168 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2169 const char *, unsigned int, void *,
2171 static int parse_vc_action_mplsogre_encap(struct context *,
2172 const struct token *, const char *,
2173 unsigned int, void *, unsigned int);
2174 static int parse_vc_action_mplsogre_decap(struct context *,
2175 const struct token *, const char *,
2176 unsigned int, void *, unsigned int);
2177 static int parse_vc_action_mplsoudp_encap(struct context *,
2178 const struct token *, const char *,
2179 unsigned int, void *, unsigned int);
2180 static int parse_vc_action_mplsoudp_decap(struct context *,
2181 const struct token *, const char *,
2182 unsigned int, void *, unsigned int);
2183 static int parse_vc_action_raw_encap(struct context *,
2184 const struct token *, const char *,
2185 unsigned int, void *, unsigned int);
2186 static int parse_vc_action_raw_decap(struct context *,
2187 const struct token *, const char *,
2188 unsigned int, void *, unsigned int);
2189 static int parse_vc_action_raw_encap_index(struct context *,
2190 const struct token *, const char *,
2191 unsigned int, void *, unsigned int);
2192 static int parse_vc_action_raw_decap_index(struct context *,
2193 const struct token *, const char *,
2194 unsigned int, void *, unsigned int);
2195 static int parse_vc_action_set_meta(struct context *ctx,
2196 const struct token *token, const char *str,
2197 unsigned int len, void *buf,
2199 static int parse_vc_action_sample(struct context *ctx,
2200 const struct token *token, const char *str,
2201 unsigned int len, void *buf,
2204 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2205 const char *str, unsigned int len, void *buf,
2208 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2209 const char *str, unsigned int len, void *buf,
2212 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2213 const char *str, unsigned int len, void *buf,
2216 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2217 const char *str, unsigned int len, void *buf,
2219 static int parse_destroy(struct context *, const struct token *,
2220 const char *, unsigned int,
2221 void *, unsigned int);
2222 static int parse_flush(struct context *, const struct token *,
2223 const char *, unsigned int,
2224 void *, unsigned int);
2225 static int parse_dump(struct context *, const struct token *,
2226 const char *, unsigned int,
2227 void *, unsigned int);
2228 static int parse_query(struct context *, const struct token *,
2229 const char *, unsigned int,
2230 void *, unsigned int);
2231 static int parse_action(struct context *, const struct token *,
2232 const char *, unsigned int,
2233 void *, unsigned int);
2234 static int parse_list(struct context *, const struct token *,
2235 const char *, unsigned int,
2236 void *, unsigned int);
2237 static int parse_aged(struct context *, const struct token *,
2238 const char *, unsigned int,
2239 void *, unsigned int);
2240 static int parse_isolate(struct context *, const struct token *,
2241 const char *, unsigned int,
2242 void *, unsigned int);
2243 static int parse_configure(struct context *, const struct token *,
2244 const char *, unsigned int,
2245 void *, unsigned int);
2246 static int parse_template(struct context *, const struct token *,
2247 const char *, unsigned int,
2248 void *, unsigned int);
2249 static int parse_template_destroy(struct context *, const struct token *,
2250 const char *, unsigned int,
2251 void *, unsigned int);
2252 static int parse_table(struct context *, const struct token *,
2253 const char *, unsigned int, void *, unsigned int);
2254 static int parse_table_destroy(struct context *, const struct token *,
2255 const char *, unsigned int,
2256 void *, unsigned int);
2257 static int parse_qo(struct context *, const struct token *,
2258 const char *, unsigned int,
2259 void *, unsigned int);
2260 static int parse_qo_destroy(struct context *, const struct token *,
2261 const char *, unsigned int,
2262 void *, unsigned int);
2263 static int parse_push(struct context *, const struct token *,
2264 const char *, unsigned int,
2265 void *, unsigned int);
2266 static int parse_pull(struct context *, const struct token *,
2267 const char *, unsigned int,
2268 void *, unsigned int);
2269 static int parse_tunnel(struct context *, const struct token *,
2270 const char *, unsigned int,
2271 void *, unsigned int);
2272 static int parse_flex(struct context *, const struct token *,
2273 const char *, unsigned int, void *, unsigned int);
2274 static int parse_int(struct context *, const struct token *,
2275 const char *, unsigned int,
2276 void *, unsigned int);
2277 static int parse_prefix(struct context *, const struct token *,
2278 const char *, unsigned int,
2279 void *, unsigned int);
2280 static int parse_boolean(struct context *, const struct token *,
2281 const char *, unsigned int,
2282 void *, unsigned int);
2283 static int parse_string(struct context *, const struct token *,
2284 const char *, unsigned int,
2285 void *, unsigned int);
2286 static int parse_hex(struct context *ctx, const struct token *token,
2287 const char *str, unsigned int len,
2288 void *buf, unsigned int size);
2289 static int parse_string0(struct context *, const struct token *,
2290 const char *, unsigned int,
2291 void *, unsigned int);
2292 static int parse_mac_addr(struct context *, const struct token *,
2293 const char *, unsigned int,
2294 void *, unsigned int);
2295 static int parse_ipv4_addr(struct context *, const struct token *,
2296 const char *, unsigned int,
2297 void *, unsigned int);
2298 static int parse_ipv6_addr(struct context *, const struct token *,
2299 const char *, unsigned int,
2300 void *, unsigned int);
2301 static int parse_port(struct context *, const struct token *,
2302 const char *, unsigned int,
2303 void *, unsigned int);
2304 static int parse_ia(struct context *, const struct token *,
2305 const char *, unsigned int,
2306 void *, unsigned int);
2307 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2308 const char *str, unsigned int len,
2309 void *buf, unsigned int size);
2310 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2311 const char *str, unsigned int len, void *buf,
2313 static int parse_mp(struct context *, const struct token *,
2314 const char *, unsigned int,
2315 void *, unsigned int);
2316 static int comp_none(struct context *, const struct token *,
2317 unsigned int, char *, unsigned int);
2318 static int comp_boolean(struct context *, const struct token *,
2319 unsigned int, char *, unsigned int);
2320 static int comp_action(struct context *, const struct token *,
2321 unsigned int, char *, unsigned int);
2322 static int comp_port(struct context *, const struct token *,
2323 unsigned int, char *, unsigned int);
2324 static int comp_rule_id(struct context *, const struct token *,
2325 unsigned int, char *, unsigned int);
2326 static int comp_vc_action_rss_type(struct context *, const struct token *,
2327 unsigned int, char *, unsigned int);
2328 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2329 unsigned int, char *, unsigned int);
2330 static int comp_set_raw_index(struct context *, const struct token *,
2331 unsigned int, char *, unsigned int);
2332 static int comp_set_sample_index(struct context *, const struct token *,
2333 unsigned int, char *, unsigned int);
2334 static int comp_set_modify_field_op(struct context *, const struct token *,
2335 unsigned int, char *, unsigned int);
2336 static int comp_set_modify_field_id(struct context *, const struct token *,
2337 unsigned int, char *, unsigned int);
2338 static int comp_pattern_template_id(struct context *, const struct token *,
2339 unsigned int, char *, unsigned int);
2340 static int comp_actions_template_id(struct context *, const struct token *,
2341 unsigned int, char *, unsigned int);
2342 static int comp_table_id(struct context *, const struct token *,
2343 unsigned int, char *, unsigned int);
2344 static int comp_queue_id(struct context *, const struct token *,
2345 unsigned int, char *, unsigned int);
2347 /** Token definitions. */
2348 static const struct token token_list[] = {
2349 /* Special tokens. */
2352 .help = "null entry, abused as the entry point",
2353 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2358 .help = "command may end here",
2361 .name = "START_SET",
2362 .help = "null entry, abused as the entry point for set",
2363 .next = NEXT(NEXT_ENTRY(SET)),
2368 .help = "set command may end here",
2370 /* Common tokens. */
2371 [COMMON_INTEGER] = {
2374 .help = "integer value",
2378 [COMMON_UNSIGNED] = {
2379 .name = "{unsigned}",
2381 .help = "unsigned integer value",
2388 .help = "prefix length for bit-mask",
2389 .call = parse_prefix,
2392 [COMMON_BOOLEAN] = {
2393 .name = "{boolean}",
2395 .help = "any boolean value",
2396 .call = parse_boolean,
2397 .comp = comp_boolean,
2402 .help = "fixed string",
2403 .call = parse_string,
2409 .help = "fixed string",
2412 [COMMON_FILE_PATH] = {
2413 .name = "{file path}",
2415 .help = "file path",
2416 .call = parse_string0,
2419 [COMMON_MAC_ADDR] = {
2420 .name = "{MAC address}",
2422 .help = "standard MAC address notation",
2423 .call = parse_mac_addr,
2426 [COMMON_IPV4_ADDR] = {
2427 .name = "{IPv4 address}",
2428 .type = "IPV4 ADDRESS",
2429 .help = "standard IPv4 address notation",
2430 .call = parse_ipv4_addr,
2433 [COMMON_IPV6_ADDR] = {
2434 .name = "{IPv6 address}",
2435 .type = "IPV6 ADDRESS",
2436 .help = "standard IPv6 address notation",
2437 .call = parse_ipv6_addr,
2440 [COMMON_RULE_ID] = {
2441 .name = "{rule id}",
2443 .help = "rule identifier",
2445 .comp = comp_rule_id,
2447 [COMMON_PORT_ID] = {
2448 .name = "{port_id}",
2450 .help = "port identifier",
2454 [COMMON_GROUP_ID] = {
2455 .name = "{group_id}",
2457 .help = "group identifier",
2461 [COMMON_PRIORITY_LEVEL] = {
2464 .help = "priority level",
2468 [COMMON_INDIRECT_ACTION_ID] = {
2469 .name = "{indirect_action_id}",
2470 .type = "INDIRECT_ACTION_ID",
2471 .help = "indirect action id",
2475 [COMMON_POLICY_ID] = {
2476 .name = "{policy_id}",
2477 .type = "POLICY_ID",
2478 .help = "policy id",
2482 [COMMON_FLEX_TOKEN] = {
2483 .name = "{flex token}",
2484 .type = "flex token",
2485 .help = "flex token",
2489 [COMMON_FLEX_HANDLE] = {
2490 .name = "{flex handle}",
2491 .type = "FLEX HANDLE",
2492 .help = "fill flex item data",
2493 .call = parse_flex_handle,
2496 [COMMON_PATTERN_TEMPLATE_ID] = {
2497 .name = "{pattern_template_id}",
2498 .type = "PATTERN_TEMPLATE_ID",
2499 .help = "pattern template id",
2501 .comp = comp_pattern_template_id,
2503 [COMMON_ACTIONS_TEMPLATE_ID] = {
2504 .name = "{actions_template_id}",
2505 .type = "ACTIONS_TEMPLATE_ID",
2506 .help = "actions template id",
2508 .comp = comp_actions_template_id,
2510 [COMMON_TABLE_ID] = {
2511 .name = "{table_id}",
2515 .comp = comp_table_id,
2517 [COMMON_QUEUE_ID] = {
2518 .name = "{queue_id}",
2522 .comp = comp_queue_id,
2524 /* Top-level command. */
2527 .type = "{command} {port_id} [{arg} [...]]",
2528 .help = "manage ingress/egress flow rules",
2529 .next = NEXT(NEXT_ENTRY
2552 /* Top-level command. */
2555 .help = "get information about flow engine",
2556 .next = NEXT(NEXT_ENTRY(END),
2557 NEXT_ENTRY(COMMON_PORT_ID)),
2558 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2559 .call = parse_configure,
2561 /* Top-level command. */
2563 .name = "configure",
2564 .help = "configure flow engine",
2565 .next = NEXT(next_config_attr,
2566 NEXT_ENTRY(COMMON_PORT_ID)),
2567 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2568 .call = parse_configure,
2570 /* Configure arguments. */
2571 [CONFIG_QUEUES_NUMBER] = {
2572 .name = "queues_number",
2573 .help = "number of queues",
2574 .next = NEXT(next_config_attr,
2575 NEXT_ENTRY(COMMON_UNSIGNED)),
2576 .args = ARGS(ARGS_ENTRY(struct buffer,
2577 args.configure.nb_queue)),
2579 [CONFIG_QUEUES_SIZE] = {
2580 .name = "queues_size",
2581 .help = "number of elements in queues",
2582 .next = NEXT(next_config_attr,
2583 NEXT_ENTRY(COMMON_UNSIGNED)),
2584 .args = ARGS(ARGS_ENTRY(struct buffer,
2585 args.configure.queue_attr.size)),
2587 [CONFIG_COUNTERS_NUMBER] = {
2588 .name = "counters_number",
2589 .help = "number of counters",
2590 .next = NEXT(next_config_attr,
2591 NEXT_ENTRY(COMMON_UNSIGNED)),
2592 .args = ARGS(ARGS_ENTRY(struct buffer,
2593 args.configure.port_attr.nb_counters)),
2595 [CONFIG_AGING_OBJECTS_NUMBER] = {
2596 .name = "aging_counters_number",
2597 .help = "number of aging objects",
2598 .next = NEXT(next_config_attr,
2599 NEXT_ENTRY(COMMON_UNSIGNED)),
2600 .args = ARGS(ARGS_ENTRY(struct buffer,
2601 args.configure.port_attr.nb_aging_objects)),
2603 [CONFIG_METERS_NUMBER] = {
2604 .name = "meters_number",
2605 .help = "number of meters",
2606 .next = NEXT(next_config_attr,
2607 NEXT_ENTRY(COMMON_UNSIGNED)),
2608 .args = ARGS(ARGS_ENTRY(struct buffer,
2609 args.configure.port_attr.nb_meters)),
2611 /* Top-level command. */
2612 [PATTERN_TEMPLATE] = {
2613 .name = "pattern_template",
2614 .type = "{command} {port_id} [{arg} [...]]",
2615 .help = "manage pattern templates",
2616 .next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2617 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2618 .call = parse_template,
2620 /* Sub-level commands. */
2621 [PATTERN_TEMPLATE_CREATE] = {
2623 .help = "create pattern template",
2624 .next = NEXT(next_pt_attr),
2625 .call = parse_template,
2627 [PATTERN_TEMPLATE_DESTROY] = {
2629 .help = "destroy pattern template",
2630 .next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
2631 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2632 .call = parse_template_destroy,
2634 /* Pattern template arguments. */
2635 [PATTERN_TEMPLATE_CREATE_ID] = {
2636 .name = "pattern_template_id",
2637 .help = "specify a pattern template id to create",
2638 .next = NEXT(next_pt_attr,
2639 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2640 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
2642 [PATTERN_TEMPLATE_DESTROY_ID] = {
2643 .name = "pattern_template",
2644 .help = "specify a pattern template id to destroy",
2645 .next = NEXT(next_pt_destroy_attr,
2646 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2647 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2648 args.templ_destroy.template_id)),
2649 .call = parse_template_destroy,
2651 [PATTERN_TEMPLATE_RELAXED_MATCHING] = {
2653 .help = "is matching relaxed",
2654 .next = NEXT(next_pt_attr,
2655 NEXT_ENTRY(COMMON_BOOLEAN)),
2656 .args = ARGS(ARGS_ENTRY_BF(struct buffer,
2657 args.vc.attr.reserved, 1)),
2659 [PATTERN_TEMPLATE_INGRESS] = {
2661 .help = "attribute pattern to ingress",
2662 .next = NEXT(next_pt_attr),
2663 .call = parse_template,
2665 [PATTERN_TEMPLATE_EGRESS] = {
2667 .help = "attribute pattern to egress",
2668 .next = NEXT(next_pt_attr),
2669 .call = parse_template,
2671 [PATTERN_TEMPLATE_TRANSFER] = {
2673 .help = "attribute pattern to transfer",
2674 .next = NEXT(next_pt_attr),
2675 .call = parse_template,
2677 [PATTERN_TEMPLATE_SPEC] = {
2679 .help = "specify item to create pattern template",
2680 .next = NEXT(next_item),
2682 /* Top-level command. */
2683 [ACTIONS_TEMPLATE] = {
2684 .name = "actions_template",
2685 .type = "{command} {port_id} [{arg} [...]]",
2686 .help = "manage actions templates",
2687 .next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2688 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2689 .call = parse_template,
2691 /* Sub-level commands. */
2692 [ACTIONS_TEMPLATE_CREATE] = {
2694 .help = "create actions template",
2695 .next = NEXT(next_at_attr),
2696 .call = parse_template,
2698 [ACTIONS_TEMPLATE_DESTROY] = {
2700 .help = "destroy actions template",
2701 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
2702 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2703 .call = parse_template_destroy,
2705 /* Actions template arguments. */
2706 [ACTIONS_TEMPLATE_CREATE_ID] = {
2707 .name = "actions_template_id",
2708 .help = "specify an actions template id to create",
2709 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
2710 NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
2711 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2712 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
2714 [ACTIONS_TEMPLATE_DESTROY_ID] = {
2715 .name = "actions_template",
2716 .help = "specify an actions template id to destroy",
2717 .next = NEXT(next_at_destroy_attr,
2718 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2719 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2720 args.templ_destroy.template_id)),
2721 .call = parse_template_destroy,
2723 [ACTIONS_TEMPLATE_INGRESS] = {
2725 .help = "attribute actions to ingress",
2726 .next = NEXT(next_at_attr),
2727 .call = parse_template,
2729 [ACTIONS_TEMPLATE_EGRESS] = {
2731 .help = "attribute actions to egress",
2732 .next = NEXT(next_at_attr),
2733 .call = parse_template,
2735 [ACTIONS_TEMPLATE_TRANSFER] = {
2737 .help = "attribute actions to transfer",
2738 .next = NEXT(next_at_attr),
2739 .call = parse_template,
2741 [ACTIONS_TEMPLATE_SPEC] = {
2743 .help = "specify action to create actions template",
2744 .next = NEXT(next_action),
2745 .call = parse_template,
2747 [ACTIONS_TEMPLATE_MASK] = {
2749 .help = "specify action mask to create actions template",
2750 .next = NEXT(next_action),
2751 .call = parse_template,
2753 /* Top-level command. */
2755 .name = "template_table",
2756 .type = "{command} {port_id} [{arg} [...]]",
2757 .help = "manage template tables",
2758 .next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2759 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2760 .call = parse_table,
2762 /* Sub-level commands. */
2765 .help = "create template table",
2766 .next = NEXT(next_table_attr),
2767 .call = parse_table,
2771 .help = "destroy template table",
2772 .next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
2773 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2774 .call = parse_table_destroy,
2776 /* Table arguments. */
2777 [TABLE_CREATE_ID] = {
2779 .help = "specify table id to create",
2780 .next = NEXT(next_table_attr,
2781 NEXT_ENTRY(COMMON_TABLE_ID)),
2782 .args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
2784 [TABLE_DESTROY_ID] = {
2786 .help = "specify table id to destroy",
2787 .next = NEXT(next_table_destroy_attr,
2788 NEXT_ENTRY(COMMON_TABLE_ID)),
2789 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2790 args.table_destroy.table_id)),
2791 .call = parse_table_destroy,
2795 .help = "specify a group",
2796 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2797 .args = ARGS(ARGS_ENTRY(struct buffer,
2798 args.table.attr.flow_attr.group)),
2800 [TABLE_PRIORITY] = {
2802 .help = "specify a priority level",
2803 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2804 .args = ARGS(ARGS_ENTRY(struct buffer,
2805 args.table.attr.flow_attr.priority)),
2809 .help = "affect rule to egress",
2810 .next = NEXT(next_table_attr),
2811 .call = parse_table,
2815 .help = "affect rule to ingress",
2816 .next = NEXT(next_table_attr),
2817 .call = parse_table,
2819 [TABLE_TRANSFER] = {
2821 .help = "affect rule to transfer",
2822 .next = NEXT(next_table_attr),
2823 .call = parse_table,
2825 [TABLE_RULES_NUMBER] = {
2826 .name = "rules_number",
2827 .help = "number of rules in table",
2828 .next = NEXT(next_table_attr,
2829 NEXT_ENTRY(COMMON_UNSIGNED)),
2830 .args = ARGS(ARGS_ENTRY(struct buffer,
2831 args.table.attr.nb_flows)),
2833 [TABLE_PATTERN_TEMPLATE] = {
2834 .name = "pattern_template",
2835 .help = "specify pattern template id",
2836 .next = NEXT(next_table_attr,
2837 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2838 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2839 args.table.pat_templ_id)),
2840 .call = parse_table,
2842 [TABLE_ACTIONS_TEMPLATE] = {
2843 .name = "actions_template",
2844 .help = "specify actions template id",
2845 .next = NEXT(next_table_attr,
2846 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2847 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2848 args.table.act_templ_id)),
2849 .call = parse_table,
2851 /* Top-level command. */
2854 .help = "queue a flow rule operation",
2855 .next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2856 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2859 /* Sub-level commands. */
2862 .help = "create a flow rule",
2863 .next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
2864 NEXT_ENTRY(COMMON_QUEUE_ID)),
2865 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2870 .help = "destroy a flow rule",
2871 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
2872 NEXT_ENTRY(COMMON_QUEUE_ID)),
2873 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2874 .call = parse_qo_destroy,
2876 /* Queue arguments. */
2877 [QUEUE_TEMPLATE_TABLE] = {
2878 .name = "template table",
2879 .help = "specify table id",
2880 .next = NEXT(NEXT_ENTRY(QUEUE_PATTERN_TEMPLATE),
2881 NEXT_ENTRY(COMMON_TABLE_ID)),
2882 .args = ARGS(ARGS_ENTRY(struct buffer,
2886 [QUEUE_PATTERN_TEMPLATE] = {
2887 .name = "pattern_template",
2888 .help = "specify pattern template index",
2889 .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
2890 NEXT_ENTRY(COMMON_UNSIGNED)),
2891 .args = ARGS(ARGS_ENTRY(struct buffer,
2892 args.vc.pat_templ_id)),
2895 [QUEUE_ACTIONS_TEMPLATE] = {
2896 .name = "actions_template",
2897 .help = "specify actions template index",
2898 .next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
2899 NEXT_ENTRY(COMMON_UNSIGNED)),
2900 .args = ARGS(ARGS_ENTRY(struct buffer,
2901 args.vc.act_templ_id)),
2904 [QUEUE_CREATE_POSTPONE] = {
2906 .help = "postpone create operation",
2907 .next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
2908 NEXT_ENTRY(COMMON_BOOLEAN)),
2909 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
2912 [QUEUE_DESTROY_POSTPONE] = {
2914 .help = "postpone destroy operation",
2915 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
2916 NEXT_ENTRY(COMMON_BOOLEAN)),
2917 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
2918 .call = parse_qo_destroy,
2920 [QUEUE_DESTROY_ID] = {
2922 .help = "specify rule id to destroy",
2923 .next = NEXT(next_queue_destroy_attr,
2924 NEXT_ENTRY(COMMON_UNSIGNED)),
2925 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2926 args.destroy.rule)),
2927 .call = parse_qo_destroy,
2929 /* Top-level command. */
2932 .help = "push enqueued operations",
2933 .next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
2934 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2937 /* Sub-level commands. */
2940 .help = "specify queue id",
2941 .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
2942 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2944 /* Top-level command. */
2947 .help = "pull flow operations results",
2948 .next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
2949 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2952 /* Sub-level commands. */
2955 .help = "specify queue id",
2956 .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
2957 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2959 /* Top-level command. */
2960 [INDIRECT_ACTION] = {
2961 .name = "indirect_action",
2962 .type = "{command} {port_id} [{arg} [...]]",
2963 .help = "manage indirect actions",
2964 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2965 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2968 /* Sub-level commands. */
2969 [INDIRECT_ACTION_CREATE] = {
2971 .help = "create indirect action",
2972 .next = NEXT(next_ia_create_attr),
2975 [INDIRECT_ACTION_UPDATE] = {
2977 .help = "update indirect action",
2978 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2979 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2980 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2983 [INDIRECT_ACTION_DESTROY] = {
2985 .help = "destroy indirect action",
2986 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2987 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2988 .call = parse_ia_destroy,
2990 [INDIRECT_ACTION_QUERY] = {
2992 .help = "query indirect action",
2993 .next = NEXT(NEXT_ENTRY(END),
2994 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2995 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3000 .help = "check whether a flow rule can be created",
3001 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3002 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3007 .help = "create a flow rule",
3008 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3009 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3014 .help = "destroy specific flow rules",
3015 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
3016 NEXT_ENTRY(COMMON_PORT_ID)),
3017 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3018 .call = parse_destroy,
3022 .help = "destroy all flow rules",
3023 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3024 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3025 .call = parse_flush,
3029 .help = "dump single/all flow rules to file",
3030 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3031 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3036 .help = "query an existing flow rule",
3037 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
3038 NEXT_ENTRY(COMMON_RULE_ID),
3039 NEXT_ENTRY(COMMON_PORT_ID)),
3040 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
3041 ARGS_ENTRY(struct buffer, args.query.rule),
3042 ARGS_ENTRY(struct buffer, port)),
3043 .call = parse_query,
3047 .help = "list existing flow rules",
3048 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3049 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3054 .help = "list and destroy aged flows",
3055 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3056 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3061 .help = "restrict ingress traffic to the defined flow rules",
3062 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
3063 NEXT_ENTRY(COMMON_PORT_ID)),
3064 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
3065 ARGS_ENTRY(struct buffer, port)),
3066 .call = parse_isolate,
3069 .name = "flex_item",
3070 .help = "flex item API",
3071 .next = NEXT(next_flex_item),
3074 [FLEX_ITEM_INIT] = {
3076 .help = "flex item init",
3077 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3078 ARGS_ENTRY(struct buffer, port)),
3079 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3080 NEXT_ENTRY(COMMON_PORT_ID)),
3083 [FLEX_ITEM_CREATE] = {
3085 .help = "flex item create",
3086 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
3087 ARGS_ENTRY(struct buffer, args.flex.token),
3088 ARGS_ENTRY(struct buffer, port)),
3089 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
3090 NEXT_ENTRY(COMMON_FLEX_TOKEN),
3091 NEXT_ENTRY(COMMON_PORT_ID)),
3094 [FLEX_ITEM_DESTROY] = {
3096 .help = "flex item destroy",
3097 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3098 ARGS_ENTRY(struct buffer, port)),
3099 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3100 NEXT_ENTRY(COMMON_PORT_ID)),
3105 .help = "new tunnel API",
3106 .next = NEXT(NEXT_ENTRY
3107 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
3108 .call = parse_tunnel,
3110 /* Tunnel arguments. */
3113 .help = "create new tunnel object",
3114 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
3115 NEXT_ENTRY(COMMON_PORT_ID)),
3116 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3117 .call = parse_tunnel,
3119 [TUNNEL_CREATE_TYPE] = {
3121 .help = "create new tunnel",
3122 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
3123 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
3124 .call = parse_tunnel,
3126 [TUNNEL_DESTROY] = {
3128 .help = "destroy tunnel",
3129 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
3130 NEXT_ENTRY(COMMON_PORT_ID)),
3131 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3132 .call = parse_tunnel,
3134 [TUNNEL_DESTROY_ID] = {
3136 .help = "tunnel identifier to destroy",
3137 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
3138 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3139 .call = parse_tunnel,
3143 .help = "list existing tunnels",
3144 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3145 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3146 .call = parse_tunnel,
3148 /* Destroy arguments. */
3151 .help = "specify a rule identifier",
3152 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3153 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
3154 .call = parse_destroy,
3156 /* Dump arguments. */
3160 .next = NEXT(next_dump_attr),
3161 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
3166 .help = "dump one rule",
3167 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3168 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
3169 ARGS_ENTRY(struct buffer, args.dump.rule)),
3172 /* Query arguments. */
3176 .help = "action to query, must be part of the rule",
3177 .call = parse_action,
3178 .comp = comp_action,
3180 /* List arguments. */
3183 .help = "specify a group",
3184 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3185 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
3190 .help = "specify aged flows need be destroyed",
3194 /* Validate/create attributes. */
3197 .help = "specify a group",
3198 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3199 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
3204 .help = "specify a priority level",
3205 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3206 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
3211 .help = "affect rule to ingress",
3212 .next = NEXT(next_vc_attr),
3217 .help = "affect rule to egress",
3218 .next = NEXT(next_vc_attr),
3223 .help = "apply rule directly to endpoints found in pattern",
3224 .next = NEXT(next_vc_attr),
3228 .name = "tunnel_set",
3229 .help = "tunnel steer rule",
3230 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3231 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3234 [VC_TUNNEL_MATCH] = {
3235 .name = "tunnel_match",
3236 .help = "tunnel match rule",
3237 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3238 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3241 /* Validate/create pattern. */
3244 .help = "submit a list of pattern items",
3245 .next = NEXT(next_item),
3250 .help = "match value perfectly (with full bit-mask)",
3251 .call = parse_vc_spec,
3253 [ITEM_PARAM_SPEC] = {
3255 .help = "match value according to configured bit-mask",
3256 .call = parse_vc_spec,
3258 [ITEM_PARAM_LAST] = {
3260 .help = "specify upper bound to establish a range",
3261 .call = parse_vc_spec,
3263 [ITEM_PARAM_MASK] = {
3265 .help = "specify bit-mask with relevant bits set to one",
3266 .call = parse_vc_spec,
3268 [ITEM_PARAM_PREFIX] = {
3270 .help = "generate bit-mask from a prefix length",
3271 .call = parse_vc_spec,
3275 .help = "specify next pattern item",
3276 .next = NEXT(next_item),
3280 .help = "end list of pattern items",
3281 .priv = PRIV_ITEM(END, 0),
3282 .next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3287 .help = "no-op pattern item",
3288 .priv = PRIV_ITEM(VOID, 0),
3289 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3294 .help = "perform actions when pattern does not match",
3295 .priv = PRIV_ITEM(INVERT, 0),
3296 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3301 .help = "match any protocol for the current layer",
3302 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
3303 .next = NEXT(item_any),
3308 .help = "number of layers covered",
3309 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3310 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
3314 .help = "match traffic from/to the physical function",
3315 .priv = PRIV_ITEM(PF, 0),
3316 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3321 .help = "match traffic from/to a virtual function ID",
3322 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
3323 .next = NEXT(item_vf),
3329 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3330 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
3334 .help = "match traffic from/to a specific physical port",
3335 .priv = PRIV_ITEM(PHY_PORT,
3336 sizeof(struct rte_flow_item_phy_port)),
3337 .next = NEXT(item_phy_port),
3340 [ITEM_PHY_PORT_INDEX] = {
3342 .help = "physical port index",
3343 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
3345 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
3349 .help = "match traffic from/to a given DPDK port ID",
3350 .priv = PRIV_ITEM(PORT_ID,
3351 sizeof(struct rte_flow_item_port_id)),
3352 .next = NEXT(item_port_id),
3355 [ITEM_PORT_ID_ID] = {
3357 .help = "DPDK port ID",
3358 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
3360 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
3364 .help = "match traffic against value set in previously matched rule",
3365 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
3366 .next = NEXT(item_mark),
3371 .help = "Integer value to match against",
3372 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
3374 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
3378 .help = "match an arbitrary byte string",
3379 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
3380 .next = NEXT(item_raw),
3383 [ITEM_RAW_RELATIVE] = {
3385 .help = "look for pattern after the previous item",
3386 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3387 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3390 [ITEM_RAW_SEARCH] = {
3392 .help = "search pattern from offset (see also limit)",
3393 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3394 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3397 [ITEM_RAW_OFFSET] = {
3399 .help = "absolute or relative offset for pattern",
3400 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
3401 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
3403 [ITEM_RAW_LIMIT] = {
3405 .help = "search area limit for start of pattern",
3406 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3407 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
3409 [ITEM_RAW_PATTERN] = {
3411 .help = "byte string to look for",
3412 .next = NEXT(item_raw,
3413 NEXT_ENTRY(COMMON_STRING),
3414 NEXT_ENTRY(ITEM_PARAM_IS,
3417 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3418 ARGS_ENTRY(struct rte_flow_item_raw, length),
3419 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3420 ITEM_RAW_PATTERN_SIZE)),
3422 [ITEM_RAW_PATTERN_HEX] = {
3423 .name = "pattern_hex",
3424 .help = "hex string to look for",
3425 .next = NEXT(item_raw,
3426 NEXT_ENTRY(COMMON_HEX),
3427 NEXT_ENTRY(ITEM_PARAM_IS,
3430 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3431 ARGS_ENTRY(struct rte_flow_item_raw, length),
3432 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3433 ITEM_RAW_PATTERN_SIZE)),
3437 .help = "match Ethernet header",
3438 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
3439 .next = NEXT(item_eth),
3444 .help = "destination MAC",
3445 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3446 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
3450 .help = "source MAC",
3451 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3452 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
3456 .help = "EtherType",
3457 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3458 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
3460 [ITEM_ETH_HAS_VLAN] = {
3462 .help = "packet header contains VLAN",
3463 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3464 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
3469 .help = "match 802.1Q/ad VLAN tag",
3470 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
3471 .next = NEXT(item_vlan),
3476 .help = "tag control information",
3477 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3479 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
3483 .help = "priority code point",
3484 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3486 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3491 .help = "drop eligible indicator",
3492 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3494 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3499 .help = "VLAN identifier",
3500 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3502 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3505 [ITEM_VLAN_INNER_TYPE] = {
3506 .name = "inner_type",
3507 .help = "inner EtherType",
3508 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3510 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
3513 [ITEM_VLAN_HAS_MORE_VLAN] = {
3514 .name = "has_more_vlan",
3515 .help = "packet header contains another VLAN",
3516 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3518 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
3523 .help = "match IPv4 header",
3524 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
3525 .next = NEXT(item_ipv4),
3528 [ITEM_IPV4_VER_IHL] = {
3529 .name = "version_ihl",
3530 .help = "match header length",
3531 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3533 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
3538 .help = "type of service",
3539 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3541 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3542 hdr.type_of_service)),
3545 .name = "packet_id",
3546 .help = "fragment packet id",
3547 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3549 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3552 [ITEM_IPV4_FRAGMENT_OFFSET] = {
3553 .name = "fragment_offset",
3554 .help = "fragmentation flags and fragment offset",
3555 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3557 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3558 hdr.fragment_offset)),
3562 .help = "time to live",
3563 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3565 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3568 [ITEM_IPV4_PROTO] = {
3570 .help = "next protocol ID",
3571 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3573 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3574 hdr.next_proto_id)),
3578 .help = "source address",
3579 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3581 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3586 .help = "destination address",
3587 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3589 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3594 .help = "match IPv6 header",
3595 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
3596 .next = NEXT(item_ipv6),
3601 .help = "traffic class",
3602 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3604 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3606 "\x0f\xf0\x00\x00")),
3608 [ITEM_IPV6_FLOW] = {
3610 .help = "flow label",
3611 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3613 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3615 "\x00\x0f\xff\xff")),
3617 [ITEM_IPV6_PROTO] = {
3619 .help = "protocol (next header)",
3620 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3622 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3627 .help = "hop limit",
3628 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3630 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3635 .help = "source address",
3636 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3638 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3643 .help = "destination address",
3644 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3646 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3649 [ITEM_IPV6_HAS_FRAG_EXT] = {
3650 .name = "has_frag_ext",
3651 .help = "fragment packet attribute",
3652 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3654 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
3659 .help = "match ICMP header",
3660 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
3661 .next = NEXT(item_icmp),
3664 [ITEM_ICMP_TYPE] = {
3666 .help = "ICMP packet type",
3667 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3669 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3672 [ITEM_ICMP_CODE] = {
3674 .help = "ICMP packet code",
3675 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3677 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3680 [ITEM_ICMP_IDENT] = {
3682 .help = "ICMP packet identifier",
3683 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3685 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3690 .help = "ICMP packet sequence number",
3691 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3693 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3698 .help = "match UDP header",
3699 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
3700 .next = NEXT(item_udp),
3705 .help = "UDP source port",
3706 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
3708 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3713 .help = "UDP destination port",
3714 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3715 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3720 .help = "match TCP header",
3721 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
3722 .next = NEXT(item_tcp),
3727 .help = "TCP source port",
3728 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3729 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3734 .help = "TCP destination port",
3735 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3736 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3739 [ITEM_TCP_FLAGS] = {
3741 .help = "TCP flags",
3742 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3743 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3748 .help = "match SCTP header",
3749 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
3750 .next = NEXT(item_sctp),
3755 .help = "SCTP source port",
3756 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3758 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3763 .help = "SCTP destination port",
3764 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3766 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3771 .help = "validation tag",
3772 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3774 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3777 [ITEM_SCTP_CKSUM] = {
3780 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3782 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3787 .help = "match VXLAN header",
3788 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
3789 .next = NEXT(item_vxlan),
3792 [ITEM_VXLAN_VNI] = {
3794 .help = "VXLAN identifier",
3795 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3797 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
3799 [ITEM_VXLAN_LAST_RSVD] = {
3800 .name = "last_rsvd",
3801 .help = "VXLAN last reserved bits",
3802 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3804 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
3809 .help = "match E-Tag header",
3810 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
3811 .next = NEXT(item_e_tag),
3814 [ITEM_E_TAG_GRP_ECID_B] = {
3815 .name = "grp_ecid_b",
3816 .help = "GRP and E-CID base",
3817 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3819 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
3825 .help = "match NVGRE header",
3826 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
3827 .next = NEXT(item_nvgre),
3830 [ITEM_NVGRE_TNI] = {
3832 .help = "virtual subnet ID",
3833 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
3835 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
3839 .help = "match MPLS header",
3840 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
3841 .next = NEXT(item_mpls),
3844 [ITEM_MPLS_LABEL] = {
3846 .help = "MPLS label",
3847 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3849 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3855 .help = "MPLS Traffic Class",
3856 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3858 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3864 .help = "MPLS Bottom-of-Stack",
3865 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3867 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3873 .help = "match GRE header",
3874 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
3875 .next = NEXT(item_gre),
3878 [ITEM_GRE_PROTO] = {
3880 .help = "GRE protocol type",
3881 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3883 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3886 [ITEM_GRE_C_RSVD0_VER] = {
3887 .name = "c_rsvd0_ver",
3889 "checksum (1b), undefined (1b), key bit (1b),"
3890 " sequence number (1b), reserved 0 (9b),"
3892 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3894 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3897 [ITEM_GRE_C_BIT] = {
3899 .help = "checksum bit (C)",
3900 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
3902 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3904 "\x80\x00\x00\x00")),
3906 [ITEM_GRE_S_BIT] = {
3908 .help = "sequence number bit (S)",
3909 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3910 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3912 "\x10\x00\x00\x00")),
3914 [ITEM_GRE_K_BIT] = {
3916 .help = "key bit (K)",
3917 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3918 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3920 "\x20\x00\x00\x00")),
3924 .help = "fuzzy pattern match, expect faster than default",
3925 .priv = PRIV_ITEM(FUZZY,
3926 sizeof(struct rte_flow_item_fuzzy)),
3927 .next = NEXT(item_fuzzy),
3930 [ITEM_FUZZY_THRESH] = {
3932 .help = "match accuracy threshold",
3933 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
3935 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
3940 .help = "match GTP header",
3941 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
3942 .next = NEXT(item_gtp),
3945 [ITEM_GTP_FLAGS] = {
3946 .name = "v_pt_rsv_flags",
3947 .help = "GTP flags",
3948 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3949 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3952 [ITEM_GTP_MSG_TYPE] = {
3954 .help = "GTP message type",
3955 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3956 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3960 .help = "tunnel endpoint identifier",
3961 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3962 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3966 .help = "match GTP header",
3967 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3968 .next = NEXT(item_gtp),
3973 .help = "match GTP header",
3974 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3975 .next = NEXT(item_gtp),
3980 .help = "match GENEVE header",
3981 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3982 .next = NEXT(item_geneve),
3985 [ITEM_GENEVE_VNI] = {
3987 .help = "virtual network identifier",
3988 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3990 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3992 [ITEM_GENEVE_PROTO] = {
3994 .help = "GENEVE protocol type",
3995 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3997 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
4000 [ITEM_GENEVE_OPTLEN] = {
4002 .help = "GENEVE options length in dwords",
4003 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4005 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
4006 ver_opt_len_o_c_rsvd0,
4009 [ITEM_VXLAN_GPE] = {
4010 .name = "vxlan-gpe",
4011 .help = "match VXLAN-GPE header",
4012 .priv = PRIV_ITEM(VXLAN_GPE,
4013 sizeof(struct rte_flow_item_vxlan_gpe)),
4014 .next = NEXT(item_vxlan_gpe),
4017 [ITEM_VXLAN_GPE_VNI] = {
4019 .help = "VXLAN-GPE identifier",
4020 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
4022 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
4025 [ITEM_ARP_ETH_IPV4] = {
4026 .name = "arp_eth_ipv4",
4027 .help = "match ARP header for Ethernet/IPv4",
4028 .priv = PRIV_ITEM(ARP_ETH_IPV4,
4029 sizeof(struct rte_flow_item_arp_eth_ipv4)),
4030 .next = NEXT(item_arp_eth_ipv4),
4033 [ITEM_ARP_ETH_IPV4_SHA] = {
4035 .help = "sender hardware address",
4036 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4038 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4041 [ITEM_ARP_ETH_IPV4_SPA] = {
4043 .help = "sender IPv4 address",
4044 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4046 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4049 [ITEM_ARP_ETH_IPV4_THA] = {
4051 .help = "target hardware address",
4052 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4054 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4057 [ITEM_ARP_ETH_IPV4_TPA] = {
4059 .help = "target IPv4 address",
4060 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4062 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4067 .help = "match presence of any IPv6 extension header",
4068 .priv = PRIV_ITEM(IPV6_EXT,
4069 sizeof(struct rte_flow_item_ipv6_ext)),
4070 .next = NEXT(item_ipv6_ext),
4073 [ITEM_IPV6_EXT_NEXT_HDR] = {
4075 .help = "next header",
4076 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4078 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
4081 [ITEM_IPV6_FRAG_EXT] = {
4082 .name = "ipv6_frag_ext",
4083 .help = "match presence of IPv6 fragment extension header",
4084 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
4085 sizeof(struct rte_flow_item_ipv6_frag_ext)),
4086 .next = NEXT(item_ipv6_frag_ext),
4089 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
4091 .help = "next header",
4092 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4094 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
4097 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
4098 .name = "frag_data",
4099 .help = "fragment flags and offset",
4100 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4102 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4105 [ITEM_IPV6_FRAG_EXT_ID] = {
4106 .name = "packet_id",
4107 .help = "fragment packet id",
4108 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4110 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4115 .help = "match any ICMPv6 header",
4116 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
4117 .next = NEXT(item_icmp6),
4120 [ITEM_ICMP6_TYPE] = {
4122 .help = "ICMPv6 type",
4123 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4125 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4128 [ITEM_ICMP6_CODE] = {
4130 .help = "ICMPv6 code",
4131 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4133 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4136 [ITEM_ICMP6_ND_NS] = {
4137 .name = "icmp6_nd_ns",
4138 .help = "match ICMPv6 neighbor discovery solicitation",
4139 .priv = PRIV_ITEM(ICMP6_ND_NS,
4140 sizeof(struct rte_flow_item_icmp6_nd_ns)),
4141 .next = NEXT(item_icmp6_nd_ns),
4144 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
4145 .name = "target_addr",
4146 .help = "target address",
4147 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
4149 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
4152 [ITEM_ICMP6_ND_NA] = {
4153 .name = "icmp6_nd_na",
4154 .help = "match ICMPv6 neighbor discovery advertisement",
4155 .priv = PRIV_ITEM(ICMP6_ND_NA,
4156 sizeof(struct rte_flow_item_icmp6_nd_na)),
4157 .next = NEXT(item_icmp6_nd_na),
4160 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
4161 .name = "target_addr",
4162 .help = "target address",
4163 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
4165 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
4168 [ITEM_ICMP6_ND_OPT] = {
4169 .name = "icmp6_nd_opt",
4170 .help = "match presence of any ICMPv6 neighbor discovery"
4172 .priv = PRIV_ITEM(ICMP6_ND_OPT,
4173 sizeof(struct rte_flow_item_icmp6_nd_opt)),
4174 .next = NEXT(item_icmp6_nd_opt),
4177 [ITEM_ICMP6_ND_OPT_TYPE] = {
4179 .help = "ND option type",
4180 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4182 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
4185 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
4186 .name = "icmp6_nd_opt_sla_eth",
4187 .help = "match ICMPv6 neighbor discovery source Ethernet"
4188 " link-layer address option",
4190 (ICMP6_ND_OPT_SLA_ETH,
4191 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
4192 .next = NEXT(item_icmp6_nd_opt_sla_eth),
4195 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
4197 .help = "source Ethernet LLA",
4198 .next = NEXT(item_icmp6_nd_opt_sla_eth,
4199 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4200 .args = ARGS(ARGS_ENTRY_HTON
4201 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
4203 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
4204 .name = "icmp6_nd_opt_tla_eth",
4205 .help = "match ICMPv6 neighbor discovery target Ethernet"
4206 " link-layer address option",
4208 (ICMP6_ND_OPT_TLA_ETH,
4209 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
4210 .next = NEXT(item_icmp6_nd_opt_tla_eth),
4213 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
4215 .help = "target Ethernet LLA",
4216 .next = NEXT(item_icmp6_nd_opt_tla_eth,
4217 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4218 .args = ARGS(ARGS_ENTRY_HTON
4219 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
4223 .help = "match metadata header",
4224 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
4225 .next = NEXT(item_meta),
4228 [ITEM_META_DATA] = {
4230 .help = "metadata value",
4231 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
4233 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
4234 data, "\xff\xff\xff\xff")),
4238 .help = "match GRE key",
4239 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
4240 .next = NEXT(item_gre_key),
4243 [ITEM_GRE_KEY_VALUE] = {
4245 .help = "key value",
4246 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
4248 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4250 [ITEM_GRE_OPTION] = {
4251 .name = "gre_option",
4252 .help = "match GRE optional fields",
4253 .priv = PRIV_ITEM(GRE_OPTION,
4254 sizeof(struct rte_flow_item_gre_opt)),
4255 .next = NEXT(item_gre_option),
4258 [ITEM_GRE_OPTION_CHECKSUM] = {
4260 .help = "match GRE checksum",
4261 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4263 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4264 checksum_rsvd.checksum)),
4266 [ITEM_GRE_OPTION_KEY] = {
4268 .help = "match GRE key",
4269 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4271 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4274 [ITEM_GRE_OPTION_SEQUENCE] = {
4276 .help = "match GRE sequence",
4277 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4279 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4280 sequence.sequence)),
4284 .help = "match GTP extension header with type 0x85",
4285 .priv = PRIV_ITEM(GTP_PSC,
4286 sizeof(struct rte_flow_item_gtp_psc)),
4287 .next = NEXT(item_gtp_psc),
4290 [ITEM_GTP_PSC_QFI] = {
4292 .help = "QoS flow identifier",
4293 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4295 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4298 [ITEM_GTP_PSC_PDU_T] = {
4301 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4303 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4308 .help = "match PPPoE session header",
4309 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
4310 .next = NEXT(item_pppoes),
4315 .help = "match PPPoE discovery header",
4316 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
4317 .next = NEXT(item_pppoed),
4320 [ITEM_PPPOE_SEID] = {
4322 .help = "session identifier",
4323 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
4325 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
4328 [ITEM_PPPOE_PROTO_ID] = {
4329 .name = "pppoe_proto_id",
4330 .help = "match PPPoE session protocol identifier",
4331 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
4332 sizeof(struct rte_flow_item_pppoe_proto_id)),
4333 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
4335 .args = ARGS(ARGS_ENTRY_HTON
4336 (struct rte_flow_item_pppoe_proto_id, proto_id)),
4341 .help = "matches higig2 header",
4342 .priv = PRIV_ITEM(HIGIG2,
4343 sizeof(struct rte_flow_item_higig2_hdr)),
4344 .next = NEXT(item_higig2),
4347 [ITEM_HIGIG2_CLASSIFICATION] = {
4348 .name = "classification",
4349 .help = "matches classification of higig2 header",
4350 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4352 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4353 hdr.ppt1.classification)),
4355 [ITEM_HIGIG2_VID] = {
4357 .help = "matches vid of higig2 header",
4358 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4360 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4365 .help = "match tag value",
4366 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
4367 .next = NEXT(item_tag),
4372 .help = "tag value to match",
4373 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4374 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
4376 [ITEM_TAG_INDEX] = {
4378 .help = "index of tag array to match",
4379 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4380 NEXT_ENTRY(ITEM_PARAM_IS)),
4381 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
4383 [ITEM_L2TPV3OIP] = {
4384 .name = "l2tpv3oip",
4385 .help = "match L2TPv3 over IP header",
4386 .priv = PRIV_ITEM(L2TPV3OIP,
4387 sizeof(struct rte_flow_item_l2tpv3oip)),
4388 .next = NEXT(item_l2tpv3oip),
4391 [ITEM_L2TPV3OIP_SESSION_ID] = {
4392 .name = "session_id",
4393 .help = "session identifier",
4394 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
4396 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
4401 .help = "match ESP header",
4402 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
4403 .next = NEXT(item_esp),
4408 .help = "security policy index",
4409 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4410 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
4415 .help = "match AH header",
4416 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
4417 .next = NEXT(item_ah),
4422 .help = "security parameters index",
4423 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4424 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
4428 .help = "match pfcp header",
4429 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
4430 .next = NEXT(item_pfcp),
4433 [ITEM_PFCP_S_FIELD] = {
4436 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
4438 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
4441 [ITEM_PFCP_SEID] = {
4443 .help = "session endpoint identifier",
4444 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
4446 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
4450 .help = "match eCPRI header",
4451 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
4452 .next = NEXT(item_ecpri),
4455 [ITEM_ECPRI_COMMON] = {
4457 .help = "eCPRI common header",
4458 .next = NEXT(item_ecpri_common),
4460 [ITEM_ECPRI_COMMON_TYPE] = {
4462 .help = "type of common header",
4463 .next = NEXT(item_ecpri_common_type),
4464 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
4466 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
4468 .help = "Type #0: IQ Data",
4469 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
4471 .call = parse_vc_item_ecpri_type,
4473 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
4475 .help = "Physical Channel ID",
4476 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
4477 ITEM_ECPRI_COMMON, ITEM_NEXT),
4478 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4479 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4482 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
4484 .help = "Type #2: Real-Time Control Data",
4485 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
4487 .call = parse_vc_item_ecpri_type,
4489 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
4491 .help = "Real-Time Control Data ID",
4492 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
4493 ITEM_ECPRI_COMMON, ITEM_NEXT),
4494 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4495 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4498 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
4499 .name = "delay_measure",
4500 .help = "Type #5: One-Way Delay Measurement",
4501 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
4503 .call = parse_vc_item_ecpri_type,
4505 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
4507 .help = "Measurement ID",
4508 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
4509 ITEM_ECPRI_COMMON, ITEM_NEXT),
4510 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4511 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4514 [ITEM_GENEVE_OPT] = {
4515 .name = "geneve-opt",
4516 .help = "GENEVE header option",
4517 .priv = PRIV_ITEM(GENEVE_OPT,
4518 sizeof(struct rte_flow_item_geneve_opt) +
4519 ITEM_GENEVE_OPT_DATA_SIZE),
4520 .next = NEXT(item_geneve_opt),
4523 [ITEM_GENEVE_OPT_CLASS] = {
4525 .help = "GENEVE option class",
4526 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4528 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
4531 [ITEM_GENEVE_OPT_TYPE] = {
4533 .help = "GENEVE option type",
4534 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4536 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
4539 [ITEM_GENEVE_OPT_LENGTH] = {
4541 .help = "GENEVE option data length (in 32b words)",
4542 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4544 .args = ARGS(ARGS_ENTRY_BOUNDED(
4545 struct rte_flow_item_geneve_opt, option_len,
4548 [ITEM_GENEVE_OPT_DATA] = {
4550 .help = "GENEVE option data pattern",
4551 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
4553 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
4554 ARGS_ENTRY_ARB(0, 0),
4556 (sizeof(struct rte_flow_item_geneve_opt),
4557 ITEM_GENEVE_OPT_DATA_SIZE)),
4559 [ITEM_INTEGRITY] = {
4560 .name = "integrity",
4561 .help = "match packet integrity",
4562 .priv = PRIV_ITEM(INTEGRITY,
4563 sizeof(struct rte_flow_item_integrity)),
4564 .next = NEXT(item_integrity),
4567 [ITEM_INTEGRITY_LEVEL] = {
4569 .help = "integrity level",
4570 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
4572 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
4574 [ITEM_INTEGRITY_VALUE] = {
4576 .help = "integrity value",
4577 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
4579 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
4581 [ITEM_CONNTRACK] = {
4582 .name = "conntrack",
4583 .help = "conntrack state",
4584 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
4586 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
4588 [ITEM_PORT_REPRESENTOR] = {
4589 .name = "port_representor",
4590 .help = "match traffic entering the embedded switch from the given ethdev",
4591 .priv = PRIV_ITEM(PORT_REPRESENTOR,
4592 sizeof(struct rte_flow_item_ethdev)),
4593 .next = NEXT(item_port_representor),
4596 [ITEM_PORT_REPRESENTOR_PORT_ID] = {
4598 .help = "ethdev port ID",
4599 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
4601 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4603 [ITEM_REPRESENTED_PORT] = {
4604 .name = "represented_port",
4605 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
4606 .priv = PRIV_ITEM(REPRESENTED_PORT,
4607 sizeof(struct rte_flow_item_ethdev)),
4608 .next = NEXT(item_represented_port),
4611 [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
4612 .name = "ethdev_port_id",
4613 .help = "ethdev port ID",
4614 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
4616 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4620 .help = "match flex header",
4621 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
4622 .next = NEXT(item_flex),
4625 [ITEM_FLEX_ITEM_HANDLE] = {
4627 .help = "flex item handle",
4628 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4629 NEXT_ENTRY(ITEM_PARAM_IS)),
4630 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
4632 [ITEM_FLEX_PATTERN_HANDLE] = {
4634 .help = "flex pattern handle",
4635 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4636 NEXT_ENTRY(ITEM_PARAM_IS)),
4637 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
4641 .help = "match L2TPv2 header",
4642 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
4643 .next = NEXT(item_l2tpv2),
4646 [ITEM_L2TPV2_TYPE] = {
4648 .help = "type of l2tpv2",
4649 .next = NEXT(item_l2tpv2_type),
4650 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
4652 [ITEM_L2TPV2_TYPE_DATA] = {
4654 .help = "Type #7: data message without any options",
4655 .next = NEXT(item_l2tpv2_type_data),
4656 .call = parse_vc_item_l2tpv2_type,
4658 [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
4659 .name = "tunnel_id",
4660 .help = "tunnel identifier",
4661 .next = NEXT(item_l2tpv2_type_data,
4662 NEXT_ENTRY(COMMON_UNSIGNED),
4664 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4665 hdr.type7.tunnel_id)),
4667 [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
4668 .name = "session_id",
4669 .help = "session identifier",
4670 .next = NEXT(item_l2tpv2_type_data,
4671 NEXT_ENTRY(COMMON_UNSIGNED),
4673 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4674 hdr.type7.session_id)),
4676 [ITEM_L2TPV2_TYPE_DATA_L] = {
4678 .help = "Type #6: data message with length option",
4679 .next = NEXT(item_l2tpv2_type_data_l),
4680 .call = parse_vc_item_l2tpv2_type,
4682 [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
4684 .help = "message length",
4685 .next = NEXT(item_l2tpv2_type_data_l,
4686 NEXT_ENTRY(COMMON_UNSIGNED),
4688 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4691 [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
4692 .name = "tunnel_id",
4693 .help = "tunnel identifier",
4694 .next = NEXT(item_l2tpv2_type_data_l,
4695 NEXT_ENTRY(COMMON_UNSIGNED),
4697 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4698 hdr.type6.tunnel_id)),
4700 [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
4701 .name = "session_id",
4702 .help = "session identifier",
4703 .next = NEXT(item_l2tpv2_type_data_l,
4704 NEXT_ENTRY(COMMON_UNSIGNED),
4706 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4707 hdr.type6.session_id)),
4709 [ITEM_L2TPV2_TYPE_DATA_S] = {
4711 .help = "Type #5: data message with ns, nr option",
4712 .next = NEXT(item_l2tpv2_type_data_s),
4713 .call = parse_vc_item_l2tpv2_type,
4715 [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
4716 .name = "tunnel_id",
4717 .help = "tunnel identifier",
4718 .next = NEXT(item_l2tpv2_type_data_s,
4719 NEXT_ENTRY(COMMON_UNSIGNED),
4721 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4722 hdr.type5.tunnel_id)),
4724 [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
4725 .name = "session_id",
4726 .help = "session identifier",
4727 .next = NEXT(item_l2tpv2_type_data_s,
4728 NEXT_ENTRY(COMMON_UNSIGNED),
4730 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4731 hdr.type5.session_id)),
4733 [ITEM_L2TPV2_MSG_DATA_S_NS] = {
4735 .help = "sequence number for message",
4736 .next = NEXT(item_l2tpv2_type_data_s,
4737 NEXT_ENTRY(COMMON_UNSIGNED),
4739 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4742 [ITEM_L2TPV2_MSG_DATA_S_NR] = {
4744 .help = "sequence number for next receive message",
4745 .next = NEXT(item_l2tpv2_type_data_s,
4746 NEXT_ENTRY(COMMON_UNSIGNED),
4748 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4751 [ITEM_L2TPV2_TYPE_DATA_O] = {
4753 .help = "Type #4: data message with offset option",
4754 .next = NEXT(item_l2tpv2_type_data_o),
4755 .call = parse_vc_item_l2tpv2_type,
4757 [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
4758 .name = "tunnel_id",
4759 .help = "tunnel identifier",
4760 .next = NEXT(item_l2tpv2_type_data_o,
4761 NEXT_ENTRY(COMMON_UNSIGNED),
4763 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4764 hdr.type4.tunnel_id)),
4766 [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
4767 .name = "session_id",
4768 .help = "session identifier",
4769 .next = NEXT(item_l2tpv2_type_data_o,
4770 NEXT_ENTRY(COMMON_UNSIGNED),
4772 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4773 hdr.type5.session_id)),
4775 [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
4776 .name = "offset_size",
4777 .help = "the size of offset padding",
4778 .next = NEXT(item_l2tpv2_type_data_o,
4779 NEXT_ENTRY(COMMON_UNSIGNED),
4781 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4782 hdr.type4.offset_size)),
4784 [ITEM_L2TPV2_TYPE_DATA_L_S] = {
4786 .help = "Type #3: data message contains length, ns, nr "
4788 .next = NEXT(item_l2tpv2_type_data_l_s),
4789 .call = parse_vc_item_l2tpv2_type,
4791 [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
4793 .help = "message length",
4794 .next = NEXT(item_l2tpv2_type_data_l_s,
4795 NEXT_ENTRY(COMMON_UNSIGNED),
4797 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4800 [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
4801 .name = "tunnel_id",
4802 .help = "tunnel identifier",
4803 .next = NEXT(item_l2tpv2_type_data_l_s,
4804 NEXT_ENTRY(COMMON_UNSIGNED),
4806 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4807 hdr.type3.tunnel_id)),
4809 [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
4810 .name = "session_id",
4811 .help = "session identifier",
4812 .next = NEXT(item_l2tpv2_type_data_l_s,
4813 NEXT_ENTRY(COMMON_UNSIGNED),
4815 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4816 hdr.type3.session_id)),
4818 [ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
4820 .help = "sequence number for message",
4821 .next = NEXT(item_l2tpv2_type_data_l_s,
4822 NEXT_ENTRY(COMMON_UNSIGNED),
4824 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4827 [ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
4829 .help = "sequence number for next receive message",
4830 .next = NEXT(item_l2tpv2_type_data_l_s,
4831 NEXT_ENTRY(COMMON_UNSIGNED),
4833 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4836 [ITEM_L2TPV2_TYPE_CTRL] = {
4838 .help = "Type #3: conrtol message contains length, ns, nr "
4840 .next = NEXT(item_l2tpv2_type_ctrl),
4841 .call = parse_vc_item_l2tpv2_type,
4843 [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
4845 .help = "message length",
4846 .next = NEXT(item_l2tpv2_type_ctrl,
4847 NEXT_ENTRY(COMMON_UNSIGNED),
4849 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4852 [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
4853 .name = "tunnel_id",
4854 .help = "tunnel identifier",
4855 .next = NEXT(item_l2tpv2_type_ctrl,
4856 NEXT_ENTRY(COMMON_UNSIGNED),
4858 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4859 hdr.type3.tunnel_id)),
4861 [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
4862 .name = "session_id",
4863 .help = "session identifier",
4864 .next = NEXT(item_l2tpv2_type_ctrl,
4865 NEXT_ENTRY(COMMON_UNSIGNED),
4867 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4868 hdr.type3.session_id)),
4870 [ITEM_L2TPV2_MSG_CTRL_NS] = {
4872 .help = "sequence number for message",
4873 .next = NEXT(item_l2tpv2_type_ctrl,
4874 NEXT_ENTRY(COMMON_UNSIGNED),
4876 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4879 [ITEM_L2TPV2_MSG_CTRL_NR] = {
4881 .help = "sequence number for next receive message",
4882 .next = NEXT(item_l2tpv2_type_ctrl,
4883 NEXT_ENTRY(COMMON_UNSIGNED),
4885 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4890 .help = "match PPP header",
4891 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
4892 .next = NEXT(item_ppp),
4897 .help = "PPP address",
4898 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4900 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
4904 .help = "PPP control",
4905 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4907 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
4909 [ITEM_PPP_PROTO_ID] = {
4911 .help = "PPP protocol identifier",
4912 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4914 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
4917 /* Validate/create actions. */
4920 .help = "submit a list of associated actions",
4921 .next = NEXT(next_action),
4926 .help = "specify next action",
4927 .next = NEXT(next_action),
4931 .help = "end list of actions",
4932 .priv = PRIV_ACTION(END, 0),
4937 .help = "no-op action",
4938 .priv = PRIV_ACTION(VOID, 0),
4939 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4942 [ACTION_PASSTHRU] = {
4944 .help = "let subsequent rule process matched packets",
4945 .priv = PRIV_ACTION(PASSTHRU, 0),
4946 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4951 .help = "redirect traffic to a given group",
4952 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
4953 .next = NEXT(action_jump),
4956 [ACTION_JUMP_GROUP] = {
4958 .help = "group to redirect traffic to",
4959 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
4960 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
4961 .call = parse_vc_conf,
4965 .help = "attach 32 bit value to packets",
4966 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
4967 .next = NEXT(action_mark),
4970 [ACTION_MARK_ID] = {
4972 .help = "32 bit value to return with packets",
4973 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
4974 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
4975 .call = parse_vc_conf,
4979 .help = "flag packets",
4980 .priv = PRIV_ACTION(FLAG, 0),
4981 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4986 .help = "assign packets to a given queue index",
4987 .priv = PRIV_ACTION(QUEUE,
4988 sizeof(struct rte_flow_action_queue)),
4989 .next = NEXT(action_queue),
4992 [ACTION_QUEUE_INDEX] = {
4994 .help = "queue index to use",
4995 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
4996 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
4997 .call = parse_vc_conf,
5001 .help = "drop packets (note: passthru has priority)",
5002 .priv = PRIV_ACTION(DROP, 0),
5003 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5008 .help = "enable counters for this rule",
5009 .priv = PRIV_ACTION(COUNT,
5010 sizeof(struct rte_flow_action_count)),
5011 .next = NEXT(action_count),
5014 [ACTION_COUNT_ID] = {
5015 .name = "identifier",
5016 .help = "counter identifier to use",
5017 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
5018 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
5019 .call = parse_vc_conf,
5023 .help = "spread packets among several queues",
5024 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
5025 .next = NEXT(action_rss),
5026 .call = parse_vc_action_rss,
5028 [ACTION_RSS_FUNC] = {
5030 .help = "RSS hash function to apply",
5031 .next = NEXT(action_rss,
5032 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
5033 ACTION_RSS_FUNC_TOEPLITZ,
5034 ACTION_RSS_FUNC_SIMPLE_XOR,
5035 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
5037 [ACTION_RSS_FUNC_DEFAULT] = {
5039 .help = "default hash function",
5040 .call = parse_vc_action_rss_func,
5042 [ACTION_RSS_FUNC_TOEPLITZ] = {
5044 .help = "Toeplitz hash function",
5045 .call = parse_vc_action_rss_func,
5047 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
5048 .name = "simple_xor",
5049 .help = "simple XOR hash function",
5050 .call = parse_vc_action_rss_func,
5052 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
5053 .name = "symmetric_toeplitz",
5054 .help = "Symmetric Toeplitz hash function",
5055 .call = parse_vc_action_rss_func,
5057 [ACTION_RSS_LEVEL] = {
5059 .help = "encapsulation level for \"types\"",
5060 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5061 .args = ARGS(ARGS_ENTRY_ARB
5062 (offsetof(struct action_rss_data, conf) +
5063 offsetof(struct rte_flow_action_rss, level),
5064 sizeof(((struct rte_flow_action_rss *)0)->
5067 [ACTION_RSS_TYPES] = {
5069 .help = "specific RSS hash types",
5070 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
5072 [ACTION_RSS_TYPE] = {
5074 .help = "RSS hash type",
5075 .call = parse_vc_action_rss_type,
5076 .comp = comp_vc_action_rss_type,
5078 [ACTION_RSS_KEY] = {
5080 .help = "RSS hash key",
5081 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
5082 .args = ARGS(ARGS_ENTRY_ARB
5083 (offsetof(struct action_rss_data, conf) +
5084 offsetof(struct rte_flow_action_rss, key),
5085 sizeof(((struct rte_flow_action_rss *)0)->key)),
5087 (offsetof(struct action_rss_data, conf) +
5088 offsetof(struct rte_flow_action_rss, key_len),
5089 sizeof(((struct rte_flow_action_rss *)0)->
5091 ARGS_ENTRY(struct action_rss_data, key)),
5093 [ACTION_RSS_KEY_LEN] = {
5095 .help = "RSS hash key length in bytes",
5096 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5097 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5098 (offsetof(struct action_rss_data, conf) +
5099 offsetof(struct rte_flow_action_rss, key_len),
5100 sizeof(((struct rte_flow_action_rss *)0)->
5103 RSS_HASH_KEY_LENGTH)),
5105 [ACTION_RSS_QUEUES] = {
5107 .help = "queue indices to use",
5108 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
5109 .call = parse_vc_conf,
5111 [ACTION_RSS_QUEUE] = {
5113 .help = "queue index",
5114 .call = parse_vc_action_rss_queue,
5115 .comp = comp_vc_action_rss_queue,
5119 .help = "direct traffic to physical function",
5120 .priv = PRIV_ACTION(PF, 0),
5121 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5126 .help = "direct traffic to a virtual function ID",
5127 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
5128 .next = NEXT(action_vf),
5131 [ACTION_VF_ORIGINAL] = {
5133 .help = "use original VF ID if possible",
5134 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
5135 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
5137 .call = parse_vc_conf,
5142 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
5143 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
5144 .call = parse_vc_conf,
5146 [ACTION_PHY_PORT] = {
5148 .help = "direct packets to physical port index",
5149 .priv = PRIV_ACTION(PHY_PORT,
5150 sizeof(struct rte_flow_action_phy_port)),
5151 .next = NEXT(action_phy_port),
5154 [ACTION_PHY_PORT_ORIGINAL] = {
5156 .help = "use original port index if possible",
5157 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
5158 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
5160 .call = parse_vc_conf,
5162 [ACTION_PHY_PORT_INDEX] = {
5164 .help = "physical port index",
5165 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
5166 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
5168 .call = parse_vc_conf,
5170 [ACTION_PORT_ID] = {
5172 .help = "direct matching traffic to a given DPDK port ID",
5173 .priv = PRIV_ACTION(PORT_ID,
5174 sizeof(struct rte_flow_action_port_id)),
5175 .next = NEXT(action_port_id),
5178 [ACTION_PORT_ID_ORIGINAL] = {
5180 .help = "use original DPDK port ID if possible",
5181 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
5182 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
5184 .call = parse_vc_conf,
5186 [ACTION_PORT_ID_ID] = {
5188 .help = "DPDK port ID",
5189 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
5190 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
5191 .call = parse_vc_conf,
5195 .help = "meter the directed packets at given id",
5196 .priv = PRIV_ACTION(METER,
5197 sizeof(struct rte_flow_action_meter)),
5198 .next = NEXT(action_meter),
5201 [ACTION_METER_COLOR] = {
5203 .help = "meter color for the packets",
5204 .priv = PRIV_ACTION(METER_COLOR,
5205 sizeof(struct rte_flow_action_meter_color)),
5206 .next = NEXT(action_meter_color),
5209 [ACTION_METER_COLOR_TYPE] = {
5211 .help = "specific meter color",
5212 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5213 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
5214 ACTION_METER_COLOR_YELLOW,
5215 ACTION_METER_COLOR_RED)),
5217 [ACTION_METER_COLOR_GREEN] = {
5219 .help = "meter color green",
5220 .call = parse_vc_action_meter_color_type,
5222 [ACTION_METER_COLOR_YELLOW] = {
5224 .help = "meter color yellow",
5225 .call = parse_vc_action_meter_color_type,
5227 [ACTION_METER_COLOR_RED] = {
5229 .help = "meter color red",
5230 .call = parse_vc_action_meter_color_type,
5232 [ACTION_METER_ID] = {
5234 .help = "meter id to use",
5235 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
5236 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
5237 .call = parse_vc_conf,
5239 [ACTION_OF_SET_MPLS_TTL] = {
5240 .name = "of_set_mpls_ttl",
5241 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
5244 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
5245 .next = NEXT(action_of_set_mpls_ttl),
5248 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
5251 .next = NEXT(action_of_set_mpls_ttl,
5252 NEXT_ENTRY(COMMON_UNSIGNED)),
5253 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
5255 .call = parse_vc_conf,
5257 [ACTION_OF_DEC_MPLS_TTL] = {
5258 .name = "of_dec_mpls_ttl",
5259 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
5260 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
5261 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5264 [ACTION_OF_SET_NW_TTL] = {
5265 .name = "of_set_nw_ttl",
5266 .help = "OpenFlow's OFPAT_SET_NW_TTL",
5269 sizeof(struct rte_flow_action_of_set_nw_ttl)),
5270 .next = NEXT(action_of_set_nw_ttl),
5273 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
5276 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5277 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
5279 .call = parse_vc_conf,
5281 [ACTION_OF_DEC_NW_TTL] = {
5282 .name = "of_dec_nw_ttl",
5283 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
5284 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
5285 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5288 [ACTION_OF_COPY_TTL_OUT] = {
5289 .name = "of_copy_ttl_out",
5290 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
5291 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
5292 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5295 [ACTION_OF_COPY_TTL_IN] = {
5296 .name = "of_copy_ttl_in",
5297 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
5298 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
5299 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5302 [ACTION_OF_POP_VLAN] = {
5303 .name = "of_pop_vlan",
5304 .help = "OpenFlow's OFPAT_POP_VLAN",
5305 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
5306 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5309 [ACTION_OF_PUSH_VLAN] = {
5310 .name = "of_push_vlan",
5311 .help = "OpenFlow's OFPAT_PUSH_VLAN",
5314 sizeof(struct rte_flow_action_of_push_vlan)),
5315 .next = NEXT(action_of_push_vlan),
5318 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
5319 .name = "ethertype",
5320 .help = "EtherType",
5321 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
5322 .args = ARGS(ARGS_ENTRY_HTON
5323 (struct rte_flow_action_of_push_vlan,
5325 .call = parse_vc_conf,
5327 [ACTION_OF_SET_VLAN_VID] = {
5328 .name = "of_set_vlan_vid",
5329 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
5332 sizeof(struct rte_flow_action_of_set_vlan_vid)),
5333 .next = NEXT(action_of_set_vlan_vid),
5336 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
5339 .next = NEXT(action_of_set_vlan_vid,
5340 NEXT_ENTRY(COMMON_UNSIGNED)),
5341 .args = ARGS(ARGS_ENTRY_HTON
5342 (struct rte_flow_action_of_set_vlan_vid,
5344 .call = parse_vc_conf,
5346 [ACTION_OF_SET_VLAN_PCP] = {
5347 .name = "of_set_vlan_pcp",
5348 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
5351 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
5352 .next = NEXT(action_of_set_vlan_pcp),
5355 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
5357 .help = "VLAN priority",
5358 .next = NEXT(action_of_set_vlan_pcp,
5359 NEXT_ENTRY(COMMON_UNSIGNED)),
5360 .args = ARGS(ARGS_ENTRY_HTON
5361 (struct rte_flow_action_of_set_vlan_pcp,
5363 .call = parse_vc_conf,
5365 [ACTION_OF_POP_MPLS] = {
5366 .name = "of_pop_mpls",
5367 .help = "OpenFlow's OFPAT_POP_MPLS",
5368 .priv = PRIV_ACTION(OF_POP_MPLS,
5369 sizeof(struct rte_flow_action_of_pop_mpls)),
5370 .next = NEXT(action_of_pop_mpls),
5373 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
5374 .name = "ethertype",
5375 .help = "EtherType",
5376 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5377 .args = ARGS(ARGS_ENTRY_HTON
5378 (struct rte_flow_action_of_pop_mpls,
5380 .call = parse_vc_conf,
5382 [ACTION_OF_PUSH_MPLS] = {
5383 .name = "of_push_mpls",
5384 .help = "OpenFlow's OFPAT_PUSH_MPLS",
5387 sizeof(struct rte_flow_action_of_push_mpls)),
5388 .next = NEXT(action_of_push_mpls),
5391 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
5392 .name = "ethertype",
5393 .help = "EtherType",
5394 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5395 .args = ARGS(ARGS_ENTRY_HTON
5396 (struct rte_flow_action_of_push_mpls,
5398 .call = parse_vc_conf,
5400 [ACTION_VXLAN_ENCAP] = {
5401 .name = "vxlan_encap",
5402 .help = "VXLAN encapsulation, uses configuration set by \"set"
5404 .priv = PRIV_ACTION(VXLAN_ENCAP,
5405 sizeof(struct action_vxlan_encap_data)),
5406 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5407 .call = parse_vc_action_vxlan_encap,
5409 [ACTION_VXLAN_DECAP] = {
5410 .name = "vxlan_decap",
5411 .help = "Performs a decapsulation action by stripping all"
5412 " headers of the VXLAN tunnel network overlay from the"
5414 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
5415 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5418 [ACTION_NVGRE_ENCAP] = {
5419 .name = "nvgre_encap",
5420 .help = "NVGRE encapsulation, uses configuration set by \"set"
5422 .priv = PRIV_ACTION(NVGRE_ENCAP,
5423 sizeof(struct action_nvgre_encap_data)),
5424 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5425 .call = parse_vc_action_nvgre_encap,
5427 [ACTION_NVGRE_DECAP] = {
5428 .name = "nvgre_decap",
5429 .help = "Performs a decapsulation action by stripping all"
5430 " headers of the NVGRE tunnel network overlay from the"
5432 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
5433 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5436 [ACTION_L2_ENCAP] = {
5438 .help = "l2 encap, uses configuration set by"
5439 " \"set l2_encap\"",
5440 .priv = PRIV_ACTION(RAW_ENCAP,
5441 sizeof(struct action_raw_encap_data)),
5442 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5443 .call = parse_vc_action_l2_encap,
5445 [ACTION_L2_DECAP] = {
5447 .help = "l2 decap, uses configuration set by"
5448 " \"set l2_decap\"",
5449 .priv = PRIV_ACTION(RAW_DECAP,
5450 sizeof(struct action_raw_decap_data)),
5451 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5452 .call = parse_vc_action_l2_decap,
5454 [ACTION_MPLSOGRE_ENCAP] = {
5455 .name = "mplsogre_encap",
5456 .help = "mplsogre encapsulation, uses configuration set by"
5457 " \"set mplsogre_encap\"",
5458 .priv = PRIV_ACTION(RAW_ENCAP,
5459 sizeof(struct action_raw_encap_data)),
5460 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5461 .call = parse_vc_action_mplsogre_encap,
5463 [ACTION_MPLSOGRE_DECAP] = {
5464 .name = "mplsogre_decap",
5465 .help = "mplsogre decapsulation, uses configuration set by"
5466 " \"set mplsogre_decap\"",
5467 .priv = PRIV_ACTION(RAW_DECAP,
5468 sizeof(struct action_raw_decap_data)),
5469 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5470 .call = parse_vc_action_mplsogre_decap,
5472 [ACTION_MPLSOUDP_ENCAP] = {
5473 .name = "mplsoudp_encap",
5474 .help = "mplsoudp encapsulation, uses configuration set by"
5475 " \"set mplsoudp_encap\"",
5476 .priv = PRIV_ACTION(RAW_ENCAP,
5477 sizeof(struct action_raw_encap_data)),
5478 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5479 .call = parse_vc_action_mplsoudp_encap,
5481 [ACTION_MPLSOUDP_DECAP] = {
5482 .name = "mplsoudp_decap",
5483 .help = "mplsoudp decapsulation, uses configuration set by"
5484 " \"set mplsoudp_decap\"",
5485 .priv = PRIV_ACTION(RAW_DECAP,
5486 sizeof(struct action_raw_decap_data)),
5487 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5488 .call = parse_vc_action_mplsoudp_decap,
5490 [ACTION_SET_IPV4_SRC] = {
5491 .name = "set_ipv4_src",
5492 .help = "Set a new IPv4 source address in the outermost"
5494 .priv = PRIV_ACTION(SET_IPV4_SRC,
5495 sizeof(struct rte_flow_action_set_ipv4)),
5496 .next = NEXT(action_set_ipv4_src),
5499 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
5500 .name = "ipv4_addr",
5501 .help = "new IPv4 source address to set",
5502 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
5503 .args = ARGS(ARGS_ENTRY_HTON
5504 (struct rte_flow_action_set_ipv4, ipv4_addr)),
5505 .call = parse_vc_conf,
5507 [ACTION_SET_IPV4_DST] = {
5508 .name = "set_ipv4_dst",
5509 .help = "Set a new IPv4 destination address in the outermost"
5511 .priv = PRIV_ACTION(SET_IPV4_DST,
5512 sizeof(struct rte_flow_action_set_ipv4)),
5513 .next = NEXT(action_set_ipv4_dst),
5516 [ACTION_SET_IPV4_DST_IPV4_DST] = {
5517 .name = "ipv4_addr",
5518 .help = "new IPv4 destination address to set",
5519 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
5520 .args = ARGS(ARGS_ENTRY_HTON
5521 (struct rte_flow_action_set_ipv4, ipv4_addr)),
5522 .call = parse_vc_conf,
5524 [ACTION_SET_IPV6_SRC] = {
5525 .name = "set_ipv6_src",
5526 .help = "Set a new IPv6 source address in the outermost"
5528 .priv = PRIV_ACTION(SET_IPV6_SRC,
5529 sizeof(struct rte_flow_action_set_ipv6)),
5530 .next = NEXT(action_set_ipv6_src),
5533 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
5534 .name = "ipv6_addr",
5535 .help = "new IPv6 source address to set",
5536 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
5537 .args = ARGS(ARGS_ENTRY_HTON
5538 (struct rte_flow_action_set_ipv6, ipv6_addr)),
5539 .call = parse_vc_conf,
5541 [ACTION_SET_IPV6_DST] = {
5542 .name = "set_ipv6_dst",
5543 .help = "Set a new IPv6 destination address in the outermost"
5545 .priv = PRIV_ACTION(SET_IPV6_DST,
5546 sizeof(struct rte_flow_action_set_ipv6)),
5547 .next = NEXT(action_set_ipv6_dst),
5550 [ACTION_SET_IPV6_DST_IPV6_DST] = {
5551 .name = "ipv6_addr",
5552 .help = "new IPv6 destination address to set",
5553 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
5554 .args = ARGS(ARGS_ENTRY_HTON
5555 (struct rte_flow_action_set_ipv6, ipv6_addr)),
5556 .call = parse_vc_conf,
5558 [ACTION_SET_TP_SRC] = {
5559 .name = "set_tp_src",
5560 .help = "set a new source port number in the outermost"
5562 .priv = PRIV_ACTION(SET_TP_SRC,
5563 sizeof(struct rte_flow_action_set_tp)),
5564 .next = NEXT(action_set_tp_src),
5567 [ACTION_SET_TP_SRC_TP_SRC] = {
5569 .help = "new source port number to set",
5570 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
5571 .args = ARGS(ARGS_ENTRY_HTON
5572 (struct rte_flow_action_set_tp, port)),
5573 .call = parse_vc_conf,
5575 [ACTION_SET_TP_DST] = {
5576 .name = "set_tp_dst",
5577 .help = "set a new destination port number in the outermost"
5579 .priv = PRIV_ACTION(SET_TP_DST,
5580 sizeof(struct rte_flow_action_set_tp)),
5581 .next = NEXT(action_set_tp_dst),
5584 [ACTION_SET_TP_DST_TP_DST] = {
5586 .help = "new destination port number to set",
5587 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
5588 .args = ARGS(ARGS_ENTRY_HTON
5589 (struct rte_flow_action_set_tp, port)),
5590 .call = parse_vc_conf,
5592 [ACTION_MAC_SWAP] = {
5594 .help = "Swap the source and destination MAC addresses"
5595 " in the outermost Ethernet header",
5596 .priv = PRIV_ACTION(MAC_SWAP, 0),
5597 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5600 [ACTION_DEC_TTL] = {
5602 .help = "decrease network TTL if available",
5603 .priv = PRIV_ACTION(DEC_TTL, 0),
5604 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5607 [ACTION_SET_TTL] = {
5609 .help = "set ttl value",
5610 .priv = PRIV_ACTION(SET_TTL,
5611 sizeof(struct rte_flow_action_set_ttl)),
5612 .next = NEXT(action_set_ttl),
5615 [ACTION_SET_TTL_TTL] = {
5616 .name = "ttl_value",
5617 .help = "new ttl value to set",
5618 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5619 .args = ARGS(ARGS_ENTRY_HTON
5620 (struct rte_flow_action_set_ttl, ttl_value)),
5621 .call = parse_vc_conf,
5623 [ACTION_SET_MAC_SRC] = {
5624 .name = "set_mac_src",
5625 .help = "set source mac address",
5626 .priv = PRIV_ACTION(SET_MAC_SRC,
5627 sizeof(struct rte_flow_action_set_mac)),
5628 .next = NEXT(action_set_mac_src),
5631 [ACTION_SET_MAC_SRC_MAC_SRC] = {
5633 .help = "new source mac address",
5634 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
5635 .args = ARGS(ARGS_ENTRY_HTON
5636 (struct rte_flow_action_set_mac, mac_addr)),
5637 .call = parse_vc_conf,
5639 [ACTION_SET_MAC_DST] = {
5640 .name = "set_mac_dst",
5641 .help = "set destination mac address",
5642 .priv = PRIV_ACTION(SET_MAC_DST,
5643 sizeof(struct rte_flow_action_set_mac)),
5644 .next = NEXT(action_set_mac_dst),
5647 [ACTION_SET_MAC_DST_MAC_DST] = {
5649 .help = "new destination mac address to set",
5650 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
5651 .args = ARGS(ARGS_ENTRY_HTON
5652 (struct rte_flow_action_set_mac, mac_addr)),
5653 .call = parse_vc_conf,
5655 [ACTION_INC_TCP_SEQ] = {
5656 .name = "inc_tcp_seq",
5657 .help = "increase TCP sequence number",
5658 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
5659 .next = NEXT(action_inc_tcp_seq),
5662 [ACTION_INC_TCP_SEQ_VALUE] = {
5664 .help = "the value to increase TCP sequence number by",
5665 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5666 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5667 .call = parse_vc_conf,
5669 [ACTION_DEC_TCP_SEQ] = {
5670 .name = "dec_tcp_seq",
5671 .help = "decrease TCP sequence number",
5672 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
5673 .next = NEXT(action_dec_tcp_seq),
5676 [ACTION_DEC_TCP_SEQ_VALUE] = {
5678 .help = "the value to decrease TCP sequence number by",
5679 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5680 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5681 .call = parse_vc_conf,
5683 [ACTION_INC_TCP_ACK] = {
5684 .name = "inc_tcp_ack",
5685 .help = "increase TCP acknowledgment number",
5686 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
5687 .next = NEXT(action_inc_tcp_ack),
5690 [ACTION_INC_TCP_ACK_VALUE] = {
5692 .help = "the value to increase TCP acknowledgment number by",
5693 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5694 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5695 .call = parse_vc_conf,
5697 [ACTION_DEC_TCP_ACK] = {
5698 .name = "dec_tcp_ack",
5699 .help = "decrease TCP acknowledgment number",
5700 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
5701 .next = NEXT(action_dec_tcp_ack),
5704 [ACTION_DEC_TCP_ACK_VALUE] = {
5706 .help = "the value to decrease TCP acknowledgment number by",
5707 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5708 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5709 .call = parse_vc_conf,
5711 [ACTION_RAW_ENCAP] = {
5712 .name = "raw_encap",
5713 .help = "encapsulation data, defined by set raw_encap",
5714 .priv = PRIV_ACTION(RAW_ENCAP,
5715 sizeof(struct action_raw_encap_data)),
5716 .next = NEXT(action_raw_encap),
5717 .call = parse_vc_action_raw_encap,
5719 [ACTION_RAW_ENCAP_INDEX] = {
5721 .help = "the index of raw_encap_confs",
5722 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
5724 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
5727 .help = "unsigned integer value",
5728 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5729 .call = parse_vc_action_raw_encap_index,
5730 .comp = comp_set_raw_index,
5732 [ACTION_RAW_DECAP] = {
5733 .name = "raw_decap",
5734 .help = "decapsulation data, defined by set raw_encap",
5735 .priv = PRIV_ACTION(RAW_DECAP,
5736 sizeof(struct action_raw_decap_data)),
5737 .next = NEXT(action_raw_decap),
5738 .call = parse_vc_action_raw_decap,
5740 [ACTION_RAW_DECAP_INDEX] = {
5742 .help = "the index of raw_encap_confs",
5743 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
5745 [ACTION_RAW_DECAP_INDEX_VALUE] = {
5748 .help = "unsigned integer value",
5749 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5750 .call = parse_vc_action_raw_decap_index,
5751 .comp = comp_set_raw_index,
5753 [ACTION_MODIFY_FIELD] = {
5754 .name = "modify_field",
5755 .help = "modify destination field with data from source field",
5756 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
5757 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
5760 [ACTION_MODIFY_FIELD_OP] = {
5762 .help = "operation type",
5763 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
5764 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
5765 .call = parse_vc_conf,
5767 [ACTION_MODIFY_FIELD_OP_VALUE] = {
5768 .name = "{operation}",
5769 .help = "operation type value",
5770 .call = parse_vc_modify_field_op,
5771 .comp = comp_set_modify_field_op,
5773 [ACTION_MODIFY_FIELD_DST_TYPE] = {
5775 .help = "destination field type",
5776 .next = NEXT(action_modify_field_dst,
5777 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
5778 .call = parse_vc_conf,
5780 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
5781 .name = "{dst_type}",
5782 .help = "destination field type value",
5783 .call = parse_vc_modify_field_id,
5784 .comp = comp_set_modify_field_id,
5786 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
5787 .name = "dst_level",
5788 .help = "destination field level",
5789 .next = NEXT(action_modify_field_dst,
5790 NEXT_ENTRY(COMMON_UNSIGNED)),
5791 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5793 .call = parse_vc_conf,
5795 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
5796 .name = "dst_offset",
5797 .help = "destination field bit offset",
5798 .next = NEXT(action_modify_field_dst,
5799 NEXT_ENTRY(COMMON_UNSIGNED)),
5800 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5802 .call = parse_vc_conf,
5804 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
5806 .help = "source field type",
5807 .next = NEXT(action_modify_field_src,
5808 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
5809 .call = parse_vc_conf,
5811 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
5812 .name = "{src_type}",
5813 .help = "source field type value",
5814 .call = parse_vc_modify_field_id,
5815 .comp = comp_set_modify_field_id,
5817 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
5818 .name = "src_level",
5819 .help = "source field level",
5820 .next = NEXT(action_modify_field_src,
5821 NEXT_ENTRY(COMMON_UNSIGNED)),
5822 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5824 .call = parse_vc_conf,
5826 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
5827 .name = "src_offset",
5828 .help = "source field bit offset",
5829 .next = NEXT(action_modify_field_src,
5830 NEXT_ENTRY(COMMON_UNSIGNED)),
5831 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5833 .call = parse_vc_conf,
5835 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
5836 .name = "src_value",
5837 .help = "source immediate value",
5838 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5839 NEXT_ENTRY(COMMON_HEX)),
5840 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
5841 ARGS_ENTRY_ARB(0, 0),
5842 ARGS_ENTRY(struct rte_flow_action_modify_field,
5844 .call = parse_vc_conf,
5846 [ACTION_MODIFY_FIELD_SRC_POINTER] = {
5848 .help = "pointer to source immediate value",
5849 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5850 NEXT_ENTRY(COMMON_HEX)),
5851 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5853 ARGS_ENTRY_ARB(0, 0),
5855 (sizeof(struct rte_flow_action_modify_field),
5856 ACTION_MODIFY_PATTERN_SIZE)),
5857 .call = parse_vc_conf,
5859 [ACTION_MODIFY_FIELD_WIDTH] = {
5861 .help = "number of bits to copy",
5862 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5863 NEXT_ENTRY(COMMON_UNSIGNED)),
5864 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5866 .call = parse_vc_conf,
5868 /* Top level command. */
5871 .help = "set raw encap/decap/sample data",
5872 .type = "set raw_encap|raw_decap <index> <pattern>"
5873 " or set sample_actions <index> <action>",
5874 .next = NEXT(NEXT_ENTRY
5877 SET_SAMPLE_ACTIONS)),
5878 .call = parse_set_init,
5880 /* Sub-level commands. */
5882 .name = "raw_encap",
5883 .help = "set raw encap data",
5884 .next = NEXT(next_set_raw),
5885 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5886 (offsetof(struct buffer, port),
5887 sizeof(((struct buffer *)0)->port),
5888 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5889 .call = parse_set_raw_encap_decap,
5892 .name = "raw_decap",
5893 .help = "set raw decap data",
5894 .next = NEXT(next_set_raw),
5895 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5896 (offsetof(struct buffer, port),
5897 sizeof(((struct buffer *)0)->port),
5898 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5899 .call = parse_set_raw_encap_decap,
5903 .type = "COMMON_UNSIGNED",
5904 .help = "index of raw_encap/raw_decap data",
5905 .next = NEXT(next_item),
5908 [SET_SAMPLE_INDEX] = {
5911 .help = "index of sample actions",
5912 .next = NEXT(next_action_sample),
5915 [SET_SAMPLE_ACTIONS] = {
5916 .name = "sample_actions",
5917 .help = "set sample actions list",
5918 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
5919 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5920 (offsetof(struct buffer, port),
5921 sizeof(((struct buffer *)0)->port),
5922 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
5923 .call = parse_set_sample_action,
5925 [ACTION_SET_TAG] = {
5928 .priv = PRIV_ACTION(SET_TAG,
5929 sizeof(struct rte_flow_action_set_tag)),
5930 .next = NEXT(action_set_tag),
5933 [ACTION_SET_TAG_INDEX] = {
5935 .help = "index of tag array",
5936 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5937 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
5938 .call = parse_vc_conf,
5940 [ACTION_SET_TAG_DATA] = {
5942 .help = "tag value",
5943 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5944 .args = ARGS(ARGS_ENTRY
5945 (struct rte_flow_action_set_tag, data)),
5946 .call = parse_vc_conf,
5948 [ACTION_SET_TAG_MASK] = {
5950 .help = "mask for tag value",
5951 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5952 .args = ARGS(ARGS_ENTRY
5953 (struct rte_flow_action_set_tag, mask)),
5954 .call = parse_vc_conf,
5956 [ACTION_SET_META] = {
5958 .help = "set metadata",
5959 .priv = PRIV_ACTION(SET_META,
5960 sizeof(struct rte_flow_action_set_meta)),
5961 .next = NEXT(action_set_meta),
5962 .call = parse_vc_action_set_meta,
5964 [ACTION_SET_META_DATA] = {
5966 .help = "metadata value",
5967 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5968 .args = ARGS(ARGS_ENTRY
5969 (struct rte_flow_action_set_meta, data)),
5970 .call = parse_vc_conf,
5972 [ACTION_SET_META_MASK] = {
5974 .help = "mask for metadata value",
5975 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5976 .args = ARGS(ARGS_ENTRY
5977 (struct rte_flow_action_set_meta, mask)),
5978 .call = parse_vc_conf,
5980 [ACTION_SET_IPV4_DSCP] = {
5981 .name = "set_ipv4_dscp",
5982 .help = "set DSCP value",
5983 .priv = PRIV_ACTION(SET_IPV4_DSCP,
5984 sizeof(struct rte_flow_action_set_dscp)),
5985 .next = NEXT(action_set_ipv4_dscp),
5988 [ACTION_SET_IPV4_DSCP_VALUE] = {
5989 .name = "dscp_value",
5990 .help = "new IPv4 DSCP value to set",
5991 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5992 .args = ARGS(ARGS_ENTRY
5993 (struct rte_flow_action_set_dscp, dscp)),
5994 .call = parse_vc_conf,
5996 [ACTION_SET_IPV6_DSCP] = {
5997 .name = "set_ipv6_dscp",
5998 .help = "set DSCP value",
5999 .priv = PRIV_ACTION(SET_IPV6_DSCP,
6000 sizeof(struct rte_flow_action_set_dscp)),
6001 .next = NEXT(action_set_ipv6_dscp),
6004 [ACTION_SET_IPV6_DSCP_VALUE] = {
6005 .name = "dscp_value",
6006 .help = "new IPv6 DSCP value to set",
6007 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
6008 .args = ARGS(ARGS_ENTRY
6009 (struct rte_flow_action_set_dscp, dscp)),
6010 .call = parse_vc_conf,
6014 .help = "set a specific metadata header",
6015 .next = NEXT(action_age),
6016 .priv = PRIV_ACTION(AGE,
6017 sizeof(struct rte_flow_action_age)),
6020 [ACTION_AGE_TIMEOUT] = {
6022 .help = "flow age timeout value",
6023 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
6025 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
6026 .call = parse_vc_conf,
6030 .help = "set a sample action",
6031 .next = NEXT(action_sample),
6032 .priv = PRIV_ACTION(SAMPLE,
6033 sizeof(struct action_sample_data)),
6034 .call = parse_vc_action_sample,
6036 [ACTION_SAMPLE_RATIO] = {
6038 .help = "flow sample ratio value",
6039 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
6040 .args = ARGS(ARGS_ENTRY_ARB
6041 (offsetof(struct action_sample_data, conf) +
6042 offsetof(struct rte_flow_action_sample, ratio),
6043 sizeof(((struct rte_flow_action_sample *)0)->
6046 [ACTION_SAMPLE_INDEX] = {
6048 .help = "the index of sample actions list",
6049 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
6051 [ACTION_SAMPLE_INDEX_VALUE] = {
6053 .type = "COMMON_UNSIGNED",
6054 .help = "unsigned integer value",
6055 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6056 .call = parse_vc_action_sample_index,
6057 .comp = comp_set_sample_index,
6059 [ACTION_CONNTRACK] = {
6060 .name = "conntrack",
6061 .help = "create a conntrack object",
6062 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6063 .priv = PRIV_ACTION(CONNTRACK,
6064 sizeof(struct rte_flow_action_conntrack)),
6067 [ACTION_CONNTRACK_UPDATE] = {
6068 .name = "conntrack_update",
6069 .help = "update a conntrack object",
6070 .next = NEXT(action_update_conntrack),
6071 .priv = PRIV_ACTION(CONNTRACK,
6072 sizeof(struct rte_flow_modify_conntrack)),
6075 [ACTION_CONNTRACK_UPDATE_DIR] = {
6077 .help = "update a conntrack object direction",
6078 .next = NEXT(action_update_conntrack),
6079 .call = parse_vc_action_conntrack_update,
6081 [ACTION_CONNTRACK_UPDATE_CTX] = {
6083 .help = "update a conntrack object context",
6084 .next = NEXT(action_update_conntrack),
6085 .call = parse_vc_action_conntrack_update,
6087 [ACTION_PORT_REPRESENTOR] = {
6088 .name = "port_representor",
6089 .help = "at embedded switch level, send matching traffic to the given ethdev",
6090 .priv = PRIV_ACTION(PORT_REPRESENTOR,
6091 sizeof(struct rte_flow_action_ethdev)),
6092 .next = NEXT(action_port_representor),
6095 [ACTION_PORT_REPRESENTOR_PORT_ID] = {
6097 .help = "ethdev port ID",
6098 .next = NEXT(action_port_representor,
6099 NEXT_ENTRY(COMMON_UNSIGNED)),
6100 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6102 .call = parse_vc_conf,
6104 [ACTION_REPRESENTED_PORT] = {
6105 .name = "represented_port",
6106 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
6107 .priv = PRIV_ACTION(REPRESENTED_PORT,
6108 sizeof(struct rte_flow_action_ethdev)),
6109 .next = NEXT(action_represented_port),
6112 [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
6113 .name = "ethdev_port_id",
6114 .help = "ethdev port ID",
6115 .next = NEXT(action_represented_port,
6116 NEXT_ENTRY(COMMON_UNSIGNED)),
6117 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6119 .call = parse_vc_conf,
6121 /* Indirect action destroy arguments. */
6122 [INDIRECT_ACTION_DESTROY_ID] = {
6123 .name = "action_id",
6124 .help = "specify a indirect action id to destroy",
6125 .next = NEXT(next_ia_destroy_attr,
6126 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6127 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
6128 args.ia_destroy.action_id)),
6129 .call = parse_ia_destroy,
6131 /* Indirect action create arguments. */
6132 [INDIRECT_ACTION_CREATE_ID] = {
6133 .name = "action_id",
6134 .help = "specify a indirect action id to create",
6135 .next = NEXT(next_ia_create_attr,
6136 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6137 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
6139 [ACTION_INDIRECT] = {
6141 .help = "apply indirect action by id",
6142 .priv = PRIV_ACTION(INDIRECT, 0),
6143 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
6144 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6147 [INDIRECT_ACTION_ID2PTR] = {
6148 .name = "{action_id}",
6149 .type = "INDIRECT_ACTION_ID",
6150 .help = "indirect action id",
6151 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6152 .call = parse_ia_id2ptr,
6155 [INDIRECT_ACTION_INGRESS] = {
6157 .help = "affect rule to ingress",
6158 .next = NEXT(next_ia_create_attr),
6161 [INDIRECT_ACTION_EGRESS] = {
6163 .help = "affect rule to egress",
6164 .next = NEXT(next_ia_create_attr),
6167 [INDIRECT_ACTION_TRANSFER] = {
6169 .help = "affect rule to transfer",
6170 .next = NEXT(next_ia_create_attr),
6173 [INDIRECT_ACTION_SPEC] = {
6175 .help = "specify action to create indirect handle",
6176 .next = NEXT(next_action),
6179 .name = "g_actions",
6180 .help = "submit a list of associated actions for green",
6181 .next = NEXT(next_action),
6185 .name = "y_actions",
6186 .help = "submit a list of associated actions for yellow",
6187 .next = NEXT(next_action),
6190 .name = "r_actions",
6191 .help = "submit a list of associated actions for red",
6192 .next = NEXT(next_action),
6195 /* Top-level command. */
6198 .type = "port meter policy {port_id} {arg}",
6199 .help = "add port meter policy",
6200 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
6203 /* Sub-level commands. */
6206 .help = "add port meter policy",
6207 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
6209 [ITEM_POL_METER] = {
6211 .help = "add port meter policy",
6212 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
6214 [ITEM_POL_POLICY] = {
6216 .help = "add port meter policy",
6217 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
6218 NEXT_ENTRY(ACTION_POL_Y),
6219 NEXT_ENTRY(ACTION_POL_G),
6220 NEXT_ENTRY(COMMON_POLICY_ID),
6221 NEXT_ENTRY(COMMON_PORT_ID)),
6222 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
6223 ARGS_ENTRY(struct buffer, port)),
6228 /** Remove and return last entry from argument stack. */
6229 static const struct arg *
6230 pop_args(struct context *ctx)
6232 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
6235 /** Add entry on top of the argument stack. */
6237 push_args(struct context *ctx, const struct arg *arg)
6239 if (ctx->args_num == CTX_STACK_SIZE)
6241 ctx->args[ctx->args_num++] = arg;
6245 /** Spread value into buffer according to bit-mask. */
6247 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
6249 uint32_t i = arg->size;
6257 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6266 unsigned int shift = 0;
6267 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
6269 for (shift = 0; arg->mask[i] >> shift; ++shift) {
6270 if (!(arg->mask[i] & (1 << shift)))
6275 *buf &= ~(1 << shift);
6276 *buf |= (val & 1) << shift;
6284 /** Compare a string with a partial one of a given length. */
6286 strcmp_partial(const char *full, const char *partial, size_t partial_len)
6288 int r = strncmp(full, partial, partial_len);
6292 if (strlen(full) <= partial_len)
6294 return full[partial_len];
6298 * Parse a prefix length and generate a bit-mask.
6300 * Last argument (ctx->args) is retrieved to determine mask size, storage
6301 * location and whether the result must use network byte ordering.
6304 parse_prefix(struct context *ctx, const struct token *token,
6305 const char *str, unsigned int len,
6306 void *buf, unsigned int size)
6308 const struct arg *arg = pop_args(ctx);
6309 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
6316 /* Argument is expected. */
6320 u = strtoumax(str, &end, 0);
6321 if (errno || (size_t)(end - str) != len)
6326 extra = arg_entry_bf_fill(NULL, 0, arg);
6335 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
6336 !arg_entry_bf_fill(ctx->objmask, -1, arg))
6343 if (bytes > size || bytes + !!extra > size)
6347 buf = (uint8_t *)ctx->object + arg->offset;
6348 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6350 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
6351 memset(buf, 0x00, size - bytes);
6353 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
6357 memset(buf, 0xff, bytes);
6358 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
6360 ((uint8_t *)buf)[bytes] = conv[extra];
6363 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
6366 push_args(ctx, arg);
6370 /** Default parsing function for token name matching. */
6372 parse_default(struct context *ctx, const struct token *token,
6373 const char *str, unsigned int len,
6374 void *buf, unsigned int size)
6379 if (strcmp_partial(token->name, str, len))
6384 /** Parse flow command, initialize output buffer for subsequent tokens. */
6386 parse_init(struct context *ctx, const struct token *token,
6387 const char *str, unsigned int len,
6388 void *buf, unsigned int size)
6390 struct buffer *out = buf;
6392 /* Token name must match. */
6393 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6395 /* Nothing else to do if there is no buffer. */
6398 /* Make sure buffer is large enough. */
6399 if (size < sizeof(*out))
6401 /* Initialize buffer. */
6402 memset(out, 0x00, sizeof(*out));
6403 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
6406 ctx->objmask = NULL;
6410 /** Parse tokens for indirect action commands. */
6412 parse_ia(struct context *ctx, const struct token *token,
6413 const char *str, unsigned int len,
6414 void *buf, unsigned int size)
6416 struct buffer *out = buf;
6418 /* Token name must match. */
6419 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6421 /* Nothing else to do if there is no buffer. */
6424 if (!out->command) {
6425 if (ctx->curr != INDIRECT_ACTION)
6427 if (sizeof(*out) > size)
6429 out->command = ctx->curr;
6432 ctx->objmask = NULL;
6433 out->args.vc.data = (uint8_t *)out + size;
6436 switch (ctx->curr) {
6437 case INDIRECT_ACTION_CREATE:
6438 case INDIRECT_ACTION_UPDATE:
6439 out->args.vc.actions =
6440 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6442 out->args.vc.attr.group = UINT32_MAX;
6444 case INDIRECT_ACTION_QUERY:
6445 out->command = ctx->curr;
6448 ctx->objmask = NULL;
6450 case INDIRECT_ACTION_EGRESS:
6451 out->args.vc.attr.egress = 1;
6453 case INDIRECT_ACTION_INGRESS:
6454 out->args.vc.attr.ingress = 1;
6456 case INDIRECT_ACTION_TRANSFER:
6457 out->args.vc.attr.transfer = 1;
6465 /** Parse tokens for indirect action destroy command. */
6467 parse_ia_destroy(struct context *ctx, const struct token *token,
6468 const char *str, unsigned int len,
6469 void *buf, unsigned int size)
6471 struct buffer *out = buf;
6472 uint32_t *action_id;
6474 /* Token name must match. */
6475 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6477 /* Nothing else to do if there is no buffer. */
6480 if (!out->command || out->command == INDIRECT_ACTION) {
6481 if (ctx->curr != INDIRECT_ACTION_DESTROY)
6483 if (sizeof(*out) > size)
6485 out->command = ctx->curr;
6488 ctx->objmask = NULL;
6489 out->args.ia_destroy.action_id =
6490 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6494 action_id = out->args.ia_destroy.action_id
6495 + out->args.ia_destroy.action_id_n++;
6496 if ((uint8_t *)action_id > (uint8_t *)out + size)
6499 ctx->object = action_id;
6500 ctx->objmask = NULL;
6504 /** Parse tokens for meter policy action commands. */
6506 parse_mp(struct context *ctx, const struct token *token,
6507 const char *str, unsigned int len,
6508 void *buf, unsigned int size)
6510 struct buffer *out = buf;
6512 /* Token name must match. */
6513 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6515 /* Nothing else to do if there is no buffer. */
6518 if (!out->command) {
6519 if (ctx->curr != ITEM_POL_POLICY)
6521 if (sizeof(*out) > size)
6523 out->command = ctx->curr;
6526 ctx->objmask = NULL;
6527 out->args.vc.data = (uint8_t *)out + size;
6530 switch (ctx->curr) {
6532 out->args.vc.actions =
6533 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6535 out->command = ctx->curr;
6538 ctx->objmask = NULL;
6545 /** Parse tokens for validate/create commands. */
6547 parse_vc(struct context *ctx, const struct token *token,
6548 const char *str, unsigned int len,
6549 void *buf, unsigned int size)
6551 struct buffer *out = buf;
6555 /* Token name must match. */
6556 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6558 /* Nothing else to do if there is no buffer. */
6561 if (!out->command) {
6562 if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
6563 ctx->curr != PATTERN_TEMPLATE_CREATE &&
6564 ctx->curr != ACTIONS_TEMPLATE_CREATE)
6566 if (sizeof(*out) > size)
6568 out->command = ctx->curr;
6571 ctx->objmask = NULL;
6572 out->args.vc.data = (uint8_t *)out + size;
6576 switch (ctx->curr) {
6578 ctx->object = &out->args.vc.attr;
6581 case VC_TUNNEL_MATCH:
6582 ctx->object = &out->args.vc.tunnel_ops;
6585 ctx->objmask = NULL;
6586 switch (ctx->curr) {
6591 out->args.vc.tunnel_ops.enabled = 1;
6592 out->args.vc.tunnel_ops.actions = 1;
6594 case VC_TUNNEL_MATCH:
6595 out->args.vc.tunnel_ops.enabled = 1;
6596 out->args.vc.tunnel_ops.items = 1;
6599 out->args.vc.attr.ingress = 1;
6602 out->args.vc.attr.egress = 1;
6605 out->args.vc.attr.transfer = 1;
6608 out->args.vc.pattern =
6609 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6611 ctx->object = out->args.vc.pattern;
6612 ctx->objmask = NULL;
6615 out->args.vc.actions =
6616 (void *)RTE_ALIGN_CEIL((uintptr_t)
6617 (out->args.vc.pattern +
6618 out->args.vc.pattern_n),
6620 ctx->object = out->args.vc.actions;
6621 ctx->objmask = NULL;
6628 if (!out->args.vc.actions) {
6629 const struct parse_item_priv *priv = token->priv;
6630 struct rte_flow_item *item =
6631 out->args.vc.pattern + out->args.vc.pattern_n;
6633 data_size = priv->size * 3; /* spec, last, mask */
6634 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6635 (out->args.vc.data - data_size),
6637 if ((uint8_t *)item + sizeof(*item) > data)
6639 *item = (struct rte_flow_item){
6642 ++out->args.vc.pattern_n;
6644 ctx->objmask = NULL;
6646 const struct parse_action_priv *priv = token->priv;
6647 struct rte_flow_action *action =
6648 out->args.vc.actions + out->args.vc.actions_n;
6650 data_size = priv->size; /* configuration */
6651 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6652 (out->args.vc.data - data_size),
6654 if ((uint8_t *)action + sizeof(*action) > data)
6656 *action = (struct rte_flow_action){
6658 .conf = data_size ? data : NULL,
6660 ++out->args.vc.actions_n;
6661 ctx->object = action;
6662 ctx->objmask = NULL;
6664 memset(data, 0, data_size);
6665 out->args.vc.data = data;
6666 ctx->objdata = data_size;
6670 /** Parse pattern item parameter type. */
6672 parse_vc_spec(struct context *ctx, const struct token *token,
6673 const char *str, unsigned int len,
6674 void *buf, unsigned int size)
6676 struct buffer *out = buf;
6677 struct rte_flow_item *item;
6683 /* Token name must match. */
6684 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6686 /* Parse parameter types. */
6687 switch (ctx->curr) {
6688 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
6694 case ITEM_PARAM_SPEC:
6697 case ITEM_PARAM_LAST:
6700 case ITEM_PARAM_PREFIX:
6701 /* Modify next token to expect a prefix. */
6702 if (ctx->next_num < 2)
6704 ctx->next[ctx->next_num - 2] = prefix;
6706 case ITEM_PARAM_MASK:
6712 /* Nothing else to do if there is no buffer. */
6715 if (!out->args.vc.pattern_n)
6717 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6718 data_size = ctx->objdata / 3; /* spec, last, mask */
6719 /* Point to selected object. */
6720 ctx->object = out->args.vc.data + (data_size * index);
6722 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
6723 item->mask = ctx->objmask;
6725 ctx->objmask = NULL;
6726 /* Update relevant item pointer. */
6727 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
6732 /** Parse action configuration field. */
6734 parse_vc_conf(struct context *ctx, const struct token *token,
6735 const char *str, unsigned int len,
6736 void *buf, unsigned int size)
6738 struct buffer *out = buf;
6741 /* Token name must match. */
6742 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6744 /* Nothing else to do if there is no buffer. */
6747 /* Point to selected object. */
6748 ctx->object = out->args.vc.data;
6749 ctx->objmask = NULL;
6753 /** Parse eCPRI common header type field. */
6755 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
6756 const char *str, unsigned int len,
6757 void *buf, unsigned int size)
6759 struct rte_flow_item_ecpri *ecpri;
6760 struct rte_flow_item_ecpri *ecpri_mask;
6761 struct rte_flow_item *item;
6764 struct buffer *out = buf;
6765 const struct arg *arg;
6768 /* Token name must match. */
6769 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6771 switch (ctx->curr) {
6772 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
6773 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
6775 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
6776 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
6778 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
6779 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
6786 arg = pop_args(ctx);
6789 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
6790 ecpri->hdr.common.type = msg_type;
6791 data_size = ctx->objdata / 3; /* spec, last, mask */
6792 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
6794 ecpri_mask->hdr.common.type = 0xFF;
6796 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
6797 ecpri_mask->hdr.common.u32 =
6798 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
6800 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6802 item->mask = ecpri_mask;
6806 /** Parse L2TPv2 common header type field. */
6808 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
6809 const char *str, unsigned int len,
6810 void *buf, unsigned int size)
6812 struct rte_flow_item_l2tpv2 *l2tpv2;
6813 struct rte_flow_item_l2tpv2 *l2tpv2_mask;
6814 struct rte_flow_item *item;
6816 uint16_t msg_type = 0;
6817 struct buffer *out = buf;
6818 const struct arg *arg;
6821 /* Token name must match. */
6822 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6824 switch (ctx->curr) {
6825 case ITEM_L2TPV2_TYPE_DATA:
6826 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
6828 case ITEM_L2TPV2_TYPE_DATA_L:
6829 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
6831 case ITEM_L2TPV2_TYPE_DATA_S:
6832 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
6834 case ITEM_L2TPV2_TYPE_DATA_O:
6835 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
6837 case ITEM_L2TPV2_TYPE_DATA_L_S:
6838 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
6840 case ITEM_L2TPV2_TYPE_CTRL:
6841 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
6848 arg = pop_args(ctx);
6851 l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
6852 l2tpv2->hdr.common.flags_version |= msg_type;
6853 data_size = ctx->objdata / 3; /* spec, last, mask */
6854 l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
6856 l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
6858 l2tpv2->hdr.common.flags_version =
6859 rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
6860 l2tpv2_mask->hdr.common.flags_version =
6861 rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
6863 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6864 item->spec = l2tpv2;
6865 item->mask = l2tpv2_mask;
6869 /** Parse meter color action type. */
6871 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
6872 const char *str, unsigned int len,
6873 void *buf, unsigned int size)
6875 struct rte_flow_action *action_data;
6876 struct rte_flow_action_meter_color *conf;
6877 enum rte_color color;
6881 /* Token name must match. */
6882 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6884 switch (ctx->curr) {
6885 case ACTION_METER_COLOR_GREEN:
6886 color = RTE_COLOR_GREEN;
6888 case ACTION_METER_COLOR_YELLOW:
6889 color = RTE_COLOR_YELLOW;
6891 case ACTION_METER_COLOR_RED:
6892 color = RTE_COLOR_RED;
6900 action_data = ctx->object;
6901 conf = (struct rte_flow_action_meter_color *)
6902 (uintptr_t)(action_data->conf);
6903 conf->color = color;
6907 /** Parse RSS action. */
6909 parse_vc_action_rss(struct context *ctx, const struct token *token,
6910 const char *str, unsigned int len,
6911 void *buf, unsigned int size)
6913 struct buffer *out = buf;
6914 struct rte_flow_action *action;
6915 struct action_rss_data *action_rss_data;
6919 ret = parse_vc(ctx, token, str, len, buf, size);
6922 /* Nothing else to do if there is no buffer. */
6925 if (!out->args.vc.actions_n)
6927 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6928 /* Point to selected object. */
6929 ctx->object = out->args.vc.data;
6930 ctx->objmask = NULL;
6931 /* Set up default configuration. */
6932 action_rss_data = ctx->object;
6933 *action_rss_data = (struct action_rss_data){
6934 .conf = (struct rte_flow_action_rss){
6935 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
6939 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
6941 .queue = action_rss_data->queue,
6945 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
6946 action_rss_data->queue[i] = i;
6947 action->conf = &action_rss_data->conf;
6952 * Parse func field for RSS action.
6954 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
6955 * ACTION_RSS_FUNC_* index that called this function.
6958 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
6959 const char *str, unsigned int len,
6960 void *buf, unsigned int size)
6962 struct action_rss_data *action_rss_data;
6963 enum rte_eth_hash_function func;
6967 /* Token name must match. */
6968 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6970 switch (ctx->curr) {
6971 case ACTION_RSS_FUNC_DEFAULT:
6972 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
6974 case ACTION_RSS_FUNC_TOEPLITZ:
6975 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
6977 case ACTION_RSS_FUNC_SIMPLE_XOR:
6978 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
6980 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
6981 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
6988 action_rss_data = ctx->object;
6989 action_rss_data->conf.func = func;
6994 * Parse type field for RSS action.
6996 * Valid tokens are type field names and the "end" token.
6999 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
7000 const char *str, unsigned int len,
7001 void *buf, unsigned int size)
7003 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
7004 struct action_rss_data *action_rss_data;
7010 if (ctx->curr != ACTION_RSS_TYPE)
7012 if (!(ctx->objdata >> 16) && ctx->object) {
7013 action_rss_data = ctx->object;
7014 action_rss_data->conf.types = 0;
7016 if (!strcmp_partial("end", str, len)) {
7017 ctx->objdata &= 0xffff;
7020 for (i = 0; rss_type_table[i].str; ++i)
7021 if (!strcmp_partial(rss_type_table[i].str, str, len))
7023 if (!rss_type_table[i].str)
7025 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
7027 if (ctx->next_num == RTE_DIM(ctx->next))
7029 ctx->next[ctx->next_num++] = next;
7032 action_rss_data = ctx->object;
7033 action_rss_data->conf.types |= rss_type_table[i].rss_type;
7038 * Parse queue field for RSS action.
7040 * Valid tokens are queue indices and the "end" token.
7043 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
7044 const char *str, unsigned int len,
7045 void *buf, unsigned int size)
7047 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
7048 struct action_rss_data *action_rss_data;
7049 const struct arg *arg;
7056 if (ctx->curr != ACTION_RSS_QUEUE)
7058 i = ctx->objdata >> 16;
7059 if (!strcmp_partial("end", str, len)) {
7060 ctx->objdata &= 0xffff;
7063 if (i >= ACTION_RSS_QUEUE_NUM)
7065 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
7066 i * sizeof(action_rss_data->queue[i]),
7067 sizeof(action_rss_data->queue[i]));
7068 if (push_args(ctx, arg))
7070 ret = parse_int(ctx, token, str, len, NULL, 0);
7076 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
7078 if (ctx->next_num == RTE_DIM(ctx->next))
7080 ctx->next[ctx->next_num++] = next;
7084 action_rss_data = ctx->object;
7085 action_rss_data->conf.queue_num = i;
7086 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
7090 /** Setup VXLAN encap configuration. */
7092 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
7094 /* Set up default configuration. */
7095 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
7096 .conf = (struct rte_flow_action_vxlan_encap){
7097 .definition = action_vxlan_encap_data->items,
7101 .type = RTE_FLOW_ITEM_TYPE_ETH,
7102 .spec = &action_vxlan_encap_data->item_eth,
7103 .mask = &rte_flow_item_eth_mask,
7106 .type = RTE_FLOW_ITEM_TYPE_VLAN,
7107 .spec = &action_vxlan_encap_data->item_vlan,
7108 .mask = &rte_flow_item_vlan_mask,
7111 .type = RTE_FLOW_ITEM_TYPE_IPV4,
7112 .spec = &action_vxlan_encap_data->item_ipv4,
7113 .mask = &rte_flow_item_ipv4_mask,
7116 .type = RTE_FLOW_ITEM_TYPE_UDP,
7117 .spec = &action_vxlan_encap_data->item_udp,
7118 .mask = &rte_flow_item_udp_mask,
7121 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
7122 .spec = &action_vxlan_encap_data->item_vxlan,
7123 .mask = &rte_flow_item_vxlan_mask,
7126 .type = RTE_FLOW_ITEM_TYPE_END,
7131 .tci = vxlan_encap_conf.vlan_tci,
7135 .src_addr = vxlan_encap_conf.ipv4_src,
7136 .dst_addr = vxlan_encap_conf.ipv4_dst,
7139 .src_port = vxlan_encap_conf.udp_src,
7140 .dst_port = vxlan_encap_conf.udp_dst,
7142 .item_vxlan.flags = 0,
7144 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
7145 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7146 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
7147 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7148 if (!vxlan_encap_conf.select_ipv4) {
7149 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
7150 &vxlan_encap_conf.ipv6_src,
7151 sizeof(vxlan_encap_conf.ipv6_src));
7152 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
7153 &vxlan_encap_conf.ipv6_dst,
7154 sizeof(vxlan_encap_conf.ipv6_dst));
7155 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
7156 .type = RTE_FLOW_ITEM_TYPE_IPV6,
7157 .spec = &action_vxlan_encap_data->item_ipv6,
7158 .mask = &rte_flow_item_ipv6_mask,
7161 if (!vxlan_encap_conf.select_vlan)
7162 action_vxlan_encap_data->items[1].type =
7163 RTE_FLOW_ITEM_TYPE_VOID;
7164 if (vxlan_encap_conf.select_tos_ttl) {
7165 if (vxlan_encap_conf.select_ipv4) {
7166 static struct rte_flow_item_ipv4 ipv4_mask_tos;
7168 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
7169 sizeof(ipv4_mask_tos));
7170 ipv4_mask_tos.hdr.type_of_service = 0xff;
7171 ipv4_mask_tos.hdr.time_to_live = 0xff;
7172 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
7173 vxlan_encap_conf.ip_tos;
7174 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
7175 vxlan_encap_conf.ip_ttl;
7176 action_vxlan_encap_data->items[2].mask =
7179 static struct rte_flow_item_ipv6 ipv6_mask_tos;
7181 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
7182 sizeof(ipv6_mask_tos));
7183 ipv6_mask_tos.hdr.vtc_flow |=
7184 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
7185 ipv6_mask_tos.hdr.hop_limits = 0xff;
7186 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
7188 ((uint32_t)vxlan_encap_conf.ip_tos <<
7189 RTE_IPV6_HDR_TC_SHIFT);
7190 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
7191 vxlan_encap_conf.ip_ttl;
7192 action_vxlan_encap_data->items[2].mask =
7196 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
7197 RTE_DIM(vxlan_encap_conf.vni));
7201 /** Parse VXLAN encap action. */
7203 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
7204 const char *str, unsigned int len,
7205 void *buf, unsigned int size)
7207 struct buffer *out = buf;
7208 struct rte_flow_action *action;
7209 struct action_vxlan_encap_data *action_vxlan_encap_data;
7212 ret = parse_vc(ctx, token, str, len, buf, size);
7215 /* Nothing else to do if there is no buffer. */
7218 if (!out->args.vc.actions_n)
7220 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7221 /* Point to selected object. */
7222 ctx->object = out->args.vc.data;
7223 ctx->objmask = NULL;
7224 action_vxlan_encap_data = ctx->object;
7225 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
7226 action->conf = &action_vxlan_encap_data->conf;
7230 /** Setup NVGRE encap configuration. */
7232 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
7234 /* Set up default configuration. */
7235 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
7236 .conf = (struct rte_flow_action_nvgre_encap){
7237 .definition = action_nvgre_encap_data->items,
7241 .type = RTE_FLOW_ITEM_TYPE_ETH,
7242 .spec = &action_nvgre_encap_data->item_eth,
7243 .mask = &rte_flow_item_eth_mask,
7246 .type = RTE_FLOW_ITEM_TYPE_VLAN,
7247 .spec = &action_nvgre_encap_data->item_vlan,
7248 .mask = &rte_flow_item_vlan_mask,
7251 .type = RTE_FLOW_ITEM_TYPE_IPV4,
7252 .spec = &action_nvgre_encap_data->item_ipv4,
7253 .mask = &rte_flow_item_ipv4_mask,
7256 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
7257 .spec = &action_nvgre_encap_data->item_nvgre,
7258 .mask = &rte_flow_item_nvgre_mask,
7261 .type = RTE_FLOW_ITEM_TYPE_END,
7266 .tci = nvgre_encap_conf.vlan_tci,
7270 .src_addr = nvgre_encap_conf.ipv4_src,
7271 .dst_addr = nvgre_encap_conf.ipv4_dst,
7273 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
7274 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
7275 .item_nvgre.flow_id = 0,
7277 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
7278 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7279 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
7280 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7281 if (!nvgre_encap_conf.select_ipv4) {
7282 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
7283 &nvgre_encap_conf.ipv6_src,
7284 sizeof(nvgre_encap_conf.ipv6_src));
7285 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
7286 &nvgre_encap_conf.ipv6_dst,
7287 sizeof(nvgre_encap_conf.ipv6_dst));
7288 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
7289 .type = RTE_FLOW_ITEM_TYPE_IPV6,
7290 .spec = &action_nvgre_encap_data->item_ipv6,
7291 .mask = &rte_flow_item_ipv6_mask,
7294 if (!nvgre_encap_conf.select_vlan)
7295 action_nvgre_encap_data->items[1].type =
7296 RTE_FLOW_ITEM_TYPE_VOID;
7297 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
7298 RTE_DIM(nvgre_encap_conf.tni));
7302 /** Parse NVGRE encap action. */
7304 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
7305 const char *str, unsigned int len,
7306 void *buf, unsigned int size)
7308 struct buffer *out = buf;
7309 struct rte_flow_action *action;
7310 struct action_nvgre_encap_data *action_nvgre_encap_data;
7313 ret = parse_vc(ctx, token, str, len, buf, size);
7316 /* Nothing else to do if there is no buffer. */
7319 if (!out->args.vc.actions_n)
7321 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7322 /* Point to selected object. */
7323 ctx->object = out->args.vc.data;
7324 ctx->objmask = NULL;
7325 action_nvgre_encap_data = ctx->object;
7326 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
7327 action->conf = &action_nvgre_encap_data->conf;
7331 /** Parse l2 encap action. */
7333 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
7334 const char *str, unsigned int len,
7335 void *buf, unsigned int size)
7337 struct buffer *out = buf;
7338 struct rte_flow_action *action;
7339 struct action_raw_encap_data *action_encap_data;
7340 struct rte_flow_item_eth eth = { .type = 0, };
7341 struct rte_flow_item_vlan vlan = {
7342 .tci = mplsoudp_encap_conf.vlan_tci,
7348 ret = parse_vc(ctx, token, str, len, buf, size);
7351 /* Nothing else to do if there is no buffer. */
7354 if (!out->args.vc.actions_n)
7356 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7357 /* Point to selected object. */
7358 ctx->object = out->args.vc.data;
7359 ctx->objmask = NULL;
7360 /* Copy the headers to the buffer. */
7361 action_encap_data = ctx->object;
7362 *action_encap_data = (struct action_raw_encap_data) {
7363 .conf = (struct rte_flow_action_raw_encap){
7364 .data = action_encap_data->data,
7368 header = action_encap_data->data;
7369 if (l2_encap_conf.select_vlan)
7370 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7371 else if (l2_encap_conf.select_ipv4)
7372 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7374 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7375 memcpy(eth.dst.addr_bytes,
7376 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7377 memcpy(eth.src.addr_bytes,
7378 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7379 memcpy(header, ð, sizeof(eth));
7380 header += sizeof(eth);
7381 if (l2_encap_conf.select_vlan) {
7382 if (l2_encap_conf.select_ipv4)
7383 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7385 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7386 memcpy(header, &vlan, sizeof(vlan));
7387 header += sizeof(vlan);
7389 action_encap_data->conf.size = header -
7390 action_encap_data->data;
7391 action->conf = &action_encap_data->conf;
7395 /** Parse l2 decap action. */
7397 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
7398 const char *str, unsigned int len,
7399 void *buf, unsigned int size)
7401 struct buffer *out = buf;
7402 struct rte_flow_action *action;
7403 struct action_raw_decap_data *action_decap_data;
7404 struct rte_flow_item_eth eth = { .type = 0, };
7405 struct rte_flow_item_vlan vlan = {
7406 .tci = mplsoudp_encap_conf.vlan_tci,
7412 ret = parse_vc(ctx, token, str, len, buf, size);
7415 /* Nothing else to do if there is no buffer. */
7418 if (!out->args.vc.actions_n)
7420 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7421 /* Point to selected object. */
7422 ctx->object = out->args.vc.data;
7423 ctx->objmask = NULL;
7424 /* Copy the headers to the buffer. */
7425 action_decap_data = ctx->object;
7426 *action_decap_data = (struct action_raw_decap_data) {
7427 .conf = (struct rte_flow_action_raw_decap){
7428 .data = action_decap_data->data,
7432 header = action_decap_data->data;
7433 if (l2_decap_conf.select_vlan)
7434 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7435 memcpy(header, ð, sizeof(eth));
7436 header += sizeof(eth);
7437 if (l2_decap_conf.select_vlan) {
7438 memcpy(header, &vlan, sizeof(vlan));
7439 header += sizeof(vlan);
7441 action_decap_data->conf.size = header -
7442 action_decap_data->data;
7443 action->conf = &action_decap_data->conf;
7447 #define ETHER_TYPE_MPLS_UNICAST 0x8847
7449 /** Parse MPLSOGRE encap action. */
7451 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
7452 const char *str, unsigned int len,
7453 void *buf, unsigned int size)
7455 struct buffer *out = buf;
7456 struct rte_flow_action *action;
7457 struct action_raw_encap_data *action_encap_data;
7458 struct rte_flow_item_eth eth = { .type = 0, };
7459 struct rte_flow_item_vlan vlan = {
7460 .tci = mplsogre_encap_conf.vlan_tci,
7463 struct rte_flow_item_ipv4 ipv4 = {
7465 .src_addr = mplsogre_encap_conf.ipv4_src,
7466 .dst_addr = mplsogre_encap_conf.ipv4_dst,
7467 .next_proto_id = IPPROTO_GRE,
7468 .version_ihl = RTE_IPV4_VHL_DEF,
7469 .time_to_live = IPDEFTTL,
7472 struct rte_flow_item_ipv6 ipv6 = {
7474 .proto = IPPROTO_GRE,
7475 .hop_limits = IPDEFTTL,
7478 struct rte_flow_item_gre gre = {
7479 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
7481 struct rte_flow_item_mpls mpls = {
7487 ret = parse_vc(ctx, token, str, len, buf, size);
7490 /* Nothing else to do if there is no buffer. */
7493 if (!out->args.vc.actions_n)
7495 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7496 /* Point to selected object. */
7497 ctx->object = out->args.vc.data;
7498 ctx->objmask = NULL;
7499 /* Copy the headers to the buffer. */
7500 action_encap_data = ctx->object;
7501 *action_encap_data = (struct action_raw_encap_data) {
7502 .conf = (struct rte_flow_action_raw_encap){
7503 .data = action_encap_data->data,
7508 header = action_encap_data->data;
7509 if (mplsogre_encap_conf.select_vlan)
7510 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7511 else if (mplsogre_encap_conf.select_ipv4)
7512 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7514 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7515 memcpy(eth.dst.addr_bytes,
7516 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7517 memcpy(eth.src.addr_bytes,
7518 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7519 memcpy(header, ð, sizeof(eth));
7520 header += sizeof(eth);
7521 if (mplsogre_encap_conf.select_vlan) {
7522 if (mplsogre_encap_conf.select_ipv4)
7523 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7525 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7526 memcpy(header, &vlan, sizeof(vlan));
7527 header += sizeof(vlan);
7529 if (mplsogre_encap_conf.select_ipv4) {
7530 memcpy(header, &ipv4, sizeof(ipv4));
7531 header += sizeof(ipv4);
7533 memcpy(&ipv6.hdr.src_addr,
7534 &mplsogre_encap_conf.ipv6_src,
7535 sizeof(mplsogre_encap_conf.ipv6_src));
7536 memcpy(&ipv6.hdr.dst_addr,
7537 &mplsogre_encap_conf.ipv6_dst,
7538 sizeof(mplsogre_encap_conf.ipv6_dst));
7539 memcpy(header, &ipv6, sizeof(ipv6));
7540 header += sizeof(ipv6);
7542 memcpy(header, &gre, sizeof(gre));
7543 header += sizeof(gre);
7544 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
7545 RTE_DIM(mplsogre_encap_conf.label));
7546 mpls.label_tc_s[2] |= 0x1;
7547 memcpy(header, &mpls, sizeof(mpls));
7548 header += sizeof(mpls);
7549 action_encap_data->conf.size = header -
7550 action_encap_data->data;
7551 action->conf = &action_encap_data->conf;
7555 /** Parse MPLSOGRE decap action. */
7557 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
7558 const char *str, unsigned int len,
7559 void *buf, unsigned int size)
7561 struct buffer *out = buf;
7562 struct rte_flow_action *action;
7563 struct action_raw_decap_data *action_decap_data;
7564 struct rte_flow_item_eth eth = { .type = 0, };
7565 struct rte_flow_item_vlan vlan = {.tci = 0};
7566 struct rte_flow_item_ipv4 ipv4 = {
7568 .next_proto_id = IPPROTO_GRE,
7571 struct rte_flow_item_ipv6 ipv6 = {
7573 .proto = IPPROTO_GRE,
7576 struct rte_flow_item_gre gre = {
7577 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
7579 struct rte_flow_item_mpls mpls;
7583 ret = parse_vc(ctx, token, str, len, buf, size);
7586 /* Nothing else to do if there is no buffer. */
7589 if (!out->args.vc.actions_n)
7591 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7592 /* Point to selected object. */
7593 ctx->object = out->args.vc.data;
7594 ctx->objmask = NULL;
7595 /* Copy the headers to the buffer. */
7596 action_decap_data = ctx->object;
7597 *action_decap_data = (struct action_raw_decap_data) {
7598 .conf = (struct rte_flow_action_raw_decap){
7599 .data = action_decap_data->data,
7603 header = action_decap_data->data;
7604 if (mplsogre_decap_conf.select_vlan)
7605 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7606 else if (mplsogre_encap_conf.select_ipv4)
7607 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7609 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7610 memcpy(eth.dst.addr_bytes,
7611 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7612 memcpy(eth.src.addr_bytes,
7613 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7614 memcpy(header, ð, sizeof(eth));
7615 header += sizeof(eth);
7616 if (mplsogre_encap_conf.select_vlan) {
7617 if (mplsogre_encap_conf.select_ipv4)
7618 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7620 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7621 memcpy(header, &vlan, sizeof(vlan));
7622 header += sizeof(vlan);
7624 if (mplsogre_encap_conf.select_ipv4) {
7625 memcpy(header, &ipv4, sizeof(ipv4));
7626 header += sizeof(ipv4);
7628 memcpy(header, &ipv6, sizeof(ipv6));
7629 header += sizeof(ipv6);
7631 memcpy(header, &gre, sizeof(gre));
7632 header += sizeof(gre);
7633 memset(&mpls, 0, sizeof(mpls));
7634 memcpy(header, &mpls, sizeof(mpls));
7635 header += sizeof(mpls);
7636 action_decap_data->conf.size = header -
7637 action_decap_data->data;
7638 action->conf = &action_decap_data->conf;
7642 /** Parse MPLSOUDP encap action. */
7644 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
7645 const char *str, unsigned int len,
7646 void *buf, unsigned int size)
7648 struct buffer *out = buf;
7649 struct rte_flow_action *action;
7650 struct action_raw_encap_data *action_encap_data;
7651 struct rte_flow_item_eth eth = { .type = 0, };
7652 struct rte_flow_item_vlan vlan = {
7653 .tci = mplsoudp_encap_conf.vlan_tci,
7656 struct rte_flow_item_ipv4 ipv4 = {
7658 .src_addr = mplsoudp_encap_conf.ipv4_src,
7659 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
7660 .next_proto_id = IPPROTO_UDP,
7661 .version_ihl = RTE_IPV4_VHL_DEF,
7662 .time_to_live = IPDEFTTL,
7665 struct rte_flow_item_ipv6 ipv6 = {
7667 .proto = IPPROTO_UDP,
7668 .hop_limits = IPDEFTTL,
7671 struct rte_flow_item_udp udp = {
7673 .src_port = mplsoudp_encap_conf.udp_src,
7674 .dst_port = mplsoudp_encap_conf.udp_dst,
7677 struct rte_flow_item_mpls mpls;
7681 ret = parse_vc(ctx, token, str, len, buf, size);
7684 /* Nothing else to do if there is no buffer. */
7687 if (!out->args.vc.actions_n)
7689 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7690 /* Point to selected object. */
7691 ctx->object = out->args.vc.data;
7692 ctx->objmask = NULL;
7693 /* Copy the headers to the buffer. */
7694 action_encap_data = ctx->object;
7695 *action_encap_data = (struct action_raw_encap_data) {
7696 .conf = (struct rte_flow_action_raw_encap){
7697 .data = action_encap_data->data,
7702 header = action_encap_data->data;
7703 if (mplsoudp_encap_conf.select_vlan)
7704 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7705 else if (mplsoudp_encap_conf.select_ipv4)
7706 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7708 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7709 memcpy(eth.dst.addr_bytes,
7710 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7711 memcpy(eth.src.addr_bytes,
7712 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7713 memcpy(header, ð, sizeof(eth));
7714 header += sizeof(eth);
7715 if (mplsoudp_encap_conf.select_vlan) {
7716 if (mplsoudp_encap_conf.select_ipv4)
7717 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7719 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7720 memcpy(header, &vlan, sizeof(vlan));
7721 header += sizeof(vlan);
7723 if (mplsoudp_encap_conf.select_ipv4) {
7724 memcpy(header, &ipv4, sizeof(ipv4));
7725 header += sizeof(ipv4);
7727 memcpy(&ipv6.hdr.src_addr,
7728 &mplsoudp_encap_conf.ipv6_src,
7729 sizeof(mplsoudp_encap_conf.ipv6_src));
7730 memcpy(&ipv6.hdr.dst_addr,
7731 &mplsoudp_encap_conf.ipv6_dst,
7732 sizeof(mplsoudp_encap_conf.ipv6_dst));
7733 memcpy(header, &ipv6, sizeof(ipv6));
7734 header += sizeof(ipv6);
7736 memcpy(header, &udp, sizeof(udp));
7737 header += sizeof(udp);
7738 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
7739 RTE_DIM(mplsoudp_encap_conf.label));
7740 mpls.label_tc_s[2] |= 0x1;
7741 memcpy(header, &mpls, sizeof(mpls));
7742 header += sizeof(mpls);
7743 action_encap_data->conf.size = header -
7744 action_encap_data->data;
7745 action->conf = &action_encap_data->conf;
7749 /** Parse MPLSOUDP decap action. */
7751 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
7752 const char *str, unsigned int len,
7753 void *buf, unsigned int size)
7755 struct buffer *out = buf;
7756 struct rte_flow_action *action;
7757 struct action_raw_decap_data *action_decap_data;
7758 struct rte_flow_item_eth eth = { .type = 0, };
7759 struct rte_flow_item_vlan vlan = {.tci = 0};
7760 struct rte_flow_item_ipv4 ipv4 = {
7762 .next_proto_id = IPPROTO_UDP,
7765 struct rte_flow_item_ipv6 ipv6 = {
7767 .proto = IPPROTO_UDP,
7770 struct rte_flow_item_udp udp = {
7772 .dst_port = rte_cpu_to_be_16(6635),
7775 struct rte_flow_item_mpls mpls;
7779 ret = parse_vc(ctx, token, str, len, buf, size);
7782 /* Nothing else to do if there is no buffer. */
7785 if (!out->args.vc.actions_n)
7787 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7788 /* Point to selected object. */
7789 ctx->object = out->args.vc.data;
7790 ctx->objmask = NULL;
7791 /* Copy the headers to the buffer. */
7792 action_decap_data = ctx->object;
7793 *action_decap_data = (struct action_raw_decap_data) {
7794 .conf = (struct rte_flow_action_raw_decap){
7795 .data = action_decap_data->data,
7799 header = action_decap_data->data;
7800 if (mplsoudp_decap_conf.select_vlan)
7801 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7802 else if (mplsoudp_encap_conf.select_ipv4)
7803 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7805 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7806 memcpy(eth.dst.addr_bytes,
7807 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7808 memcpy(eth.src.addr_bytes,
7809 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7810 memcpy(header, ð, sizeof(eth));
7811 header += sizeof(eth);
7812 if (mplsoudp_encap_conf.select_vlan) {
7813 if (mplsoudp_encap_conf.select_ipv4)
7814 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7816 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7817 memcpy(header, &vlan, sizeof(vlan));
7818 header += sizeof(vlan);
7820 if (mplsoudp_encap_conf.select_ipv4) {
7821 memcpy(header, &ipv4, sizeof(ipv4));
7822 header += sizeof(ipv4);
7824 memcpy(header, &ipv6, sizeof(ipv6));
7825 header += sizeof(ipv6);
7827 memcpy(header, &udp, sizeof(udp));
7828 header += sizeof(udp);
7829 memset(&mpls, 0, sizeof(mpls));
7830 memcpy(header, &mpls, sizeof(mpls));
7831 header += sizeof(mpls);
7832 action_decap_data->conf.size = header -
7833 action_decap_data->data;
7834 action->conf = &action_decap_data->conf;
7839 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
7840 const char *str, unsigned int len, void *buf,
7843 struct action_raw_decap_data *action_raw_decap_data;
7844 struct rte_flow_action *action;
7845 const struct arg *arg;
7846 struct buffer *out = buf;
7850 RTE_SET_USED(token);
7853 arg = ARGS_ENTRY_ARB_BOUNDED
7854 (offsetof(struct action_raw_decap_data, idx),
7855 sizeof(((struct action_raw_decap_data *)0)->idx),
7856 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7857 if (push_args(ctx, arg))
7859 ret = parse_int(ctx, token, str, len, NULL, 0);
7866 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7867 action_raw_decap_data = ctx->object;
7868 idx = action_raw_decap_data->idx;
7869 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
7870 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
7871 action->conf = &action_raw_decap_data->conf;
7877 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
7878 const char *str, unsigned int len, void *buf,
7881 struct action_raw_encap_data *action_raw_encap_data;
7882 struct rte_flow_action *action;
7883 const struct arg *arg;
7884 struct buffer *out = buf;
7888 RTE_SET_USED(token);
7891 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
7893 arg = ARGS_ENTRY_ARB_BOUNDED
7894 (offsetof(struct action_raw_encap_data, idx),
7895 sizeof(((struct action_raw_encap_data *)0)->idx),
7896 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7897 if (push_args(ctx, arg))
7899 ret = parse_int(ctx, token, str, len, NULL, 0);
7906 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7907 action_raw_encap_data = ctx->object;
7908 idx = action_raw_encap_data->idx;
7909 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
7910 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
7911 action_raw_encap_data->conf.preserve = NULL;
7912 action->conf = &action_raw_encap_data->conf;
7917 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
7918 const char *str, unsigned int len, void *buf,
7921 struct buffer *out = buf;
7922 struct rte_flow_action *action;
7923 struct action_raw_encap_data *action_raw_encap_data = NULL;
7926 ret = parse_vc(ctx, token, str, len, buf, size);
7929 /* Nothing else to do if there is no buffer. */
7932 if (!out->args.vc.actions_n)
7934 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7935 /* Point to selected object. */
7936 ctx->object = out->args.vc.data;
7937 ctx->objmask = NULL;
7938 /* Copy the headers to the buffer. */
7939 action_raw_encap_data = ctx->object;
7940 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
7941 action_raw_encap_data->conf.preserve = NULL;
7942 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
7943 action->conf = &action_raw_encap_data->conf;
7948 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
7949 const char *str, unsigned int len, void *buf,
7952 struct buffer *out = buf;
7953 struct rte_flow_action *action;
7954 struct action_raw_decap_data *action_raw_decap_data = NULL;
7957 ret = parse_vc(ctx, token, str, len, buf, size);
7960 /* Nothing else to do if there is no buffer. */
7963 if (!out->args.vc.actions_n)
7965 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7966 /* Point to selected object. */
7967 ctx->object = out->args.vc.data;
7968 ctx->objmask = NULL;
7969 /* Copy the headers to the buffer. */
7970 action_raw_decap_data = ctx->object;
7971 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
7972 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
7973 action->conf = &action_raw_decap_data->conf;
7978 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
7979 const char *str, unsigned int len, void *buf,
7984 ret = parse_vc(ctx, token, str, len, buf, size);
7987 ret = rte_flow_dynf_metadata_register();
7994 parse_vc_action_sample(struct context *ctx, const struct token *token,
7995 const char *str, unsigned int len, void *buf,
7998 struct buffer *out = buf;
7999 struct rte_flow_action *action;
8000 struct action_sample_data *action_sample_data = NULL;
8001 static struct rte_flow_action end_action = {
8002 RTE_FLOW_ACTION_TYPE_END, 0
8006 ret = parse_vc(ctx, token, str, len, buf, size);
8009 /* Nothing else to do if there is no buffer. */
8012 if (!out->args.vc.actions_n)
8014 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8015 /* Point to selected object. */
8016 ctx->object = out->args.vc.data;
8017 ctx->objmask = NULL;
8018 /* Copy the headers to the buffer. */
8019 action_sample_data = ctx->object;
8020 action_sample_data->conf.actions = &end_action;
8021 action->conf = &action_sample_data->conf;
8026 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
8027 const char *str, unsigned int len, void *buf,
8030 struct action_sample_data *action_sample_data;
8031 struct rte_flow_action *action;
8032 const struct arg *arg;
8033 struct buffer *out = buf;
8037 RTE_SET_USED(token);
8040 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
8042 arg = ARGS_ENTRY_ARB_BOUNDED
8043 (offsetof(struct action_sample_data, idx),
8044 sizeof(((struct action_sample_data *)0)->idx),
8045 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
8046 if (push_args(ctx, arg))
8048 ret = parse_int(ctx, token, str, len, NULL, 0);
8055 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8056 action_sample_data = ctx->object;
8057 idx = action_sample_data->idx;
8058 action_sample_data->conf.actions = raw_sample_confs[idx].data;
8059 action->conf = &action_sample_data->conf;
8063 /** Parse operation for modify_field command. */
8065 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
8066 const char *str, unsigned int len, void *buf,
8069 struct rte_flow_action_modify_field *action_modify_field;
8075 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
8077 for (i = 0; modify_field_ops[i]; ++i)
8078 if (!strcmp_partial(modify_field_ops[i], str, len))
8080 if (!modify_field_ops[i])
8084 action_modify_field = ctx->object;
8085 action_modify_field->operation = (enum rte_flow_modify_op)i;
8089 /** Parse id for modify_field command. */
8091 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
8092 const char *str, unsigned int len, void *buf,
8095 struct rte_flow_action_modify_field *action_modify_field;
8101 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
8102 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
8104 for (i = 0; modify_field_ids[i]; ++i)
8105 if (!strcmp_partial(modify_field_ids[i], str, len))
8107 if (!modify_field_ids[i])
8111 action_modify_field = ctx->object;
8112 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
8113 action_modify_field->dst.field = (enum rte_flow_field_id)i;
8115 action_modify_field->src.field = (enum rte_flow_field_id)i;
8119 /** Parse the conntrack update, not a rte_flow_action. */
8121 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
8122 const char *str, unsigned int len, void *buf,
8125 struct buffer *out = buf;
8126 struct rte_flow_modify_conntrack *ct_modify = NULL;
8129 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
8130 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
8132 /* Token name must match. */
8133 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8135 /* Nothing else to do if there is no buffer. */
8138 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
8139 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
8140 ct_modify->new_ct.is_original_dir =
8141 conntrack_context.is_original_dir;
8142 ct_modify->direction = 1;
8146 old_dir = ct_modify->new_ct.is_original_dir;
8147 memcpy(&ct_modify->new_ct, &conntrack_context,
8148 sizeof(conntrack_context));
8149 ct_modify->new_ct.is_original_dir = old_dir;
8150 ct_modify->state = 1;
8155 /** Parse tokens for destroy command. */
8157 parse_destroy(struct context *ctx, const struct token *token,
8158 const char *str, unsigned int len,
8159 void *buf, unsigned int size)
8161 struct buffer *out = buf;
8163 /* Token name must match. */
8164 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8166 /* Nothing else to do if there is no buffer. */
8169 if (!out->command) {
8170 if (ctx->curr != DESTROY)
8172 if (sizeof(*out) > size)
8174 out->command = ctx->curr;
8177 ctx->objmask = NULL;
8178 out->args.destroy.rule =
8179 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8183 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
8184 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
8187 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
8188 ctx->objmask = NULL;
8192 /** Parse tokens for flush command. */
8194 parse_flush(struct context *ctx, const struct token *token,
8195 const char *str, unsigned int len,
8196 void *buf, unsigned int size)
8198 struct buffer *out = buf;
8200 /* Token name must match. */
8201 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8203 /* Nothing else to do if there is no buffer. */
8206 if (!out->command) {
8207 if (ctx->curr != FLUSH)
8209 if (sizeof(*out) > size)
8211 out->command = ctx->curr;
8214 ctx->objmask = NULL;
8219 /** Parse tokens for dump command. */
8221 parse_dump(struct context *ctx, const struct token *token,
8222 const char *str, unsigned int len,
8223 void *buf, unsigned int size)
8225 struct buffer *out = buf;
8227 /* Token name must match. */
8228 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8230 /* Nothing else to do if there is no buffer. */
8233 if (!out->command) {
8234 if (ctx->curr != DUMP)
8236 if (sizeof(*out) > size)
8238 out->command = ctx->curr;
8241 ctx->objmask = NULL;
8244 switch (ctx->curr) {
8247 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
8248 out->command = ctx->curr;
8251 ctx->objmask = NULL;
8258 /** Parse tokens for query command. */
8260 parse_query(struct context *ctx, const struct token *token,
8261 const char *str, unsigned int len,
8262 void *buf, unsigned int size)
8264 struct buffer *out = buf;
8266 /* Token name must match. */
8267 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8269 /* Nothing else to do if there is no buffer. */
8272 if (!out->command) {
8273 if (ctx->curr != QUERY)
8275 if (sizeof(*out) > size)
8277 out->command = ctx->curr;
8280 ctx->objmask = NULL;
8285 /** Parse action names. */
8287 parse_action(struct context *ctx, const struct token *token,
8288 const char *str, unsigned int len,
8289 void *buf, unsigned int size)
8291 struct buffer *out = buf;
8292 const struct arg *arg = pop_args(ctx);
8296 /* Argument is expected. */
8299 /* Parse action name. */
8300 for (i = 0; next_action[i]; ++i) {
8301 const struct parse_action_priv *priv;
8303 token = &token_list[next_action[i]];
8304 if (strcmp_partial(token->name, str, len))
8310 memcpy((uint8_t *)ctx->object + arg->offset,
8316 push_args(ctx, arg);
8320 /** Parse tokens for list command. */
8322 parse_list(struct context *ctx, const struct token *token,
8323 const char *str, unsigned int len,
8324 void *buf, unsigned int size)
8326 struct buffer *out = buf;
8328 /* Token name must match. */
8329 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8331 /* Nothing else to do if there is no buffer. */
8334 if (!out->command) {
8335 if (ctx->curr != LIST)
8337 if (sizeof(*out) > size)
8339 out->command = ctx->curr;
8342 ctx->objmask = NULL;
8343 out->args.list.group =
8344 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8348 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
8349 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
8352 ctx->object = out->args.list.group + out->args.list.group_n++;
8353 ctx->objmask = NULL;
8357 /** Parse tokens for list all aged flows command. */
8359 parse_aged(struct context *ctx, const struct token *token,
8360 const char *str, unsigned int len,
8361 void *buf, unsigned int size)
8363 struct buffer *out = buf;
8365 /* Token name must match. */
8366 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8368 /* Nothing else to do if there is no buffer. */
8371 if (!out->command) {
8372 if (ctx->curr != AGED)
8374 if (sizeof(*out) > size)
8376 out->command = ctx->curr;
8379 ctx->objmask = NULL;
8381 if (ctx->curr == AGED_DESTROY)
8382 out->args.aged.destroy = 1;
8386 /** Parse tokens for isolate command. */
8388 parse_isolate(struct context *ctx, const struct token *token,
8389 const char *str, unsigned int len,
8390 void *buf, unsigned int size)
8392 struct buffer *out = buf;
8394 /* Token name must match. */
8395 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8397 /* Nothing else to do if there is no buffer. */
8400 if (!out->command) {
8401 if (ctx->curr != ISOLATE)
8403 if (sizeof(*out) > size)
8405 out->command = ctx->curr;
8408 ctx->objmask = NULL;
8413 /** Parse tokens for info/configure command. */
8415 parse_configure(struct context *ctx, const struct token *token,
8416 const char *str, unsigned int len,
8417 void *buf, unsigned int size)
8419 struct buffer *out = buf;
8421 /* Token name must match. */
8422 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8424 /* Nothing else to do if there is no buffer. */
8427 if (!out->command) {
8428 if (ctx->curr != INFO && ctx->curr != CONFIGURE)
8430 if (sizeof(*out) > size)
8432 out->command = ctx->curr;
8435 ctx->objmask = NULL;
8440 /** Parse tokens for template create command. */
8442 parse_template(struct context *ctx, const struct token *token,
8443 const char *str, unsigned int len,
8444 void *buf, unsigned int size)
8446 struct buffer *out = buf;
8448 /* Token name must match. */
8449 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8451 /* Nothing else to do if there is no buffer. */
8454 if (!out->command) {
8455 if (ctx->curr != PATTERN_TEMPLATE &&
8456 ctx->curr != ACTIONS_TEMPLATE)
8458 if (sizeof(*out) > size)
8460 out->command = ctx->curr;
8463 ctx->objmask = NULL;
8464 out->args.vc.data = (uint8_t *)out + size;
8467 switch (ctx->curr) {
8468 case PATTERN_TEMPLATE_CREATE:
8469 out->args.vc.pattern =
8470 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8472 out->args.vc.pat_templ_id = UINT32_MAX;
8473 out->command = ctx->curr;
8476 ctx->objmask = NULL;
8478 case PATTERN_TEMPLATE_EGRESS:
8479 out->args.vc.attr.egress = 1;
8481 case PATTERN_TEMPLATE_INGRESS:
8482 out->args.vc.attr.ingress = 1;
8484 case PATTERN_TEMPLATE_TRANSFER:
8485 out->args.vc.attr.transfer = 1;
8487 case ACTIONS_TEMPLATE_CREATE:
8488 out->args.vc.act_templ_id = UINT32_MAX;
8489 out->command = ctx->curr;
8492 ctx->objmask = NULL;
8494 case ACTIONS_TEMPLATE_SPEC:
8495 out->args.vc.actions =
8496 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8498 ctx->object = out->args.vc.actions;
8499 ctx->objmask = NULL;
8501 case ACTIONS_TEMPLATE_MASK:
8502 out->args.vc.masks =
8503 (void *)RTE_ALIGN_CEIL((uintptr_t)
8504 (out->args.vc.actions +
8505 out->args.vc.actions_n),
8507 ctx->object = out->args.vc.masks;
8508 ctx->objmask = NULL;
8510 case ACTIONS_TEMPLATE_EGRESS:
8511 out->args.vc.attr.egress = 1;
8513 case ACTIONS_TEMPLATE_INGRESS:
8514 out->args.vc.attr.ingress = 1;
8516 case ACTIONS_TEMPLATE_TRANSFER:
8517 out->args.vc.attr.transfer = 1;
8524 /** Parse tokens for template destroy command. */
8526 parse_template_destroy(struct context *ctx, const struct token *token,
8527 const char *str, unsigned int len,
8528 void *buf, unsigned int size)
8530 struct buffer *out = buf;
8531 uint32_t *template_id;
8533 /* Token name must match. */
8534 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8536 /* Nothing else to do if there is no buffer. */
8539 if (!out->command ||
8540 out->command == PATTERN_TEMPLATE ||
8541 out->command == ACTIONS_TEMPLATE) {
8542 if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
8543 ctx->curr != ACTIONS_TEMPLATE_DESTROY)
8545 if (sizeof(*out) > size)
8547 out->command = ctx->curr;
8550 ctx->objmask = NULL;
8551 out->args.templ_destroy.template_id =
8552 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8556 template_id = out->args.templ_destroy.template_id
8557 + out->args.templ_destroy.template_id_n++;
8558 if ((uint8_t *)template_id > (uint8_t *)out + size)
8561 ctx->object = template_id;
8562 ctx->objmask = NULL;
8566 /** Parse tokens for table create command. */
8568 parse_table(struct context *ctx, const struct token *token,
8569 const char *str, unsigned int len,
8570 void *buf, unsigned int size)
8572 struct buffer *out = buf;
8573 uint32_t *template_id;
8575 /* Token name must match. */
8576 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8578 /* Nothing else to do if there is no buffer. */
8581 if (!out->command) {
8582 if (ctx->curr != TABLE)
8584 if (sizeof(*out) > size)
8586 out->command = ctx->curr;
8589 ctx->objmask = NULL;
8592 switch (ctx->curr) {
8594 out->command = ctx->curr;
8597 ctx->objmask = NULL;
8598 out->args.table.id = UINT32_MAX;
8600 case TABLE_PATTERN_TEMPLATE:
8601 out->args.table.pat_templ_id =
8602 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8604 template_id = out->args.table.pat_templ_id
8605 + out->args.table.pat_templ_id_n++;
8606 if ((uint8_t *)template_id > (uint8_t *)out + size)
8609 ctx->object = template_id;
8610 ctx->objmask = NULL;
8612 case TABLE_ACTIONS_TEMPLATE:
8613 out->args.table.act_templ_id =
8614 (void *)RTE_ALIGN_CEIL((uintptr_t)
8615 (out->args.table.pat_templ_id +
8616 out->args.table.pat_templ_id_n),
8618 template_id = out->args.table.act_templ_id
8619 + out->args.table.act_templ_id_n++;
8620 if ((uint8_t *)template_id > (uint8_t *)out + size)
8623 ctx->object = template_id;
8624 ctx->objmask = NULL;
8627 out->args.table.attr.flow_attr.ingress = 1;
8630 out->args.table.attr.flow_attr.egress = 1;
8632 case TABLE_TRANSFER:
8633 out->args.table.attr.flow_attr.transfer = 1;
8640 /** Parse tokens for table destroy command. */
8642 parse_table_destroy(struct context *ctx, const struct token *token,
8643 const char *str, unsigned int len,
8644 void *buf, unsigned int size)
8646 struct buffer *out = buf;
8649 /* Token name must match. */
8650 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8652 /* Nothing else to do if there is no buffer. */
8655 if (!out->command || out->command == TABLE) {
8656 if (ctx->curr != TABLE_DESTROY)
8658 if (sizeof(*out) > size)
8660 out->command = ctx->curr;
8663 ctx->objmask = NULL;
8664 out->args.table_destroy.table_id =
8665 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8669 table_id = out->args.table_destroy.table_id
8670 + out->args.table_destroy.table_id_n++;
8671 if ((uint8_t *)table_id > (uint8_t *)out + size)
8674 ctx->object = table_id;
8675 ctx->objmask = NULL;
8679 /** Parse tokens for queue create commands. */
8681 parse_qo(struct context *ctx, const struct token *token,
8682 const char *str, unsigned int len,
8683 void *buf, unsigned int size)
8685 struct buffer *out = buf;
8687 /* Token name must match. */
8688 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8690 /* Nothing else to do if there is no buffer. */
8693 if (!out->command) {
8694 if (ctx->curr != QUEUE)
8696 if (sizeof(*out) > size)
8698 out->command = ctx->curr;
8701 ctx->objmask = NULL;
8702 out->args.vc.data = (uint8_t *)out + size;
8705 switch (ctx->curr) {
8707 out->command = ctx->curr;
8710 ctx->objmask = NULL;
8712 case QUEUE_TEMPLATE_TABLE:
8713 case QUEUE_PATTERN_TEMPLATE:
8714 case QUEUE_ACTIONS_TEMPLATE:
8715 case QUEUE_CREATE_POSTPONE:
8718 out->args.vc.pattern =
8719 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8721 ctx->object = out->args.vc.pattern;
8722 ctx->objmask = NULL;
8725 out->args.vc.actions =
8726 (void *)RTE_ALIGN_CEIL((uintptr_t)
8727 (out->args.vc.pattern +
8728 out->args.vc.pattern_n),
8730 ctx->object = out->args.vc.actions;
8731 ctx->objmask = NULL;
8738 /** Parse tokens for queue destroy command. */
8740 parse_qo_destroy(struct context *ctx, const struct token *token,
8741 const char *str, unsigned int len,
8742 void *buf, unsigned int size)
8744 struct buffer *out = buf;
8747 /* Token name must match. */
8748 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8750 /* Nothing else to do if there is no buffer. */
8753 if (!out->command || out->command == QUEUE) {
8754 if (ctx->curr != QUEUE_DESTROY)
8756 if (sizeof(*out) > size)
8758 out->command = ctx->curr;
8761 ctx->objmask = NULL;
8762 out->args.destroy.rule =
8763 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8767 switch (ctx->curr) {
8768 case QUEUE_DESTROY_ID:
8769 flow_id = out->args.destroy.rule
8770 + out->args.destroy.rule_n++;
8771 if ((uint8_t *)flow_id > (uint8_t *)out + size)
8774 ctx->object = flow_id;
8775 ctx->objmask = NULL;
8777 case QUEUE_DESTROY_POSTPONE:
8784 /** Parse tokens for push queue command. */
8786 parse_push(struct context *ctx, const struct token *token,
8787 const char *str, unsigned int len,
8788 void *buf, unsigned int size)
8790 struct buffer *out = buf;
8792 /* Token name must match. */
8793 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8795 /* Nothing else to do if there is no buffer. */
8798 if (!out->command) {
8799 if (ctx->curr != PUSH)
8801 if (sizeof(*out) > size)
8803 out->command = ctx->curr;
8806 ctx->objmask = NULL;
8807 out->args.vc.data = (uint8_t *)out + size;
8812 /** Parse tokens for pull command. */
8814 parse_pull(struct context *ctx, const struct token *token,
8815 const char *str, unsigned int len,
8816 void *buf, unsigned int size)
8818 struct buffer *out = buf;
8820 /* Token name must match. */
8821 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8823 /* Nothing else to do if there is no buffer. */
8826 if (!out->command) {
8827 if (ctx->curr != PULL)
8829 if (sizeof(*out) > size)
8831 out->command = ctx->curr;
8834 ctx->objmask = NULL;
8835 out->args.vc.data = (uint8_t *)out + size;
8841 parse_flex(struct context *ctx, const struct token *token,
8842 const char *str, unsigned int len,
8843 void *buf, unsigned int size)
8845 struct buffer *out = buf;
8847 /* Token name must match. */
8848 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8850 /* Nothing else to do if there is no buffer. */
8853 if (out->command == ZERO) {
8854 if (ctx->curr != FLEX)
8856 if (sizeof(*out) > size)
8858 out->command = ctx->curr;
8861 ctx->objmask = NULL;
8863 switch (ctx->curr) {
8866 case FLEX_ITEM_INIT:
8867 case FLEX_ITEM_CREATE:
8868 case FLEX_ITEM_DESTROY:
8869 out->command = ctx->curr;
8878 parse_tunnel(struct context *ctx, const struct token *token,
8879 const char *str, unsigned int len,
8880 void *buf, unsigned int size)
8882 struct buffer *out = buf;
8884 /* Token name must match. */
8885 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8887 /* Nothing else to do if there is no buffer. */
8890 if (!out->command) {
8891 if (ctx->curr != TUNNEL)
8893 if (sizeof(*out) > size)
8895 out->command = ctx->curr;
8898 ctx->objmask = NULL;
8900 switch (ctx->curr) {
8904 case TUNNEL_DESTROY:
8906 out->command = ctx->curr;
8908 case TUNNEL_CREATE_TYPE:
8909 case TUNNEL_DESTROY_ID:
8910 ctx->object = &out->args.vc.tunnel_ops;
8919 * Parse signed/unsigned integers 8 to 64-bit long.
8921 * Last argument (ctx->args) is retrieved to determine integer type and
8925 parse_int(struct context *ctx, const struct token *token,
8926 const char *str, unsigned int len,
8927 void *buf, unsigned int size)
8929 const struct arg *arg = pop_args(ctx);
8934 /* Argument is expected. */
8939 (uintmax_t)strtoimax(str, &end, 0) :
8940 strtoumax(str, &end, 0);
8941 if (errno || (size_t)(end - str) != len)
8944 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
8945 (intmax_t)u > (intmax_t)arg->max)) ||
8946 (!arg->sign && (u < arg->min || u > arg->max))))
8951 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
8952 !arg_entry_bf_fill(ctx->objmask, -1, arg))
8956 buf = (uint8_t *)ctx->object + arg->offset;
8958 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
8962 case sizeof(uint8_t):
8963 *(uint8_t *)buf = u;
8965 case sizeof(uint16_t):
8966 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
8968 case sizeof(uint8_t [3]):
8969 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8971 ((uint8_t *)buf)[0] = u;
8972 ((uint8_t *)buf)[1] = u >> 8;
8973 ((uint8_t *)buf)[2] = u >> 16;
8977 ((uint8_t *)buf)[0] = u >> 16;
8978 ((uint8_t *)buf)[1] = u >> 8;
8979 ((uint8_t *)buf)[2] = u;
8981 case sizeof(uint32_t):
8982 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
8984 case sizeof(uint64_t):
8985 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
8990 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
8992 buf = (uint8_t *)ctx->objmask + arg->offset;
8997 push_args(ctx, arg);
9004 * Three arguments (ctx->args) are retrieved from the stack to store data,
9005 * its actual length and address (in that order).
9008 parse_string(struct context *ctx, const struct token *token,
9009 const char *str, unsigned int len,
9010 void *buf, unsigned int size)
9012 const struct arg *arg_data = pop_args(ctx);
9013 const struct arg *arg_len = pop_args(ctx);
9014 const struct arg *arg_addr = pop_args(ctx);
9015 char tmp[16]; /* Ought to be enough. */
9018 /* Arguments are expected. */
9022 push_args(ctx, arg_data);
9026 push_args(ctx, arg_len);
9027 push_args(ctx, arg_data);
9030 size = arg_data->size;
9031 /* Bit-mask fill is not supported. */
9032 if (arg_data->mask || size < len)
9036 /* Let parse_int() fill length information first. */
9037 ret = snprintf(tmp, sizeof(tmp), "%u", len);
9040 push_args(ctx, arg_len);
9041 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
9046 buf = (uint8_t *)ctx->object + arg_data->offset;
9047 /* Output buffer is not necessarily NUL-terminated. */
9048 memcpy(buf, str, len);
9049 memset((uint8_t *)buf + len, 0x00, size - len);
9051 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
9052 /* Save address if requested. */
9053 if (arg_addr->size) {
9054 memcpy((uint8_t *)ctx->object + arg_addr->offset,
9056 (uint8_t *)ctx->object + arg_data->offset
9060 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
9062 (uint8_t *)ctx->objmask + arg_data->offset
9068 push_args(ctx, arg_addr);
9069 push_args(ctx, arg_len);
9070 push_args(ctx, arg_data);
9075 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
9077 const uint8_t *head = dst;
9080 /* Check input parameters */
9081 if ((src == NULL) ||
9089 /* Convert chars to bytes */
9091 char tmp[3], *end = tmp;
9092 uint32_t read_lim = left & 1 ? 1 : 2;
9094 snprintf(tmp, read_lim + 1, "%s", src);
9095 *dst = strtoul(tmp, &end, 16);
9098 *size = (uint32_t)(dst - head);
9106 *size = (uint32_t)(dst - head);
9111 parse_hex(struct context *ctx, const struct token *token,
9112 const char *str, unsigned int len,
9113 void *buf, unsigned int size)
9115 const struct arg *arg_data = pop_args(ctx);
9116 const struct arg *arg_len = pop_args(ctx);
9117 const struct arg *arg_addr = pop_args(ctx);
9118 char tmp[16]; /* Ought to be enough. */
9120 unsigned int hexlen = len;
9121 unsigned int length = 256;
9122 uint8_t hex_tmp[length];
9124 /* Arguments are expected. */
9128 push_args(ctx, arg_data);
9132 push_args(ctx, arg_len);
9133 push_args(ctx, arg_data);
9136 size = arg_data->size;
9137 /* Bit-mask fill is not supported. */
9143 /* translate bytes string to array. */
9144 if (str[0] == '0' && ((str[1] == 'x') ||
9149 if (hexlen > length)
9151 ret = parse_hex_string(str, hex_tmp, &hexlen);
9154 /* Check the converted binary fits into data buffer. */
9157 /* Let parse_int() fill length information first. */
9158 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
9161 /* Save length if requested. */
9162 if (arg_len->size) {
9163 push_args(ctx, arg_len);
9164 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
9170 buf = (uint8_t *)ctx->object + arg_data->offset;
9171 /* Output buffer is not necessarily NUL-terminated. */
9172 memcpy(buf, hex_tmp, hexlen);
9173 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
9175 memset((uint8_t *)ctx->objmask + arg_data->offset,
9177 /* Save address if requested. */
9178 if (arg_addr->size) {
9179 memcpy((uint8_t *)ctx->object + arg_addr->offset,
9181 (uint8_t *)ctx->object + arg_data->offset
9185 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
9187 (uint8_t *)ctx->objmask + arg_data->offset
9193 push_args(ctx, arg_addr);
9194 push_args(ctx, arg_len);
9195 push_args(ctx, arg_data);
9201 * Parse a zero-ended string.
9204 parse_string0(struct context *ctx, const struct token *token __rte_unused,
9205 const char *str, unsigned int len,
9206 void *buf, unsigned int size)
9208 const struct arg *arg_data = pop_args(ctx);
9210 /* Arguments are expected. */
9213 size = arg_data->size;
9214 /* Bit-mask fill is not supported. */
9215 if (arg_data->mask || size < len + 1)
9219 buf = (uint8_t *)ctx->object + arg_data->offset;
9220 strncpy(buf, str, len);
9222 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
9225 push_args(ctx, arg_data);
9230 * Parse a MAC address.
9232 * Last argument (ctx->args) is retrieved to determine storage size and
9236 parse_mac_addr(struct context *ctx, const struct token *token,
9237 const char *str, unsigned int len,
9238 void *buf, unsigned int size)
9240 const struct arg *arg = pop_args(ctx);
9241 struct rte_ether_addr tmp;
9245 /* Argument is expected. */
9249 /* Bit-mask fill is not supported. */
9250 if (arg->mask || size != sizeof(tmp))
9252 /* Only network endian is supported. */
9255 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
9256 if (ret < 0 || (unsigned int)ret != len)
9260 buf = (uint8_t *)ctx->object + arg->offset;
9261 memcpy(buf, &tmp, size);
9263 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9266 push_args(ctx, arg);
9271 * Parse an IPv4 address.
9273 * Last argument (ctx->args) is retrieved to determine storage size and
9277 parse_ipv4_addr(struct context *ctx, const struct token *token,
9278 const char *str, unsigned int len,
9279 void *buf, unsigned int size)
9281 const struct arg *arg = pop_args(ctx);
9286 /* Argument is expected. */
9290 /* Bit-mask fill is not supported. */
9291 if (arg->mask || size != sizeof(tmp))
9293 /* Only network endian is supported. */
9296 memcpy(str2, str, len);
9298 ret = inet_pton(AF_INET, str2, &tmp);
9300 /* Attempt integer parsing. */
9301 push_args(ctx, arg);
9302 return parse_int(ctx, token, str, len, buf, size);
9306 buf = (uint8_t *)ctx->object + arg->offset;
9307 memcpy(buf, &tmp, size);
9309 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9312 push_args(ctx, arg);
9317 * Parse an IPv6 address.
9319 * Last argument (ctx->args) is retrieved to determine storage size and
9323 parse_ipv6_addr(struct context *ctx, const struct token *token,
9324 const char *str, unsigned int len,
9325 void *buf, unsigned int size)
9327 const struct arg *arg = pop_args(ctx);
9329 struct in6_addr tmp;
9333 /* Argument is expected. */
9337 /* Bit-mask fill is not supported. */
9338 if (arg->mask || size != sizeof(tmp))
9340 /* Only network endian is supported. */
9343 memcpy(str2, str, len);
9345 ret = inet_pton(AF_INET6, str2, &tmp);
9350 buf = (uint8_t *)ctx->object + arg->offset;
9351 memcpy(buf, &tmp, size);
9353 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9356 push_args(ctx, arg);
9360 /** Boolean values (even indices stand for false). */
9361 static const char *const boolean_name[] = {
9371 * Parse a boolean value.
9373 * Last argument (ctx->args) is retrieved to determine storage size and
9377 parse_boolean(struct context *ctx, const struct token *token,
9378 const char *str, unsigned int len,
9379 void *buf, unsigned int size)
9381 const struct arg *arg = pop_args(ctx);
9385 /* Argument is expected. */
9388 for (i = 0; boolean_name[i]; ++i)
9389 if (!strcmp_partial(boolean_name[i], str, len))
9391 /* Process token as integer. */
9392 if (boolean_name[i])
9393 str = i & 1 ? "1" : "0";
9394 push_args(ctx, arg);
9395 ret = parse_int(ctx, token, str, strlen(str), buf, size);
9396 return ret > 0 ? (int)len : ret;
9399 /** Parse port and update context. */
9401 parse_port(struct context *ctx, const struct token *token,
9402 const char *str, unsigned int len,
9403 void *buf, unsigned int size)
9405 struct buffer *out = &(struct buffer){ .port = 0 };
9413 ctx->objmask = NULL;
9414 size = sizeof(*out);
9416 ret = parse_int(ctx, token, str, len, out, size);
9418 ctx->port = out->port;
9425 parse_ia_id2ptr(struct context *ctx, const struct token *token,
9426 const char *str, unsigned int len,
9427 void *buf, unsigned int size)
9429 struct rte_flow_action *action = ctx->object;
9437 ctx->objmask = NULL;
9438 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
9439 ctx->object = action;
9440 if (ret != (int)len)
9442 /* set indirect action */
9444 action->conf = port_action_handle_get_by_id(ctx->port, id);
9445 ret = (action->conf) ? ret : -1;
9450 /** Parse set command, initialize output buffer for subsequent tokens. */
9452 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
9453 const char *str, unsigned int len,
9454 void *buf, unsigned int size)
9456 struct buffer *out = buf;
9458 /* Token name must match. */
9459 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9461 /* Nothing else to do if there is no buffer. */
9464 /* Make sure buffer is large enough. */
9465 if (size < sizeof(*out))
9468 ctx->objmask = NULL;
9472 out->command = ctx->curr;
9473 /* For encap/decap we need is pattern */
9474 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9479 /** Parse set command, initialize output buffer for subsequent tokens. */
9481 parse_set_sample_action(struct context *ctx, const struct token *token,
9482 const char *str, unsigned int len,
9483 void *buf, unsigned int size)
9485 struct buffer *out = buf;
9487 /* Token name must match. */
9488 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9490 /* Nothing else to do if there is no buffer. */
9493 /* Make sure buffer is large enough. */
9494 if (size < sizeof(*out))
9497 ctx->objmask = NULL;
9501 out->command = ctx->curr;
9502 /* For sampler we need is actions */
9503 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9509 * Parse set raw_encap/raw_decap command,
9510 * initialize output buffer for subsequent tokens.
9513 parse_set_init(struct context *ctx, const struct token *token,
9514 const char *str, unsigned int len,
9515 void *buf, unsigned int size)
9517 struct buffer *out = buf;
9519 /* Token name must match. */
9520 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9522 /* Nothing else to do if there is no buffer. */
9525 /* Make sure buffer is large enough. */
9526 if (size < sizeof(*out))
9528 /* Initialize buffer. */
9529 memset(out, 0x00, sizeof(*out));
9530 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
9533 ctx->objmask = NULL;
9534 if (!out->command) {
9535 if (ctx->curr != SET)
9537 if (sizeof(*out) > size)
9539 out->command = ctx->curr;
9540 out->args.vc.data = (uint8_t *)out + size;
9541 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9548 * Replace testpmd handles in a flex flow item with real values.
9551 parse_flex_handle(struct context *ctx, const struct token *token,
9552 const char *str, unsigned int len,
9553 void *buf, unsigned int size)
9555 struct rte_flow_item_flex *spec, *mask;
9556 const struct rte_flow_item_flex *src_spec, *src_mask;
9557 const struct arg *arg = pop_args(ctx);
9563 printf("Bad environment\n");
9566 offset = arg->offset;
9567 push_args(ctx, arg);
9568 ret = parse_int(ctx, token, str, len, buf, size);
9569 if (ret <= 0 || !ctx->object)
9571 if (ctx->port >= RTE_MAX_ETHPORTS) {
9572 printf("Bad port\n");
9575 if (offset == offsetof(struct rte_flow_item_flex, handle)) {
9576 const struct flex_item *fp;
9577 struct rte_flow_item_flex *item_flex = ctx->object;
9578 handle = (uint16_t)(uintptr_t)item_flex->handle;
9579 if (handle >= FLEX_MAX_PARSERS_NUM) {
9580 printf("Bad flex item handle\n");
9583 fp = flex_items[ctx->port][handle];
9585 printf("Bad flex item handle\n");
9588 item_flex->handle = fp->flex_handle;
9589 } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
9590 handle = (uint16_t)(uintptr_t)
9591 ((struct rte_flow_item_flex *)ctx->object)->pattern;
9592 if (handle >= FLEX_MAX_PATTERNS_NUM) {
9593 printf("Bad pattern handle\n");
9596 src_spec = &flex_patterns[handle].spec;
9597 src_mask = &flex_patterns[handle].mask;
9599 mask = spec + 2; /* spec, last, mask */
9600 /* fill flow rule spec and mask parameters */
9601 spec->length = src_spec->length;
9602 spec->pattern = src_spec->pattern;
9603 mask->length = src_mask->length;
9604 mask->pattern = src_mask->pattern;
9606 printf("Bad arguments - unknown flex item offset\n");
9612 /** No completion. */
9614 comp_none(struct context *ctx, const struct token *token,
9615 unsigned int ent, char *buf, unsigned int size)
9625 /** Complete boolean values. */
9627 comp_boolean(struct context *ctx, const struct token *token,
9628 unsigned int ent, char *buf, unsigned int size)
9634 for (i = 0; boolean_name[i]; ++i)
9635 if (buf && i == ent)
9636 return strlcpy(buf, boolean_name[i], size);
9642 /** Complete action names. */
9644 comp_action(struct context *ctx, const struct token *token,
9645 unsigned int ent, char *buf, unsigned int size)
9651 for (i = 0; next_action[i]; ++i)
9652 if (buf && i == ent)
9653 return strlcpy(buf, token_list[next_action[i]].name,
9660 /** Complete available ports. */
9662 comp_port(struct context *ctx, const struct token *token,
9663 unsigned int ent, char *buf, unsigned int size)
9670 RTE_ETH_FOREACH_DEV(p) {
9671 if (buf && i == ent)
9672 return snprintf(buf, size, "%u", p);
9680 /** Complete available rule IDs. */
9682 comp_rule_id(struct context *ctx, const struct token *token,
9683 unsigned int ent, char *buf, unsigned int size)
9686 struct rte_port *port;
9687 struct port_flow *pf;
9690 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9691 ctx->port == (portid_t)RTE_PORT_ALL)
9693 port = &ports[ctx->port];
9694 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
9695 if (buf && i == ent)
9696 return snprintf(buf, size, "%u", pf->id);
9704 /** Complete type field for RSS action. */
9706 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
9707 unsigned int ent, char *buf, unsigned int size)
9713 for (i = 0; rss_type_table[i].str; ++i)
9718 return strlcpy(buf, rss_type_table[ent].str, size);
9720 return snprintf(buf, size, "end");
9724 /** Complete queue field for RSS action. */
9726 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
9727 unsigned int ent, char *buf, unsigned int size)
9734 return snprintf(buf, size, "%u", ent);
9736 return snprintf(buf, size, "end");
9740 /** Complete index number for set raw_encap/raw_decap commands. */
9742 comp_set_raw_index(struct context *ctx, const struct token *token,
9743 unsigned int ent, char *buf, unsigned int size)
9749 RTE_SET_USED(token);
9750 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
9751 if (buf && idx == ent)
9752 return snprintf(buf, size, "%u", idx);
9758 /** Complete index number for set raw_encap/raw_decap commands. */
9760 comp_set_sample_index(struct context *ctx, const struct token *token,
9761 unsigned int ent, char *buf, unsigned int size)
9767 RTE_SET_USED(token);
9768 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
9769 if (buf && idx == ent)
9770 return snprintf(buf, size, "%u", idx);
9776 /** Complete operation for modify_field command. */
9778 comp_set_modify_field_op(struct context *ctx, const struct token *token,
9779 unsigned int ent, char *buf, unsigned int size)
9782 RTE_SET_USED(token);
9784 return RTE_DIM(modify_field_ops);
9785 if (ent < RTE_DIM(modify_field_ops) - 1)
9786 return strlcpy(buf, modify_field_ops[ent], size);
9790 /** Complete field id for modify_field command. */
9792 comp_set_modify_field_id(struct context *ctx, const struct token *token,
9793 unsigned int ent, char *buf, unsigned int size)
9797 RTE_SET_USED(token);
9799 return RTE_DIM(modify_field_ids);
9800 if (ent >= RTE_DIM(modify_field_ids) - 1)
9802 name = modify_field_ids[ent];
9803 if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
9804 (strcmp(name, "pointer") && strcmp(name, "value")))
9805 return strlcpy(buf, name, size);
9809 /** Complete available pattern template IDs. */
9811 comp_pattern_template_id(struct context *ctx, const struct token *token,
9812 unsigned int ent, char *buf, unsigned int size)
9815 struct rte_port *port;
9816 struct port_template *pt;
9819 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9820 ctx->port == (portid_t)RTE_PORT_ALL)
9822 port = &ports[ctx->port];
9823 for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
9824 if (buf && i == ent)
9825 return snprintf(buf, size, "%u", pt->id);
9833 /** Complete available actions template IDs. */
9835 comp_actions_template_id(struct context *ctx, const struct token *token,
9836 unsigned int ent, char *buf, unsigned int size)
9839 struct rte_port *port;
9840 struct port_template *pt;
9843 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9844 ctx->port == (portid_t)RTE_PORT_ALL)
9846 port = &ports[ctx->port];
9847 for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
9848 if (buf && i == ent)
9849 return snprintf(buf, size, "%u", pt->id);
9857 /** Complete available table IDs. */
9859 comp_table_id(struct context *ctx, const struct token *token,
9860 unsigned int ent, char *buf, unsigned int size)
9863 struct rte_port *port;
9864 struct port_table *pt;
9867 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9868 ctx->port == (portid_t)RTE_PORT_ALL)
9870 port = &ports[ctx->port];
9871 for (pt = port->table_list; pt != NULL; pt = pt->next) {
9872 if (buf && i == ent)
9873 return snprintf(buf, size, "%u", pt->id);
9881 /** Complete available queue IDs. */
9883 comp_queue_id(struct context *ctx, const struct token *token,
9884 unsigned int ent, char *buf, unsigned int size)
9887 struct rte_port *port;
9890 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9891 ctx->port == (portid_t)RTE_PORT_ALL)
9893 port = &ports[ctx->port];
9894 for (i = 0; i < port->queue_nb; i++) {
9895 if (buf && i == ent)
9896 return snprintf(buf, size, "%u", i);
9903 /** Internal context. */
9904 static struct context cmd_flow_context;
9906 /** Global parser instance (cmdline API). */
9907 cmdline_parse_inst_t cmd_flow;
9908 cmdline_parse_inst_t cmd_set_raw;
9910 /** Initialize context. */
9912 cmd_flow_context_init(struct context *ctx)
9914 /* A full memset() is not necessary. */
9924 ctx->objmask = NULL;
9927 /** Parse a token (cmdline API). */
9929 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
9932 struct context *ctx = &cmd_flow_context;
9933 const struct token *token;
9934 const enum index *list;
9939 token = &token_list[ctx->curr];
9940 /* Check argument length. */
9943 for (len = 0; src[len]; ++len)
9944 if (src[len] == '#' || isspace(src[len]))
9948 /* Last argument and EOL detection. */
9949 for (i = len; src[i]; ++i)
9950 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
9952 else if (!isspace(src[i])) {
9957 if (src[i] == '\r' || src[i] == '\n') {
9961 /* Initialize context if necessary. */
9962 if (!ctx->next_num) {
9965 ctx->next[ctx->next_num++] = token->next[0];
9967 /* Process argument through candidates. */
9968 ctx->prev = ctx->curr;
9969 list = ctx->next[ctx->next_num - 1];
9970 for (i = 0; list[i]; ++i) {
9971 const struct token *next = &token_list[list[i]];
9974 ctx->curr = list[i];
9976 tmp = next->call(ctx, next, src, len, result, size);
9978 tmp = parse_default(ctx, next, src, len, result, size);
9979 if (tmp == -1 || tmp != len)
9987 /* Push subsequent tokens if any. */
9989 for (i = 0; token->next[i]; ++i) {
9990 if (ctx->next_num == RTE_DIM(ctx->next))
9992 ctx->next[ctx->next_num++] = token->next[i];
9994 /* Push arguments if any. */
9996 for (i = 0; token->args[i]; ++i) {
9997 if (ctx->args_num == RTE_DIM(ctx->args))
9999 ctx->args[ctx->args_num++] = token->args[i];
10005 flow_parse(const char *src, void *result, unsigned int size,
10006 struct rte_flow_attr **attr,
10007 struct rte_flow_item **pattern, struct rte_flow_action **actions)
10010 struct context saved_flow_ctx = cmd_flow_context;
10012 cmd_flow_context_init(&cmd_flow_context);
10014 ret = cmd_flow_parse(NULL, src, result, size);
10017 while (isspace(*src))
10020 } while (ret > 0 && strlen(src));
10021 cmd_flow_context = saved_flow_ctx;
10022 *attr = &((struct buffer *)result)->args.vc.attr;
10023 *pattern = ((struct buffer *)result)->args.vc.pattern;
10024 *actions = ((struct buffer *)result)->args.vc.actions;
10025 return (ret >= 0 && !strlen(src)) ? 0 : -1;
10028 /** Return number of completion entries (cmdline API). */
10030 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
10032 struct context *ctx = &cmd_flow_context;
10033 const struct token *token = &token_list[ctx->curr];
10034 const enum index *list;
10038 /* Count number of tokens in current list. */
10040 list = ctx->next[ctx->next_num - 1];
10042 list = token->next[0];
10043 for (i = 0; list[i]; ++i)
10048 * If there is a single token, use its completion callback, otherwise
10049 * return the number of entries.
10051 token = &token_list[list[0]];
10052 if (i == 1 && token->comp) {
10053 /* Save index for cmd_flow_get_help(). */
10054 ctx->prev = list[0];
10055 return token->comp(ctx, token, 0, NULL, 0);
10060 /** Return a completion entry (cmdline API). */
10062 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
10063 char *dst, unsigned int size)
10065 struct context *ctx = &cmd_flow_context;
10066 const struct token *token = &token_list[ctx->curr];
10067 const enum index *list;
10071 /* Count number of tokens in current list. */
10073 list = ctx->next[ctx->next_num - 1];
10075 list = token->next[0];
10076 for (i = 0; list[i]; ++i)
10080 /* If there is a single token, use its completion callback. */
10081 token = &token_list[list[0]];
10082 if (i == 1 && token->comp) {
10083 /* Save index for cmd_flow_get_help(). */
10084 ctx->prev = list[0];
10085 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
10087 /* Otherwise make sure the index is valid and use defaults. */
10090 token = &token_list[list[index]];
10091 strlcpy(dst, token->name, size);
10092 /* Save index for cmd_flow_get_help(). */
10093 ctx->prev = list[index];
10097 /** Populate help strings for current token (cmdline API). */
10099 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
10101 struct context *ctx = &cmd_flow_context;
10102 const struct token *token = &token_list[ctx->prev];
10107 /* Set token type and update global help with details. */
10108 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
10110 cmd_flow.help_str = token->help;
10112 cmd_flow.help_str = token->name;
10116 /** Token definition template (cmdline API). */
10117 static struct cmdline_token_hdr cmd_flow_token_hdr = {
10118 .ops = &(struct cmdline_token_ops){
10119 .parse = cmd_flow_parse,
10120 .complete_get_nb = cmd_flow_complete_get_nb,
10121 .complete_get_elt = cmd_flow_complete_get_elt,
10122 .get_help = cmd_flow_get_help,
10127 /** Populate the next dynamic token. */
10129 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
10130 cmdline_parse_token_hdr_t **hdr_inst)
10132 struct context *ctx = &cmd_flow_context;
10134 /* Always reinitialize context before requesting the first token. */
10135 if (!(hdr_inst - cmd_flow.tokens))
10136 cmd_flow_context_init(ctx);
10137 /* Return NULL when no more tokens are expected. */
10138 if (!ctx->next_num && ctx->curr) {
10142 /* Determine if command should end here. */
10143 if (ctx->eol && ctx->last && ctx->next_num) {
10144 const enum index *list = ctx->next[ctx->next_num - 1];
10147 for (i = 0; list[i]; ++i) {
10148 if (list[i] != END)
10154 *hdr = &cmd_flow_token_hdr;
10157 /** Dispatch parsed buffer to function calls. */
10159 cmd_flow_parsed(const struct buffer *in)
10161 switch (in->command) {
10163 port_flow_get_info(in->port);
10166 port_flow_configure(in->port,
10167 &in->args.configure.port_attr,
10168 in->args.configure.nb_queue,
10169 &in->args.configure.queue_attr);
10171 case PATTERN_TEMPLATE_CREATE:
10172 port_flow_pattern_template_create(in->port,
10173 in->args.vc.pat_templ_id,
10174 &((const struct rte_flow_pattern_template_attr) {
10175 .relaxed_matching = in->args.vc.attr.reserved,
10176 .ingress = in->args.vc.attr.ingress,
10177 .egress = in->args.vc.attr.egress,
10178 .transfer = in->args.vc.attr.transfer,
10180 in->args.vc.pattern);
10182 case PATTERN_TEMPLATE_DESTROY:
10183 port_flow_pattern_template_destroy(in->port,
10184 in->args.templ_destroy.template_id_n,
10185 in->args.templ_destroy.template_id);
10187 case ACTIONS_TEMPLATE_CREATE:
10188 port_flow_actions_template_create(in->port,
10189 in->args.vc.act_templ_id,
10190 &((const struct rte_flow_actions_template_attr) {
10191 .ingress = in->args.vc.attr.ingress,
10192 .egress = in->args.vc.attr.egress,
10193 .transfer = in->args.vc.attr.transfer,
10195 in->args.vc.actions,
10196 in->args.vc.masks);
10198 case ACTIONS_TEMPLATE_DESTROY:
10199 port_flow_actions_template_destroy(in->port,
10200 in->args.templ_destroy.template_id_n,
10201 in->args.templ_destroy.template_id);
10204 port_flow_template_table_create(in->port, in->args.table.id,
10205 &in->args.table.attr, in->args.table.pat_templ_id_n,
10206 in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
10207 in->args.table.act_templ_id);
10209 case TABLE_DESTROY:
10210 port_flow_template_table_destroy(in->port,
10211 in->args.table_destroy.table_id_n,
10212 in->args.table_destroy.table_id);
10215 port_queue_flow_create(in->port, in->queue, in->postpone,
10216 in->args.vc.table_id, in->args.vc.pat_templ_id,
10217 in->args.vc.act_templ_id, in->args.vc.pattern,
10218 in->args.vc.actions);
10220 case QUEUE_DESTROY:
10221 port_queue_flow_destroy(in->port, in->queue, in->postpone,
10222 in->args.destroy.rule_n,
10223 in->args.destroy.rule);
10226 port_queue_flow_push(in->port, in->queue);
10229 port_queue_flow_pull(in->port, in->queue);
10231 case INDIRECT_ACTION_CREATE:
10232 port_action_handle_create(
10233 in->port, in->args.vc.attr.group,
10234 &((const struct rte_flow_indir_action_conf) {
10235 .ingress = in->args.vc.attr.ingress,
10236 .egress = in->args.vc.attr.egress,
10237 .transfer = in->args.vc.attr.transfer,
10239 in->args.vc.actions);
10241 case INDIRECT_ACTION_DESTROY:
10242 port_action_handle_destroy(in->port,
10243 in->args.ia_destroy.action_id_n,
10244 in->args.ia_destroy.action_id);
10246 case INDIRECT_ACTION_UPDATE:
10247 port_action_handle_update(in->port, in->args.vc.attr.group,
10248 in->args.vc.actions);
10250 case INDIRECT_ACTION_QUERY:
10251 port_action_handle_query(in->port, in->args.ia.action_id);
10254 port_flow_validate(in->port, &in->args.vc.attr,
10255 in->args.vc.pattern, in->args.vc.actions,
10256 &in->args.vc.tunnel_ops);
10259 port_flow_create(in->port, &in->args.vc.attr,
10260 in->args.vc.pattern, in->args.vc.actions,
10261 &in->args.vc.tunnel_ops);
10264 port_flow_destroy(in->port, in->args.destroy.rule_n,
10265 in->args.destroy.rule);
10268 port_flow_flush(in->port);
10272 port_flow_dump(in->port, in->args.dump.mode,
10273 in->args.dump.rule, in->args.dump.file);
10276 port_flow_query(in->port, in->args.query.rule,
10277 &in->args.query.action);
10280 port_flow_list(in->port, in->args.list.group_n,
10281 in->args.list.group);
10284 port_flow_isolate(in->port, in->args.isolate.set);
10287 port_flow_aged(in->port, in->args.aged.destroy);
10289 case TUNNEL_CREATE:
10290 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
10292 case TUNNEL_DESTROY:
10293 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
10296 port_flow_tunnel_list(in->port);
10299 port_meter_policy_add(in->port, in->args.policy.policy_id,
10300 in->args.vc.actions);
10302 case FLEX_ITEM_CREATE:
10303 flex_item_create(in->port, in->args.flex.token,
10304 in->args.flex.filename);
10306 case FLEX_ITEM_DESTROY:
10307 flex_item_destroy(in->port, in->args.flex.token);
10314 /** Token generator and output processing callback (cmdline API). */
10316 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
10319 cmd_flow_tok(arg0, arg2);
10321 cmd_flow_parsed(arg0);
10324 /** Global parser instance (cmdline API). */
10325 cmdline_parse_inst_t cmd_flow = {
10327 .data = NULL, /**< Unused. */
10328 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
10331 }, /**< Tokens are returned by cmd_flow_tok(). */
10334 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
10337 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
10339 struct rte_ipv4_hdr *ipv4;
10340 struct rte_ether_hdr *eth;
10341 struct rte_ipv6_hdr *ipv6;
10342 struct rte_vxlan_hdr *vxlan;
10343 struct rte_vxlan_gpe_hdr *gpe;
10344 struct rte_flow_item_nvgre *nvgre;
10345 uint32_t ipv6_vtc_flow;
10347 switch (item->type) {
10348 case RTE_FLOW_ITEM_TYPE_ETH:
10349 eth = (struct rte_ether_hdr *)buf;
10351 eth->ether_type = rte_cpu_to_be_16(next_proto);
10353 case RTE_FLOW_ITEM_TYPE_IPV4:
10354 ipv4 = (struct rte_ipv4_hdr *)buf;
10355 if (!ipv4->version_ihl)
10356 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
10357 if (next_proto && ipv4->next_proto_id == 0)
10358 ipv4->next_proto_id = (uint8_t)next_proto;
10360 case RTE_FLOW_ITEM_TYPE_IPV6:
10361 ipv6 = (struct rte_ipv6_hdr *)buf;
10362 if (next_proto && ipv6->proto == 0)
10363 ipv6->proto = (uint8_t)next_proto;
10364 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
10365 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
10366 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
10367 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
10369 case RTE_FLOW_ITEM_TYPE_VXLAN:
10370 vxlan = (struct rte_vxlan_hdr *)buf;
10371 vxlan->vx_flags = 0x08;
10373 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10374 gpe = (struct rte_vxlan_gpe_hdr *)buf;
10375 gpe->vx_flags = 0x0C;
10377 case RTE_FLOW_ITEM_TYPE_NVGRE:
10378 nvgre = (struct rte_flow_item_nvgre *)buf;
10379 nvgre->protocol = rte_cpu_to_be_16(0x6558);
10380 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
10387 /** Helper of get item's default mask. */
10388 static const void *
10389 flow_item_default_mask(const struct rte_flow_item *item)
10391 const void *mask = NULL;
10392 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
10394 switch (item->type) {
10395 case RTE_FLOW_ITEM_TYPE_ANY:
10396 mask = &rte_flow_item_any_mask;
10398 case RTE_FLOW_ITEM_TYPE_VF:
10399 mask = &rte_flow_item_vf_mask;
10401 case RTE_FLOW_ITEM_TYPE_PORT_ID:
10402 mask = &rte_flow_item_port_id_mask;
10404 case RTE_FLOW_ITEM_TYPE_RAW:
10405 mask = &rte_flow_item_raw_mask;
10407 case RTE_FLOW_ITEM_TYPE_ETH:
10408 mask = &rte_flow_item_eth_mask;
10410 case RTE_FLOW_ITEM_TYPE_VLAN:
10411 mask = &rte_flow_item_vlan_mask;
10413 case RTE_FLOW_ITEM_TYPE_IPV4:
10414 mask = &rte_flow_item_ipv4_mask;
10416 case RTE_FLOW_ITEM_TYPE_IPV6:
10417 mask = &rte_flow_item_ipv6_mask;
10419 case RTE_FLOW_ITEM_TYPE_ICMP:
10420 mask = &rte_flow_item_icmp_mask;
10422 case RTE_FLOW_ITEM_TYPE_UDP:
10423 mask = &rte_flow_item_udp_mask;
10425 case RTE_FLOW_ITEM_TYPE_TCP:
10426 mask = &rte_flow_item_tcp_mask;
10428 case RTE_FLOW_ITEM_TYPE_SCTP:
10429 mask = &rte_flow_item_sctp_mask;
10431 case RTE_FLOW_ITEM_TYPE_VXLAN:
10432 mask = &rte_flow_item_vxlan_mask;
10434 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10435 mask = &rte_flow_item_vxlan_gpe_mask;
10437 case RTE_FLOW_ITEM_TYPE_E_TAG:
10438 mask = &rte_flow_item_e_tag_mask;
10440 case RTE_FLOW_ITEM_TYPE_NVGRE:
10441 mask = &rte_flow_item_nvgre_mask;
10443 case RTE_FLOW_ITEM_TYPE_MPLS:
10444 mask = &rte_flow_item_mpls_mask;
10446 case RTE_FLOW_ITEM_TYPE_GRE:
10447 mask = &rte_flow_item_gre_mask;
10449 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
10450 mask = &gre_key_default_mask;
10452 case RTE_FLOW_ITEM_TYPE_META:
10453 mask = &rte_flow_item_meta_mask;
10455 case RTE_FLOW_ITEM_TYPE_FUZZY:
10456 mask = &rte_flow_item_fuzzy_mask;
10458 case RTE_FLOW_ITEM_TYPE_GTP:
10459 mask = &rte_flow_item_gtp_mask;
10461 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
10462 mask = &rte_flow_item_gtp_psc_mask;
10464 case RTE_FLOW_ITEM_TYPE_GENEVE:
10465 mask = &rte_flow_item_geneve_mask;
10467 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
10468 mask = &rte_flow_item_geneve_opt_mask;
10470 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
10471 mask = &rte_flow_item_pppoe_proto_id_mask;
10473 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
10474 mask = &rte_flow_item_l2tpv3oip_mask;
10476 case RTE_FLOW_ITEM_TYPE_ESP:
10477 mask = &rte_flow_item_esp_mask;
10479 case RTE_FLOW_ITEM_TYPE_AH:
10480 mask = &rte_flow_item_ah_mask;
10482 case RTE_FLOW_ITEM_TYPE_PFCP:
10483 mask = &rte_flow_item_pfcp_mask;
10485 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
10486 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
10487 mask = &rte_flow_item_ethdev_mask;
10489 case RTE_FLOW_ITEM_TYPE_L2TPV2:
10490 mask = &rte_flow_item_l2tpv2_mask;
10492 case RTE_FLOW_ITEM_TYPE_PPP:
10493 mask = &rte_flow_item_ppp_mask;
10501 /** Dispatch parsed buffer to function calls. */
10503 cmd_set_raw_parsed_sample(const struct buffer *in)
10505 uint32_t n = in->args.vc.actions_n;
10507 struct rte_flow_action *action = NULL;
10508 struct rte_flow_action *data = NULL;
10509 const struct rte_flow_action_rss *rss = NULL;
10511 uint16_t idx = in->port; /* We borrow port field as index */
10512 uint32_t max_size = sizeof(struct rte_flow_action) *
10513 ACTION_SAMPLE_ACTIONS_NUM;
10515 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
10516 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
10517 memset(data, 0x00, max_size);
10518 for (; i <= n - 1; i++) {
10519 action = in->args.vc.actions + i;
10520 if (action->type == RTE_FLOW_ACTION_TYPE_END)
10522 switch (action->type) {
10523 case RTE_FLOW_ACTION_TYPE_MARK:
10524 size = sizeof(struct rte_flow_action_mark);
10525 rte_memcpy(&sample_mark[idx],
10526 (const void *)action->conf, size);
10527 action->conf = &sample_mark[idx];
10529 case RTE_FLOW_ACTION_TYPE_COUNT:
10530 size = sizeof(struct rte_flow_action_count);
10531 rte_memcpy(&sample_count[idx],
10532 (const void *)action->conf, size);
10533 action->conf = &sample_count[idx];
10535 case RTE_FLOW_ACTION_TYPE_QUEUE:
10536 size = sizeof(struct rte_flow_action_queue);
10537 rte_memcpy(&sample_queue[idx],
10538 (const void *)action->conf, size);
10539 action->conf = &sample_queue[idx];
10541 case RTE_FLOW_ACTION_TYPE_RSS:
10542 size = sizeof(struct rte_flow_action_rss);
10543 rss = action->conf;
10544 rte_memcpy(&sample_rss_data[idx].conf,
10545 (const void *)rss, size);
10546 if (rss->key_len && rss->key) {
10547 sample_rss_data[idx].conf.key =
10548 sample_rss_data[idx].key;
10549 rte_memcpy((void *)((uintptr_t)
10550 sample_rss_data[idx].conf.key),
10551 (const void *)rss->key,
10552 sizeof(uint8_t) * rss->key_len);
10554 if (rss->queue_num && rss->queue) {
10555 sample_rss_data[idx].conf.queue =
10556 sample_rss_data[idx].queue;
10557 rte_memcpy((void *)((uintptr_t)
10558 sample_rss_data[idx].conf.queue),
10559 (const void *)rss->queue,
10560 sizeof(uint16_t) * rss->queue_num);
10562 action->conf = &sample_rss_data[idx].conf;
10564 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
10565 size = sizeof(struct rte_flow_action_raw_encap);
10566 rte_memcpy(&sample_encap[idx],
10567 (const void *)action->conf, size);
10568 action->conf = &sample_encap[idx];
10570 case RTE_FLOW_ACTION_TYPE_PORT_ID:
10571 size = sizeof(struct rte_flow_action_port_id);
10572 rte_memcpy(&sample_port_id[idx],
10573 (const void *)action->conf, size);
10574 action->conf = &sample_port_id[idx];
10576 case RTE_FLOW_ACTION_TYPE_PF:
10578 case RTE_FLOW_ACTION_TYPE_VF:
10579 size = sizeof(struct rte_flow_action_vf);
10580 rte_memcpy(&sample_vf[idx],
10581 (const void *)action->conf, size);
10582 action->conf = &sample_vf[idx];
10584 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
10585 size = sizeof(struct rte_flow_action_vxlan_encap);
10586 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
10587 action->conf = &sample_vxlan_encap[idx].conf;
10589 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
10590 size = sizeof(struct rte_flow_action_nvgre_encap);
10591 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
10592 action->conf = &sample_nvgre_encap[idx];
10595 fprintf(stderr, "Error - Not supported action\n");
10598 rte_memcpy(data, action, sizeof(struct rte_flow_action));
10603 /** Dispatch parsed buffer to function calls. */
10605 cmd_set_raw_parsed(const struct buffer *in)
10607 uint32_t n = in->args.vc.pattern_n;
10609 struct rte_flow_item *item = NULL;
10611 uint8_t *data = NULL;
10612 uint8_t *data_tail = NULL;
10613 size_t *total_size = NULL;
10614 uint16_t upper_layer = 0;
10615 uint16_t proto = 0;
10616 uint16_t idx = in->port; /* We borrow port field as index */
10617 int gtp_psc = -1; /* GTP PSC option index. */
10619 if (in->command == SET_SAMPLE_ACTIONS)
10620 return cmd_set_raw_parsed_sample(in);
10621 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
10622 in->command == SET_RAW_DECAP);
10623 if (in->command == SET_RAW_ENCAP) {
10624 total_size = &raw_encap_confs[idx].size;
10625 data = (uint8_t *)&raw_encap_confs[idx].data;
10627 total_size = &raw_decap_confs[idx].size;
10628 data = (uint8_t *)&raw_decap_confs[idx].data;
10631 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
10632 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
10633 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
10634 for (i = n - 1 ; i >= 0; --i) {
10635 const struct rte_flow_item_gtp *gtp;
10636 const struct rte_flow_item_geneve_opt *opt;
10638 item = in->args.vc.pattern + i;
10639 if (item->spec == NULL)
10640 item->spec = flow_item_default_mask(item);
10641 switch (item->type) {
10642 case RTE_FLOW_ITEM_TYPE_ETH:
10643 size = sizeof(struct rte_ether_hdr);
10645 case RTE_FLOW_ITEM_TYPE_VLAN:
10646 size = sizeof(struct rte_vlan_hdr);
10647 proto = RTE_ETHER_TYPE_VLAN;
10649 case RTE_FLOW_ITEM_TYPE_IPV4:
10650 size = sizeof(struct rte_ipv4_hdr);
10651 proto = RTE_ETHER_TYPE_IPV4;
10653 case RTE_FLOW_ITEM_TYPE_IPV6:
10654 size = sizeof(struct rte_ipv6_hdr);
10655 proto = RTE_ETHER_TYPE_IPV6;
10657 case RTE_FLOW_ITEM_TYPE_UDP:
10658 size = sizeof(struct rte_udp_hdr);
10661 case RTE_FLOW_ITEM_TYPE_TCP:
10662 size = sizeof(struct rte_tcp_hdr);
10665 case RTE_FLOW_ITEM_TYPE_VXLAN:
10666 size = sizeof(struct rte_vxlan_hdr);
10668 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10669 size = sizeof(struct rte_vxlan_gpe_hdr);
10671 case RTE_FLOW_ITEM_TYPE_GRE:
10672 size = sizeof(struct rte_gre_hdr);
10675 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
10676 size = sizeof(rte_be32_t);
10679 case RTE_FLOW_ITEM_TYPE_MPLS:
10680 size = sizeof(struct rte_mpls_hdr);
10683 case RTE_FLOW_ITEM_TYPE_NVGRE:
10684 size = sizeof(struct rte_flow_item_nvgre);
10687 case RTE_FLOW_ITEM_TYPE_GENEVE:
10688 size = sizeof(struct rte_geneve_hdr);
10690 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
10691 opt = (const struct rte_flow_item_geneve_opt *)
10693 size = offsetof(struct rte_flow_item_geneve_opt, data);
10694 if (opt->option_len && opt->data) {
10695 *total_size += opt->option_len *
10697 rte_memcpy(data_tail - (*total_size),
10699 opt->option_len * sizeof(uint32_t));
10702 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
10703 size = sizeof(rte_be32_t);
10706 case RTE_FLOW_ITEM_TYPE_ESP:
10707 size = sizeof(struct rte_esp_hdr);
10710 case RTE_FLOW_ITEM_TYPE_AH:
10711 size = sizeof(struct rte_flow_item_ah);
10714 case RTE_FLOW_ITEM_TYPE_GTP:
10716 size = sizeof(struct rte_gtp_hdr);
10719 if (gtp_psc != i + 1) {
10721 "Error - GTP PSC does not follow GTP\n");
10725 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
10726 /* Only E flag should be set. */
10728 "Error - GTP unsupported flags\n");
10731 struct rte_gtp_hdr_ext_word ext_word = {
10735 /* We have to add GTP header extra word. */
10736 *total_size += sizeof(ext_word);
10737 rte_memcpy(data_tail - (*total_size),
10738 &ext_word, sizeof(ext_word));
10740 size = sizeof(struct rte_gtp_hdr);
10742 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
10743 if (gtp_psc >= 0) {
10745 "Error - Multiple GTP PSC items\n");
10748 const struct rte_flow_item_gtp_psc
10752 uint8_t pdu_type:4;
10756 psc.len = sizeof(psc) / 4;
10757 psc.pdu_type = opt->hdr.type;
10758 psc.qfi = opt->hdr.qfi;
10760 *total_size += sizeof(psc);
10761 rte_memcpy(data_tail - (*total_size),
10762 &psc, sizeof(psc));
10767 case RTE_FLOW_ITEM_TYPE_PFCP:
10768 size = sizeof(struct rte_flow_item_pfcp);
10770 case RTE_FLOW_ITEM_TYPE_FLEX:
10771 size = item->spec ?
10772 ((const struct rte_flow_item_flex *)
10773 item->spec)->length : 0;
10775 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
10778 const struct rte_flow_item_gre_opt
10780 if (opt->checksum_rsvd.checksum) {
10782 sizeof(opt->checksum_rsvd);
10783 rte_memcpy(data_tail - (*total_size),
10784 &opt->checksum_rsvd,
10785 sizeof(opt->checksum_rsvd));
10787 if (opt->key.key) {
10788 *total_size += sizeof(opt->key.key);
10789 rte_memcpy(data_tail - (*total_size),
10791 sizeof(opt->key.key));
10793 if (opt->sequence.sequence) {
10794 *total_size += sizeof(opt->sequence.sequence);
10795 rte_memcpy(data_tail - (*total_size),
10796 &opt->sequence.sequence,
10797 sizeof(opt->sequence.sequence));
10803 fprintf(stderr, "Error - Not supported item\n");
10806 *total_size += size;
10807 rte_memcpy(data_tail - (*total_size), item->spec, size);
10808 /* update some fields which cannot be set by cmdline */
10809 update_fields((data_tail - (*total_size)), item,
10811 upper_layer = proto;
10813 if (verbose_level & 0x1)
10814 printf("total data size is %zu\n", (*total_size));
10815 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
10816 memmove(data, (data_tail - (*total_size)), *total_size);
10821 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
10824 /** Populate help strings for current token (cmdline API). */
10826 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
10829 struct context *ctx = &cmd_flow_context;
10830 const struct token *token = &token_list[ctx->prev];
10835 /* Set token type and update global help with details. */
10836 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
10838 cmd_set_raw.help_str = token->help;
10840 cmd_set_raw.help_str = token->name;
10844 /** Token definition template (cmdline API). */
10845 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
10846 .ops = &(struct cmdline_token_ops){
10847 .parse = cmd_flow_parse,
10848 .complete_get_nb = cmd_flow_complete_get_nb,
10849 .complete_get_elt = cmd_flow_complete_get_elt,
10850 .get_help = cmd_set_raw_get_help,
10855 /** Populate the next dynamic token. */
10857 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
10858 cmdline_parse_token_hdr_t **hdr_inst)
10860 struct context *ctx = &cmd_flow_context;
10862 /* Always reinitialize context before requesting the first token. */
10863 if (!(hdr_inst - cmd_set_raw.tokens)) {
10864 cmd_flow_context_init(ctx);
10865 ctx->curr = START_SET;
10867 /* Return NULL when no more tokens are expected. */
10868 if (!ctx->next_num && (ctx->curr != START_SET)) {
10872 /* Determine if command should end here. */
10873 if (ctx->eol && ctx->last && ctx->next_num) {
10874 const enum index *list = ctx->next[ctx->next_num - 1];
10877 for (i = 0; list[i]; ++i) {
10878 if (list[i] != END)
10884 *hdr = &cmd_set_raw_token_hdr;
10887 /** Token generator and output processing callback (cmdline API). */
10889 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
10892 cmd_set_raw_tok(arg0, arg2);
10894 cmd_set_raw_parsed(arg0);
10897 /** Global parser instance (cmdline API). */
10898 cmdline_parse_inst_t cmd_set_raw = {
10899 .f = cmd_set_raw_cb,
10900 .data = NULL, /**< Unused. */
10901 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
10904 }, /**< Tokens are returned by cmd_flow_tok(). */
10907 /* *** display raw_encap/raw_decap buf */
10908 struct cmd_show_set_raw_result {
10909 cmdline_fixed_string_t cmd_show;
10910 cmdline_fixed_string_t cmd_what;
10911 cmdline_fixed_string_t cmd_all;
10912 uint16_t cmd_index;
10916 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
10918 struct cmd_show_set_raw_result *res = parsed_result;
10919 uint16_t index = res->cmd_index;
10921 uint8_t *raw_data = NULL;
10922 size_t raw_size = 0;
10923 char title[16] = {0};
10926 RTE_SET_USED(data);
10927 if (!strcmp(res->cmd_all, "all")) {
10930 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
10931 fprintf(stderr, "index should be 0-%u\n",
10932 RAW_ENCAP_CONFS_MAX_NUM - 1);
10936 if (!strcmp(res->cmd_what, "raw_encap")) {
10937 raw_data = (uint8_t *)&raw_encap_confs[index].data;
10938 raw_size = raw_encap_confs[index].size;
10939 snprintf(title, 16, "\nindex: %u", index);
10940 rte_hexdump(stdout, title, raw_data, raw_size);
10942 raw_data = (uint8_t *)&raw_decap_confs[index].data;
10943 raw_size = raw_decap_confs[index].size;
10944 snprintf(title, 16, "\nindex: %u", index);
10945 rte_hexdump(stdout, title, raw_data, raw_size);
10947 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
10950 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
10951 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
10953 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
10954 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
10955 cmd_what, "raw_encap#raw_decap");
10956 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
10957 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
10958 cmd_index, RTE_UINT16);
10959 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
10960 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
10962 cmdline_parse_inst_t cmd_show_set_raw = {
10963 .f = cmd_show_set_raw_parsed,
10965 .help_str = "show <raw_encap|raw_decap> <index>",
10967 (void *)&cmd_show_set_raw_cmd_show,
10968 (void *)&cmd_show_set_raw_cmd_what,
10969 (void *)&cmd_show_set_raw_cmd_index,
10973 cmdline_parse_inst_t cmd_show_set_raw_all = {
10974 .f = cmd_show_set_raw_parsed,
10976 .help_str = "show <raw_encap|raw_decap> all",
10978 (void *)&cmd_show_set_raw_cmd_show,
10979 (void *)&cmd_show_set_raw_cmd_what,
10980 (void *)&cmd_show_set_raw_cmd_all,