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. */
104 /* Pattern template arguments. */
105 PATTERN_TEMPLATE_CREATE,
106 PATTERN_TEMPLATE_DESTROY,
107 PATTERN_TEMPLATE_CREATE_ID,
108 PATTERN_TEMPLATE_DESTROY_ID,
109 PATTERN_TEMPLATE_RELAXED_MATCHING,
110 PATTERN_TEMPLATE_INGRESS,
111 PATTERN_TEMPLATE_EGRESS,
112 PATTERN_TEMPLATE_TRANSFER,
113 PATTERN_TEMPLATE_SPEC,
115 /* Actions template arguments. */
116 ACTIONS_TEMPLATE_CREATE,
117 ACTIONS_TEMPLATE_DESTROY,
118 ACTIONS_TEMPLATE_CREATE_ID,
119 ACTIONS_TEMPLATE_DESTROY_ID,
120 ACTIONS_TEMPLATE_INGRESS,
121 ACTIONS_TEMPLATE_EGRESS,
122 ACTIONS_TEMPLATE_TRANSFER,
123 ACTIONS_TEMPLATE_SPEC,
124 ACTIONS_TEMPLATE_MASK,
126 /* Queue arguments. */
130 /* Queue create arguments. */
132 QUEUE_CREATE_POSTPONE,
133 QUEUE_TEMPLATE_TABLE,
134 QUEUE_PATTERN_TEMPLATE,
135 QUEUE_ACTIONS_TEMPLATE,
138 /* Queue destroy arguments. */
140 QUEUE_DESTROY_POSTPONE,
142 /* Push arguments. */
145 /* Table arguments. */
156 TABLE_PATTERN_TEMPLATE,
157 TABLE_ACTIONS_TEMPLATE,
159 /* Tunnel arguments. */
166 /* Destroy arguments. */
169 /* Query arguments. */
172 /* List arguments. */
175 /* Destroy aged flow arguments. */
178 /* Validate/create arguments. */
191 /* Configure arguments */
192 CONFIG_QUEUES_NUMBER,
194 CONFIG_COUNTERS_NUMBER,
195 CONFIG_AGING_OBJECTS_NUMBER,
196 CONFIG_METERS_NUMBER,
198 /* Indirect action arguments */
199 INDIRECT_ACTION_CREATE,
200 INDIRECT_ACTION_UPDATE,
201 INDIRECT_ACTION_DESTROY,
202 INDIRECT_ACTION_QUERY,
204 /* Indirect action create arguments */
205 INDIRECT_ACTION_CREATE_ID,
206 INDIRECT_ACTION_INGRESS,
207 INDIRECT_ACTION_EGRESS,
208 INDIRECT_ACTION_TRANSFER,
209 INDIRECT_ACTION_SPEC,
211 /* Indirect action destroy arguments */
212 INDIRECT_ACTION_DESTROY_ID,
214 /* Validate/create pattern. */
242 ITEM_RAW_PATTERN_HEX,
253 ITEM_VLAN_INNER_TYPE,
254 ITEM_VLAN_HAS_MORE_VLAN,
259 ITEM_IPV4_FRAGMENT_OFFSET,
271 ITEM_IPV6_HAS_FRAG_EXT,
291 ITEM_VXLAN_LAST_RSVD,
293 ITEM_E_TAG_GRP_ECID_B,
302 ITEM_GRE_C_RSVD0_VER,
321 ITEM_ARP_ETH_IPV4_SHA,
322 ITEM_ARP_ETH_IPV4_SPA,
323 ITEM_ARP_ETH_IPV4_THA,
324 ITEM_ARP_ETH_IPV4_TPA,
326 ITEM_IPV6_EXT_NEXT_HDR,
328 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
329 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
330 ITEM_IPV6_FRAG_EXT_ID,
335 ITEM_ICMP6_ND_NS_TARGET_ADDR,
337 ITEM_ICMP6_ND_NA_TARGET_ADDR,
339 ITEM_ICMP6_ND_OPT_TYPE,
340 ITEM_ICMP6_ND_OPT_SLA_ETH,
341 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
342 ITEM_ICMP6_ND_OPT_TLA_ETH,
343 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
349 ITEM_GRE_OPTION_CHECKSUM,
351 ITEM_GRE_OPTION_SEQUENCE,
360 ITEM_HIGIG2_CLASSIFICATION,
366 ITEM_L2TPV3OIP_SESSION_ID,
376 ITEM_ECPRI_COMMON_TYPE,
377 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
378 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
379 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
380 ITEM_ECPRI_MSG_IQ_DATA_PCID,
381 ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
382 ITEM_ECPRI_MSG_DLY_MSR_MSRID,
384 ITEM_GENEVE_OPT_CLASS,
385 ITEM_GENEVE_OPT_TYPE,
386 ITEM_GENEVE_OPT_LENGTH,
387 ITEM_GENEVE_OPT_DATA,
389 ITEM_INTEGRITY_LEVEL,
390 ITEM_INTEGRITY_VALUE,
395 ITEM_PORT_REPRESENTOR,
396 ITEM_PORT_REPRESENTOR_PORT_ID,
397 ITEM_REPRESENTED_PORT,
398 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
400 ITEM_FLEX_ITEM_HANDLE,
401 ITEM_FLEX_PATTERN_HANDLE,
404 ITEM_L2TPV2_TYPE_DATA,
405 ITEM_L2TPV2_TYPE_DATA_L,
406 ITEM_L2TPV2_TYPE_DATA_S,
407 ITEM_L2TPV2_TYPE_DATA_O,
408 ITEM_L2TPV2_TYPE_DATA_L_S,
409 ITEM_L2TPV2_TYPE_CTRL,
410 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
411 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
412 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
413 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
414 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
415 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
416 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
417 ITEM_L2TPV2_MSG_DATA_S_NS,
418 ITEM_L2TPV2_MSG_DATA_S_NR,
419 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
420 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
421 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
422 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
423 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
424 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
425 ITEM_L2TPV2_MSG_DATA_L_S_NS,
426 ITEM_L2TPV2_MSG_DATA_L_S_NR,
427 ITEM_L2TPV2_MSG_CTRL_LENGTH,
428 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
429 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
430 ITEM_L2TPV2_MSG_CTRL_NS,
431 ITEM_L2TPV2_MSG_CTRL_NR,
437 /* Validate/create actions. */
456 ACTION_RSS_FUNC_DEFAULT,
457 ACTION_RSS_FUNC_TOEPLITZ,
458 ACTION_RSS_FUNC_SIMPLE_XOR,
459 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
471 ACTION_PHY_PORT_ORIGINAL,
472 ACTION_PHY_PORT_INDEX,
474 ACTION_PORT_ID_ORIGINAL,
478 ACTION_METER_COLOR_TYPE,
479 ACTION_METER_COLOR_GREEN,
480 ACTION_METER_COLOR_YELLOW,
481 ACTION_METER_COLOR_RED,
483 ACTION_OF_SET_MPLS_TTL,
484 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
485 ACTION_OF_DEC_MPLS_TTL,
486 ACTION_OF_SET_NW_TTL,
487 ACTION_OF_SET_NW_TTL_NW_TTL,
488 ACTION_OF_DEC_NW_TTL,
489 ACTION_OF_COPY_TTL_OUT,
490 ACTION_OF_COPY_TTL_IN,
493 ACTION_OF_PUSH_VLAN_ETHERTYPE,
494 ACTION_OF_SET_VLAN_VID,
495 ACTION_OF_SET_VLAN_VID_VLAN_VID,
496 ACTION_OF_SET_VLAN_PCP,
497 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
499 ACTION_OF_POP_MPLS_ETHERTYPE,
501 ACTION_OF_PUSH_MPLS_ETHERTYPE,
508 ACTION_MPLSOGRE_ENCAP,
509 ACTION_MPLSOGRE_DECAP,
510 ACTION_MPLSOUDP_ENCAP,
511 ACTION_MPLSOUDP_DECAP,
513 ACTION_SET_IPV4_SRC_IPV4_SRC,
515 ACTION_SET_IPV4_DST_IPV4_DST,
517 ACTION_SET_IPV6_SRC_IPV6_SRC,
519 ACTION_SET_IPV6_DST_IPV6_DST,
521 ACTION_SET_TP_SRC_TP_SRC,
523 ACTION_SET_TP_DST_TP_DST,
529 ACTION_SET_MAC_SRC_MAC_SRC,
531 ACTION_SET_MAC_DST_MAC_DST,
533 ACTION_INC_TCP_SEQ_VALUE,
535 ACTION_DEC_TCP_SEQ_VALUE,
537 ACTION_INC_TCP_ACK_VALUE,
539 ACTION_DEC_TCP_ACK_VALUE,
542 ACTION_RAW_ENCAP_INDEX,
543 ACTION_RAW_ENCAP_INDEX_VALUE,
544 ACTION_RAW_DECAP_INDEX,
545 ACTION_RAW_DECAP_INDEX_VALUE,
548 ACTION_SET_TAG_INDEX,
551 ACTION_SET_META_DATA,
552 ACTION_SET_META_MASK,
553 ACTION_SET_IPV4_DSCP,
554 ACTION_SET_IPV4_DSCP_VALUE,
555 ACTION_SET_IPV6_DSCP,
556 ACTION_SET_IPV6_DSCP_VALUE,
562 ACTION_SAMPLE_INDEX_VALUE,
564 INDIRECT_ACTION_ID2PTR,
566 ACTION_MODIFY_FIELD_OP,
567 ACTION_MODIFY_FIELD_OP_VALUE,
568 ACTION_MODIFY_FIELD_DST_TYPE,
569 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
570 ACTION_MODIFY_FIELD_DST_LEVEL,
571 ACTION_MODIFY_FIELD_DST_OFFSET,
572 ACTION_MODIFY_FIELD_SRC_TYPE,
573 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
574 ACTION_MODIFY_FIELD_SRC_LEVEL,
575 ACTION_MODIFY_FIELD_SRC_OFFSET,
576 ACTION_MODIFY_FIELD_SRC_VALUE,
577 ACTION_MODIFY_FIELD_SRC_POINTER,
578 ACTION_MODIFY_FIELD_WIDTH,
580 ACTION_CONNTRACK_UPDATE,
581 ACTION_CONNTRACK_UPDATE_DIR,
582 ACTION_CONNTRACK_UPDATE_CTX,
586 ACTION_PORT_REPRESENTOR,
587 ACTION_PORT_REPRESENTOR_PORT_ID,
588 ACTION_REPRESENTED_PORT,
589 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
592 /** Maximum size for pattern in struct rte_flow_item_raw. */
593 #define ITEM_RAW_PATTERN_SIZE 512
595 /** Maximum size for GENEVE option data pattern in bytes. */
596 #define ITEM_GENEVE_OPT_DATA_SIZE 124
598 /** Storage size for struct rte_flow_item_raw including pattern. */
599 #define ITEM_RAW_SIZE \
600 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
602 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
603 #define ACTION_MODIFY_PATTERN_SIZE 32
605 /** Storage size for struct rte_flow_action_modify_field including pattern. */
606 #define ACTION_MODIFY_SIZE \
607 (sizeof(struct rte_flow_action_modify_field) + \
608 ACTION_MODIFY_PATTERN_SIZE)
610 /** Maximum number of queue indices in struct rte_flow_action_rss. */
611 #define ACTION_RSS_QUEUE_NUM 128
613 /** Storage for struct rte_flow_action_rss including external data. */
614 struct action_rss_data {
615 struct rte_flow_action_rss conf;
616 uint8_t key[RSS_HASH_KEY_LENGTH];
617 uint16_t queue[ACTION_RSS_QUEUE_NUM];
620 /** Maximum data size in struct rte_flow_action_raw_encap. */
621 #define ACTION_RAW_ENCAP_MAX_DATA 512
622 #define RAW_ENCAP_CONFS_MAX_NUM 8
624 /** Storage for struct rte_flow_action_raw_encap. */
625 struct raw_encap_conf {
626 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
627 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
631 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
633 /** Storage for struct rte_flow_action_raw_encap including external data. */
634 struct action_raw_encap_data {
635 struct rte_flow_action_raw_encap conf;
636 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
637 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
641 /** Storage for struct rte_flow_action_raw_decap. */
642 struct raw_decap_conf {
643 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
647 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
649 /** Storage for struct rte_flow_action_raw_decap including external data. */
650 struct action_raw_decap_data {
651 struct rte_flow_action_raw_decap conf;
652 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
656 struct vxlan_encap_conf vxlan_encap_conf = {
660 .vni = "\x00\x00\x00",
662 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
663 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
664 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
665 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
666 "\x00\x00\x00\x00\x00\x00\x00\x01",
667 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
668 "\x00\x00\x00\x00\x00\x00\x11\x11",
672 .eth_src = "\x00\x00\x00\x00\x00\x00",
673 .eth_dst = "\xff\xff\xff\xff\xff\xff",
676 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
677 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
679 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
680 struct action_vxlan_encap_data {
681 struct rte_flow_action_vxlan_encap conf;
682 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
683 struct rte_flow_item_eth item_eth;
684 struct rte_flow_item_vlan item_vlan;
686 struct rte_flow_item_ipv4 item_ipv4;
687 struct rte_flow_item_ipv6 item_ipv6;
689 struct rte_flow_item_udp item_udp;
690 struct rte_flow_item_vxlan item_vxlan;
693 struct nvgre_encap_conf nvgre_encap_conf = {
696 .tni = "\x00\x00\x00",
697 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
698 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
699 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
700 "\x00\x00\x00\x00\x00\x00\x00\x01",
701 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
702 "\x00\x00\x00\x00\x00\x00\x11\x11",
704 .eth_src = "\x00\x00\x00\x00\x00\x00",
705 .eth_dst = "\xff\xff\xff\xff\xff\xff",
708 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
709 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
711 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
712 struct action_nvgre_encap_data {
713 struct rte_flow_action_nvgre_encap conf;
714 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
715 struct rte_flow_item_eth item_eth;
716 struct rte_flow_item_vlan item_vlan;
718 struct rte_flow_item_ipv4 item_ipv4;
719 struct rte_flow_item_ipv6 item_ipv6;
721 struct rte_flow_item_nvgre item_nvgre;
724 struct l2_encap_conf l2_encap_conf;
726 struct l2_decap_conf l2_decap_conf;
728 struct mplsogre_encap_conf mplsogre_encap_conf;
730 struct mplsogre_decap_conf mplsogre_decap_conf;
732 struct mplsoudp_encap_conf mplsoudp_encap_conf;
734 struct mplsoudp_decap_conf mplsoudp_decap_conf;
736 struct rte_flow_action_conntrack conntrack_context;
738 #define ACTION_SAMPLE_ACTIONS_NUM 10
739 #define RAW_SAMPLE_CONFS_MAX_NUM 8
740 /** Storage for struct rte_flow_action_sample including external data. */
741 struct action_sample_data {
742 struct rte_flow_action_sample conf;
745 /** Storage for struct rte_flow_action_sample. */
746 struct raw_sample_conf {
747 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
749 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
750 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
751 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
752 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
753 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
754 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
755 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
756 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
757 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
758 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
760 static const char *const modify_field_ops[] = {
761 "set", "add", "sub", NULL
764 static const char *const modify_field_ids[] = {
765 "start", "mac_dst", "mac_src",
766 "vlan_type", "vlan_id", "mac_type",
767 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
768 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
769 "tcp_port_src", "tcp_port_dst",
770 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
771 "udp_port_src", "udp_port_dst",
772 "vxlan_vni", "geneve_vni", "gtp_teid",
773 "tag", "mark", "meta", "pointer", "value", NULL
776 /** Maximum number of subsequent tokens and arguments on the stack. */
777 #define CTX_STACK_SIZE 16
779 /** Parser context. */
781 /** Stack of subsequent token lists to process. */
782 const enum index *next[CTX_STACK_SIZE];
783 /** Arguments for stacked tokens. */
784 const void *args[CTX_STACK_SIZE];
785 enum index curr; /**< Current token index. */
786 enum index prev; /**< Index of the last token seen. */
787 int next_num; /**< Number of entries in next[]. */
788 int args_num; /**< Number of entries in args[]. */
789 uint32_t eol:1; /**< EOL has been detected. */
790 uint32_t last:1; /**< No more arguments. */
791 portid_t port; /**< Current port ID (for completions). */
792 uint32_t objdata; /**< Object-specific data. */
793 void *object; /**< Address of current object for relative offsets. */
794 void *objmask; /**< Object a full mask must be written to. */
797 /** Token argument. */
799 uint32_t hton:1; /**< Use network byte ordering. */
800 uint32_t sign:1; /**< Value is signed. */
801 uint32_t bounded:1; /**< Value is bounded. */
802 uintmax_t min; /**< Minimum value if bounded. */
803 uintmax_t max; /**< Maximum value if bounded. */
804 uint32_t offset; /**< Relative offset from ctx->object. */
805 uint32_t size; /**< Field size. */
806 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
809 /** Parser token definition. */
811 /** Type displayed during completion (defaults to "TOKEN"). */
813 /** Help displayed during completion (defaults to token name). */
815 /** Private data used by parser functions. */
818 * Lists of subsequent tokens to push on the stack. Each call to the
819 * parser consumes the last entry of that stack.
821 const enum index *const *next;
822 /** Arguments stack for subsequent tokens that need them. */
823 const struct arg *const *args;
825 * Token-processing callback, returns -1 in case of error, the
826 * length of the matched string otherwise. If NULL, attempts to
827 * match the token name.
829 * If buf is not NULL, the result should be stored in it according
830 * to context. An error is returned if not large enough.
832 int (*call)(struct context *ctx, const struct token *token,
833 const char *str, unsigned int len,
834 void *buf, unsigned int size);
836 * Callback that provides possible values for this token, used for
837 * completion. Returns -1 in case of error, the number of possible
838 * values otherwise. If NULL, the token name is used.
840 * If buf is not NULL, entry index ent is written to buf and the
841 * full length of the entry is returned (same behavior as
844 int (*comp)(struct context *ctx, const struct token *token,
845 unsigned int ent, char *buf, unsigned int size);
846 /** Mandatory token name, no default value. */
850 /** Static initializer for the next field. */
851 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
853 /** Static initializer for a NEXT() entry. */
854 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
856 /** Static initializer for the args field. */
857 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
859 /** Static initializer for ARGS() to target a field. */
860 #define ARGS_ENTRY(s, f) \
861 (&(const struct arg){ \
862 .offset = offsetof(s, f), \
863 .size = sizeof(((s *)0)->f), \
866 /** Static initializer for ARGS() to target a bit-field. */
867 #define ARGS_ENTRY_BF(s, f, b) \
868 (&(const struct arg){ \
870 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
873 /** Static initializer for ARGS() to target a field with limits. */
874 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
875 (&(const struct arg){ \
879 .offset = offsetof(s, f), \
880 .size = sizeof(((s *)0)->f), \
883 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
884 #define ARGS_ENTRY_MASK(s, f, m) \
885 (&(const struct arg){ \
886 .offset = offsetof(s, f), \
887 .size = sizeof(((s *)0)->f), \
888 .mask = (const void *)(m), \
891 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
892 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
893 (&(const struct arg){ \
895 .offset = offsetof(s, f), \
896 .size = sizeof(((s *)0)->f), \
897 .mask = (const void *)(m), \
900 /** Static initializer for ARGS() to target a pointer. */
901 #define ARGS_ENTRY_PTR(s, f) \
902 (&(const struct arg){ \
903 .size = sizeof(*((s *)0)->f), \
906 /** Static initializer for ARGS() with arbitrary offset and size. */
907 #define ARGS_ENTRY_ARB(o, s) \
908 (&(const struct arg){ \
913 /** Same as ARGS_ENTRY_ARB() with bounded values. */
914 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
915 (&(const struct arg){ \
923 /** Same as ARGS_ENTRY() using network byte ordering. */
924 #define ARGS_ENTRY_HTON(s, f) \
925 (&(const struct arg){ \
927 .offset = offsetof(s, f), \
928 .size = sizeof(((s *)0)->f), \
931 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
932 #define ARG_ENTRY_HTON(s) \
933 (&(const struct arg){ \
939 /** Parser output buffer layout expected by cmd_flow_parsed(). */
941 enum index command; /**< Flow command. */
942 portid_t port; /**< Affected port ID. */
943 queueid_t queue; /** Async queue ID. */
944 bool postpone; /** Postpone async operation */
947 struct rte_flow_port_attr port_attr;
949 struct rte_flow_queue_attr queue_attr;
950 } configure; /**< Configuration arguments. */
952 uint32_t *template_id;
953 uint32_t template_id_n;
954 } templ_destroy; /**< Template destroy arguments. */
957 struct rte_flow_template_table_attr attr;
958 uint32_t *pat_templ_id;
959 uint32_t pat_templ_id_n;
960 uint32_t *act_templ_id;
961 uint32_t act_templ_id_n;
962 } table; /**< Table arguments. */
966 } table_destroy; /**< Template destroy arguments. */
969 uint32_t action_id_n;
970 } ia_destroy; /**< Indirect action destroy arguments. */
973 } ia; /* Indirect action query arguments */
976 uint32_t pat_templ_id;
977 uint32_t act_templ_id;
978 struct rte_flow_attr attr;
979 struct tunnel_ops tunnel_ops;
980 struct rte_flow_item *pattern;
981 struct rte_flow_action *actions;
982 struct rte_flow_action *masks;
986 } vc; /**< Validate/create arguments. */
990 } destroy; /**< Destroy arguments. */
995 } dump; /**< Dump arguments. */
998 struct rte_flow_action action;
999 } query; /**< Query arguments. */
1003 } list; /**< List arguments. */
1006 } isolate; /**< Isolated mode arguments. */
1009 } aged; /**< Aged arguments. */
1012 } policy;/**< Policy arguments. */
1017 } flex; /**< Flex arguments*/
1018 } args; /**< Command arguments. */
1021 /** Private data for pattern items. */
1022 struct parse_item_priv {
1023 enum rte_flow_item_type type; /**< Item type. */
1024 uint32_t size; /**< Size of item specification structure. */
1027 #define PRIV_ITEM(t, s) \
1028 (&(const struct parse_item_priv){ \
1029 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
1033 /** Private data for actions. */
1034 struct parse_action_priv {
1035 enum rte_flow_action_type type; /**< Action type. */
1036 uint32_t size; /**< Size of action configuration structure. */
1039 #define PRIV_ACTION(t, s) \
1040 (&(const struct parse_action_priv){ \
1041 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
1045 static const enum index next_flex_item[] = {
1052 static const enum index next_config_attr[] = {
1053 CONFIG_QUEUES_NUMBER,
1055 CONFIG_COUNTERS_NUMBER,
1056 CONFIG_AGING_OBJECTS_NUMBER,
1057 CONFIG_METERS_NUMBER,
1062 static const enum index next_pt_subcmd[] = {
1063 PATTERN_TEMPLATE_CREATE,
1064 PATTERN_TEMPLATE_DESTROY,
1068 static const enum index next_pt_attr[] = {
1069 PATTERN_TEMPLATE_CREATE_ID,
1070 PATTERN_TEMPLATE_RELAXED_MATCHING,
1071 PATTERN_TEMPLATE_INGRESS,
1072 PATTERN_TEMPLATE_EGRESS,
1073 PATTERN_TEMPLATE_TRANSFER,
1074 PATTERN_TEMPLATE_SPEC,
1078 static const enum index next_pt_destroy_attr[] = {
1079 PATTERN_TEMPLATE_DESTROY_ID,
1084 static const enum index next_at_subcmd[] = {
1085 ACTIONS_TEMPLATE_CREATE,
1086 ACTIONS_TEMPLATE_DESTROY,
1090 static const enum index next_at_attr[] = {
1091 ACTIONS_TEMPLATE_CREATE_ID,
1092 ACTIONS_TEMPLATE_INGRESS,
1093 ACTIONS_TEMPLATE_EGRESS,
1094 ACTIONS_TEMPLATE_TRANSFER,
1095 ACTIONS_TEMPLATE_SPEC,
1099 static const enum index next_at_destroy_attr[] = {
1100 ACTIONS_TEMPLATE_DESTROY_ID,
1105 static const enum index next_table_subcmd[] = {
1111 static const enum index next_table_attr[] = {
1119 TABLE_PATTERN_TEMPLATE,
1120 TABLE_ACTIONS_TEMPLATE,
1125 static const enum index next_table_destroy_attr[] = {
1131 static const enum index next_queue_subcmd[] = {
1137 static const enum index next_queue_destroy_attr[] = {
1143 static const enum index next_ia_create_attr[] = {
1144 INDIRECT_ACTION_CREATE_ID,
1145 INDIRECT_ACTION_INGRESS,
1146 INDIRECT_ACTION_EGRESS,
1147 INDIRECT_ACTION_TRANSFER,
1148 INDIRECT_ACTION_SPEC,
1152 static const enum index next_dump_subcmd[] = {
1158 static const enum index next_ia_subcmd[] = {
1159 INDIRECT_ACTION_CREATE,
1160 INDIRECT_ACTION_UPDATE,
1161 INDIRECT_ACTION_DESTROY,
1162 INDIRECT_ACTION_QUERY,
1166 static const enum index next_vc_attr[] = {
1178 static const enum index next_destroy_attr[] = {
1184 static const enum index next_dump_attr[] = {
1190 static const enum index next_list_attr[] = {
1196 static const enum index next_aged_attr[] = {
1202 static const enum index next_ia_destroy_attr[] = {
1203 INDIRECT_ACTION_DESTROY_ID,
1208 static const enum index item_param[] = {
1217 static const enum index next_item[] = {
1254 ITEM_ICMP6_ND_OPT_SLA_ETH,
1255 ITEM_ICMP6_ND_OPT_TLA_ETH,
1262 ITEM_PPPOE_PROTO_ID,
1273 ITEM_PORT_REPRESENTOR,
1274 ITEM_REPRESENTED_PORT,
1282 static const enum index item_fuzzy[] = {
1288 static const enum index item_any[] = {
1294 static const enum index item_vf[] = {
1300 static const enum index item_phy_port[] = {
1301 ITEM_PHY_PORT_INDEX,
1306 static const enum index item_port_id[] = {
1312 static const enum index item_mark[] = {
1318 static const enum index item_raw[] = {
1324 ITEM_RAW_PATTERN_HEX,
1329 static const enum index item_eth[] = {
1338 static const enum index item_vlan[] = {
1343 ITEM_VLAN_INNER_TYPE,
1344 ITEM_VLAN_HAS_MORE_VLAN,
1349 static const enum index item_ipv4[] = {
1353 ITEM_IPV4_FRAGMENT_OFFSET,
1362 static const enum index item_ipv6[] = {
1369 ITEM_IPV6_HAS_FRAG_EXT,
1374 static const enum index item_icmp[] = {
1383 static const enum index item_udp[] = {
1390 static const enum index item_tcp[] = {
1398 static const enum index item_sctp[] = {
1407 static const enum index item_vxlan[] = {
1409 ITEM_VXLAN_LAST_RSVD,
1414 static const enum index item_e_tag[] = {
1415 ITEM_E_TAG_GRP_ECID_B,
1420 static const enum index item_nvgre[] = {
1426 static const enum index item_mpls[] = {
1434 static const enum index item_gre[] = {
1436 ITEM_GRE_C_RSVD0_VER,
1444 static const enum index item_gre_key[] = {
1450 static const enum index item_gre_option[] = {
1451 ITEM_GRE_OPTION_CHECKSUM,
1452 ITEM_GRE_OPTION_KEY,
1453 ITEM_GRE_OPTION_SEQUENCE,
1458 static const enum index item_gtp[] = {
1466 static const enum index item_geneve[] = {
1474 static const enum index item_vxlan_gpe[] = {
1480 static const enum index item_arp_eth_ipv4[] = {
1481 ITEM_ARP_ETH_IPV4_SHA,
1482 ITEM_ARP_ETH_IPV4_SPA,
1483 ITEM_ARP_ETH_IPV4_THA,
1484 ITEM_ARP_ETH_IPV4_TPA,
1489 static const enum index item_ipv6_ext[] = {
1490 ITEM_IPV6_EXT_NEXT_HDR,
1495 static const enum index item_ipv6_frag_ext[] = {
1496 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1497 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1498 ITEM_IPV6_FRAG_EXT_ID,
1503 static const enum index item_icmp6[] = {
1510 static const enum index item_icmp6_nd_ns[] = {
1511 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1516 static const enum index item_icmp6_nd_na[] = {
1517 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1522 static const enum index item_icmp6_nd_opt[] = {
1523 ITEM_ICMP6_ND_OPT_TYPE,
1528 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1529 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1534 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1535 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1540 static const enum index item_meta[] = {
1546 static const enum index item_gtp_psc[] = {
1553 static const enum index item_pppoed[] = {
1559 static const enum index item_pppoes[] = {
1565 static const enum index item_pppoe_proto_id[] = {
1570 static const enum index item_higig2[] = {
1571 ITEM_HIGIG2_CLASSIFICATION,
1577 static const enum index item_esp[] = {
1583 static const enum index item_ah[] = {
1589 static const enum index item_pfcp[] = {
1596 static const enum index next_set_raw[] = {
1602 static const enum index item_tag[] = {
1609 static const enum index item_l2tpv3oip[] = {
1610 ITEM_L2TPV3OIP_SESSION_ID,
1615 static const enum index item_ecpri[] = {
1621 static const enum index item_ecpri_common[] = {
1622 ITEM_ECPRI_COMMON_TYPE,
1626 static const enum index item_ecpri_common_type[] = {
1627 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1628 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1629 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1633 static const enum index item_geneve_opt[] = {
1634 ITEM_GENEVE_OPT_CLASS,
1635 ITEM_GENEVE_OPT_TYPE,
1636 ITEM_GENEVE_OPT_LENGTH,
1637 ITEM_GENEVE_OPT_DATA,
1642 static const enum index item_integrity[] = {
1643 ITEM_INTEGRITY_LEVEL,
1644 ITEM_INTEGRITY_VALUE,
1648 static const enum index item_integrity_lv[] = {
1649 ITEM_INTEGRITY_LEVEL,
1650 ITEM_INTEGRITY_VALUE,
1655 static const enum index item_port_representor[] = {
1656 ITEM_PORT_REPRESENTOR_PORT_ID,
1661 static const enum index item_represented_port[] = {
1662 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1667 static const enum index item_flex[] = {
1668 ITEM_FLEX_PATTERN_HANDLE,
1669 ITEM_FLEX_ITEM_HANDLE,
1674 static const enum index item_l2tpv2[] = {
1680 static const enum index item_l2tpv2_type[] = {
1681 ITEM_L2TPV2_TYPE_DATA,
1682 ITEM_L2TPV2_TYPE_DATA_L,
1683 ITEM_L2TPV2_TYPE_DATA_S,
1684 ITEM_L2TPV2_TYPE_DATA_O,
1685 ITEM_L2TPV2_TYPE_DATA_L_S,
1686 ITEM_L2TPV2_TYPE_CTRL,
1690 static const enum index item_l2tpv2_type_data[] = {
1691 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1692 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1697 static const enum index item_l2tpv2_type_data_l[] = {
1698 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1699 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1700 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1705 static const enum index item_l2tpv2_type_data_s[] = {
1706 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1707 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1708 ITEM_L2TPV2_MSG_DATA_S_NS,
1709 ITEM_L2TPV2_MSG_DATA_S_NR,
1714 static const enum index item_l2tpv2_type_data_o[] = {
1715 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1716 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1717 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1722 static const enum index item_l2tpv2_type_data_l_s[] = {
1723 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1724 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1725 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1726 ITEM_L2TPV2_MSG_DATA_L_S_NS,
1727 ITEM_L2TPV2_MSG_DATA_L_S_NR,
1732 static const enum index item_l2tpv2_type_ctrl[] = {
1733 ITEM_L2TPV2_MSG_CTRL_LENGTH,
1734 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1735 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1736 ITEM_L2TPV2_MSG_CTRL_NS,
1737 ITEM_L2TPV2_MSG_CTRL_NR,
1742 static const enum index item_ppp[] = {
1750 static const enum index next_action[] = {
1767 ACTION_OF_SET_MPLS_TTL,
1768 ACTION_OF_DEC_MPLS_TTL,
1769 ACTION_OF_SET_NW_TTL,
1770 ACTION_OF_DEC_NW_TTL,
1771 ACTION_OF_COPY_TTL_OUT,
1772 ACTION_OF_COPY_TTL_IN,
1774 ACTION_OF_PUSH_VLAN,
1775 ACTION_OF_SET_VLAN_VID,
1776 ACTION_OF_SET_VLAN_PCP,
1778 ACTION_OF_PUSH_MPLS,
1785 ACTION_MPLSOGRE_ENCAP,
1786 ACTION_MPLSOGRE_DECAP,
1787 ACTION_MPLSOUDP_ENCAP,
1788 ACTION_MPLSOUDP_DECAP,
1789 ACTION_SET_IPV4_SRC,
1790 ACTION_SET_IPV4_DST,
1791 ACTION_SET_IPV6_SRC,
1792 ACTION_SET_IPV6_DST,
1808 ACTION_SET_IPV4_DSCP,
1809 ACTION_SET_IPV6_DSCP,
1813 ACTION_MODIFY_FIELD,
1815 ACTION_CONNTRACK_UPDATE,
1816 ACTION_PORT_REPRESENTOR,
1817 ACTION_REPRESENTED_PORT,
1821 static const enum index action_mark[] = {
1827 static const enum index action_queue[] = {
1833 static const enum index action_count[] = {
1839 static const enum index action_rss[] = {
1850 static const enum index action_vf[] = {
1857 static const enum index action_phy_port[] = {
1858 ACTION_PHY_PORT_ORIGINAL,
1859 ACTION_PHY_PORT_INDEX,
1864 static const enum index action_port_id[] = {
1865 ACTION_PORT_ID_ORIGINAL,
1871 static const enum index action_meter[] = {
1877 static const enum index action_meter_color[] = {
1878 ACTION_METER_COLOR_TYPE,
1883 static const enum index action_of_set_mpls_ttl[] = {
1884 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1889 static const enum index action_of_set_nw_ttl[] = {
1890 ACTION_OF_SET_NW_TTL_NW_TTL,
1895 static const enum index action_of_push_vlan[] = {
1896 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1901 static const enum index action_of_set_vlan_vid[] = {
1902 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1907 static const enum index action_of_set_vlan_pcp[] = {
1908 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1913 static const enum index action_of_pop_mpls[] = {
1914 ACTION_OF_POP_MPLS_ETHERTYPE,
1919 static const enum index action_of_push_mpls[] = {
1920 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1925 static const enum index action_set_ipv4_src[] = {
1926 ACTION_SET_IPV4_SRC_IPV4_SRC,
1931 static const enum index action_set_mac_src[] = {
1932 ACTION_SET_MAC_SRC_MAC_SRC,
1937 static const enum index action_set_ipv4_dst[] = {
1938 ACTION_SET_IPV4_DST_IPV4_DST,
1943 static const enum index action_set_ipv6_src[] = {
1944 ACTION_SET_IPV6_SRC_IPV6_SRC,
1949 static const enum index action_set_ipv6_dst[] = {
1950 ACTION_SET_IPV6_DST_IPV6_DST,
1955 static const enum index action_set_tp_src[] = {
1956 ACTION_SET_TP_SRC_TP_SRC,
1961 static const enum index action_set_tp_dst[] = {
1962 ACTION_SET_TP_DST_TP_DST,
1967 static const enum index action_set_ttl[] = {
1973 static const enum index action_jump[] = {
1979 static const enum index action_set_mac_dst[] = {
1980 ACTION_SET_MAC_DST_MAC_DST,
1985 static const enum index action_inc_tcp_seq[] = {
1986 ACTION_INC_TCP_SEQ_VALUE,
1991 static const enum index action_dec_tcp_seq[] = {
1992 ACTION_DEC_TCP_SEQ_VALUE,
1997 static const enum index action_inc_tcp_ack[] = {
1998 ACTION_INC_TCP_ACK_VALUE,
2003 static const enum index action_dec_tcp_ack[] = {
2004 ACTION_DEC_TCP_ACK_VALUE,
2009 static const enum index action_raw_encap[] = {
2010 ACTION_RAW_ENCAP_INDEX,
2015 static const enum index action_raw_decap[] = {
2016 ACTION_RAW_DECAP_INDEX,
2021 static const enum index action_set_tag[] = {
2022 ACTION_SET_TAG_DATA,
2023 ACTION_SET_TAG_INDEX,
2024 ACTION_SET_TAG_MASK,
2029 static const enum index action_set_meta[] = {
2030 ACTION_SET_META_DATA,
2031 ACTION_SET_META_MASK,
2036 static const enum index action_set_ipv4_dscp[] = {
2037 ACTION_SET_IPV4_DSCP_VALUE,
2042 static const enum index action_set_ipv6_dscp[] = {
2043 ACTION_SET_IPV6_DSCP_VALUE,
2048 static const enum index action_age[] = {
2055 static const enum index action_sample[] = {
2057 ACTION_SAMPLE_RATIO,
2058 ACTION_SAMPLE_INDEX,
2063 static const enum index next_action_sample[] = {
2076 static const enum index action_modify_field_dst[] = {
2077 ACTION_MODIFY_FIELD_DST_LEVEL,
2078 ACTION_MODIFY_FIELD_DST_OFFSET,
2079 ACTION_MODIFY_FIELD_SRC_TYPE,
2083 static const enum index action_modify_field_src[] = {
2084 ACTION_MODIFY_FIELD_SRC_LEVEL,
2085 ACTION_MODIFY_FIELD_SRC_OFFSET,
2086 ACTION_MODIFY_FIELD_SRC_VALUE,
2087 ACTION_MODIFY_FIELD_SRC_POINTER,
2088 ACTION_MODIFY_FIELD_WIDTH,
2092 static const enum index action_update_conntrack[] = {
2093 ACTION_CONNTRACK_UPDATE_DIR,
2094 ACTION_CONNTRACK_UPDATE_CTX,
2099 static const enum index action_port_representor[] = {
2100 ACTION_PORT_REPRESENTOR_PORT_ID,
2105 static const enum index action_represented_port[] = {
2106 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2111 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2112 const char *, unsigned int,
2113 void *, unsigned int);
2114 static int parse_set_sample_action(struct context *, const struct token *,
2115 const char *, unsigned int,
2116 void *, unsigned int);
2117 static int parse_set_init(struct context *, const struct token *,
2118 const char *, unsigned int,
2119 void *, unsigned int);
2121 parse_flex_handle(struct context *, const struct token *,
2122 const char *, unsigned int, void *, unsigned int);
2123 static int parse_init(struct context *, const struct token *,
2124 const char *, unsigned int,
2125 void *, unsigned int);
2126 static int parse_vc(struct context *, const struct token *,
2127 const char *, unsigned int,
2128 void *, unsigned int);
2129 static int parse_vc_spec(struct context *, const struct token *,
2130 const char *, unsigned int, void *, unsigned int);
2131 static int parse_vc_conf(struct context *, const struct token *,
2132 const char *, unsigned int, void *, unsigned int);
2133 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2134 const char *, unsigned int,
2135 void *, unsigned int);
2136 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2137 const char *, unsigned int,
2138 void *, unsigned int);
2139 static int parse_vc_action_meter_color_type(struct context *,
2140 const struct token *,
2141 const char *, unsigned int, void *,
2143 static int parse_vc_action_rss(struct context *, const struct token *,
2144 const char *, unsigned int, void *,
2146 static int parse_vc_action_rss_func(struct context *, const struct token *,
2147 const char *, unsigned int, void *,
2149 static int parse_vc_action_rss_type(struct context *, const struct token *,
2150 const char *, unsigned int, void *,
2152 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2153 const char *, unsigned int, void *,
2155 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2156 const char *, unsigned int, void *,
2158 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2159 const char *, unsigned int, void *,
2161 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2162 const char *, unsigned int, void *,
2164 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2165 const char *, unsigned int, void *,
2167 static int parse_vc_action_mplsogre_encap(struct context *,
2168 const struct token *, const char *,
2169 unsigned int, void *, unsigned int);
2170 static int parse_vc_action_mplsogre_decap(struct context *,
2171 const struct token *, const char *,
2172 unsigned int, void *, unsigned int);
2173 static int parse_vc_action_mplsoudp_encap(struct context *,
2174 const struct token *, const char *,
2175 unsigned int, void *, unsigned int);
2176 static int parse_vc_action_mplsoudp_decap(struct context *,
2177 const struct token *, const char *,
2178 unsigned int, void *, unsigned int);
2179 static int parse_vc_action_raw_encap(struct context *,
2180 const struct token *, const char *,
2181 unsigned int, void *, unsigned int);
2182 static int parse_vc_action_raw_decap(struct context *,
2183 const struct token *, const char *,
2184 unsigned int, void *, unsigned int);
2185 static int parse_vc_action_raw_encap_index(struct context *,
2186 const struct token *, const char *,
2187 unsigned int, void *, unsigned int);
2188 static int parse_vc_action_raw_decap_index(struct context *,
2189 const struct token *, const char *,
2190 unsigned int, void *, unsigned int);
2191 static int parse_vc_action_set_meta(struct context *ctx,
2192 const struct token *token, const char *str,
2193 unsigned int len, void *buf,
2195 static int parse_vc_action_sample(struct context *ctx,
2196 const struct token *token, const char *str,
2197 unsigned int len, void *buf,
2200 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2201 const char *str, unsigned int len, void *buf,
2204 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2205 const char *str, unsigned int len, void *buf,
2208 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2209 const char *str, unsigned int len, void *buf,
2212 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2213 const char *str, unsigned int len, void *buf,
2215 static int parse_destroy(struct context *, const struct token *,
2216 const char *, unsigned int,
2217 void *, unsigned int);
2218 static int parse_flush(struct context *, const struct token *,
2219 const char *, unsigned int,
2220 void *, unsigned int);
2221 static int parse_dump(struct context *, const struct token *,
2222 const char *, unsigned int,
2223 void *, unsigned int);
2224 static int parse_query(struct context *, const struct token *,
2225 const char *, unsigned int,
2226 void *, unsigned int);
2227 static int parse_action(struct context *, const struct token *,
2228 const char *, unsigned int,
2229 void *, unsigned int);
2230 static int parse_list(struct context *, const struct token *,
2231 const char *, unsigned int,
2232 void *, unsigned int);
2233 static int parse_aged(struct context *, const struct token *,
2234 const char *, unsigned int,
2235 void *, unsigned int);
2236 static int parse_isolate(struct context *, const struct token *,
2237 const char *, unsigned int,
2238 void *, unsigned int);
2239 static int parse_configure(struct context *, const struct token *,
2240 const char *, unsigned int,
2241 void *, unsigned int);
2242 static int parse_template(struct context *, const struct token *,
2243 const char *, unsigned int,
2244 void *, unsigned int);
2245 static int parse_template_destroy(struct context *, const struct token *,
2246 const char *, unsigned int,
2247 void *, unsigned int);
2248 static int parse_table(struct context *, const struct token *,
2249 const char *, unsigned int, void *, unsigned int);
2250 static int parse_table_destroy(struct context *, const struct token *,
2251 const char *, unsigned int,
2252 void *, unsigned int);
2253 static int parse_qo(struct context *, const struct token *,
2254 const char *, unsigned int,
2255 void *, unsigned int);
2256 static int parse_qo_destroy(struct context *, const struct token *,
2257 const char *, unsigned int,
2258 void *, unsigned int);
2259 static int parse_push(struct context *, const struct token *,
2260 const char *, unsigned int,
2261 void *, unsigned int);
2262 static int parse_tunnel(struct context *, const struct token *,
2263 const char *, unsigned int,
2264 void *, unsigned int);
2265 static int parse_flex(struct context *, const struct token *,
2266 const char *, unsigned int, void *, unsigned int);
2267 static int parse_int(struct context *, const struct token *,
2268 const char *, unsigned int,
2269 void *, unsigned int);
2270 static int parse_prefix(struct context *, const struct token *,
2271 const char *, unsigned int,
2272 void *, unsigned int);
2273 static int parse_boolean(struct context *, const struct token *,
2274 const char *, unsigned int,
2275 void *, unsigned int);
2276 static int parse_string(struct context *, const struct token *,
2277 const char *, unsigned int,
2278 void *, unsigned int);
2279 static int parse_hex(struct context *ctx, const struct token *token,
2280 const char *str, unsigned int len,
2281 void *buf, unsigned int size);
2282 static int parse_string0(struct context *, const struct token *,
2283 const char *, unsigned int,
2284 void *, unsigned int);
2285 static int parse_mac_addr(struct context *, const struct token *,
2286 const char *, unsigned int,
2287 void *, unsigned int);
2288 static int parse_ipv4_addr(struct context *, const struct token *,
2289 const char *, unsigned int,
2290 void *, unsigned int);
2291 static int parse_ipv6_addr(struct context *, const struct token *,
2292 const char *, unsigned int,
2293 void *, unsigned int);
2294 static int parse_port(struct context *, const struct token *,
2295 const char *, unsigned int,
2296 void *, unsigned int);
2297 static int parse_ia(struct context *, const struct token *,
2298 const char *, unsigned int,
2299 void *, unsigned int);
2300 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2301 const char *str, unsigned int len,
2302 void *buf, unsigned int size);
2303 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2304 const char *str, unsigned int len, void *buf,
2306 static int parse_mp(struct context *, const struct token *,
2307 const char *, unsigned int,
2308 void *, unsigned int);
2309 static int comp_none(struct context *, const struct token *,
2310 unsigned int, char *, unsigned int);
2311 static int comp_boolean(struct context *, const struct token *,
2312 unsigned int, char *, unsigned int);
2313 static int comp_action(struct context *, const struct token *,
2314 unsigned int, char *, unsigned int);
2315 static int comp_port(struct context *, const struct token *,
2316 unsigned int, char *, unsigned int);
2317 static int comp_rule_id(struct context *, const struct token *,
2318 unsigned int, char *, unsigned int);
2319 static int comp_vc_action_rss_type(struct context *, const struct token *,
2320 unsigned int, char *, unsigned int);
2321 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2322 unsigned int, char *, unsigned int);
2323 static int comp_set_raw_index(struct context *, const struct token *,
2324 unsigned int, char *, unsigned int);
2325 static int comp_set_sample_index(struct context *, const struct token *,
2326 unsigned int, char *, unsigned int);
2327 static int comp_set_modify_field_op(struct context *, const struct token *,
2328 unsigned int, char *, unsigned int);
2329 static int comp_set_modify_field_id(struct context *, const struct token *,
2330 unsigned int, char *, unsigned int);
2331 static int comp_pattern_template_id(struct context *, const struct token *,
2332 unsigned int, char *, unsigned int);
2333 static int comp_actions_template_id(struct context *, const struct token *,
2334 unsigned int, char *, unsigned int);
2335 static int comp_table_id(struct context *, const struct token *,
2336 unsigned int, char *, unsigned int);
2337 static int comp_queue_id(struct context *, const struct token *,
2338 unsigned int, char *, unsigned int);
2340 /** Token definitions. */
2341 static const struct token token_list[] = {
2342 /* Special tokens. */
2345 .help = "null entry, abused as the entry point",
2346 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2351 .help = "command may end here",
2354 .name = "START_SET",
2355 .help = "null entry, abused as the entry point for set",
2356 .next = NEXT(NEXT_ENTRY(SET)),
2361 .help = "set command may end here",
2363 /* Common tokens. */
2364 [COMMON_INTEGER] = {
2367 .help = "integer value",
2371 [COMMON_UNSIGNED] = {
2372 .name = "{unsigned}",
2374 .help = "unsigned integer value",
2381 .help = "prefix length for bit-mask",
2382 .call = parse_prefix,
2385 [COMMON_BOOLEAN] = {
2386 .name = "{boolean}",
2388 .help = "any boolean value",
2389 .call = parse_boolean,
2390 .comp = comp_boolean,
2395 .help = "fixed string",
2396 .call = parse_string,
2402 .help = "fixed string",
2405 [COMMON_FILE_PATH] = {
2406 .name = "{file path}",
2408 .help = "file path",
2409 .call = parse_string0,
2412 [COMMON_MAC_ADDR] = {
2413 .name = "{MAC address}",
2415 .help = "standard MAC address notation",
2416 .call = parse_mac_addr,
2419 [COMMON_IPV4_ADDR] = {
2420 .name = "{IPv4 address}",
2421 .type = "IPV4 ADDRESS",
2422 .help = "standard IPv4 address notation",
2423 .call = parse_ipv4_addr,
2426 [COMMON_IPV6_ADDR] = {
2427 .name = "{IPv6 address}",
2428 .type = "IPV6 ADDRESS",
2429 .help = "standard IPv6 address notation",
2430 .call = parse_ipv6_addr,
2433 [COMMON_RULE_ID] = {
2434 .name = "{rule id}",
2436 .help = "rule identifier",
2438 .comp = comp_rule_id,
2440 [COMMON_PORT_ID] = {
2441 .name = "{port_id}",
2443 .help = "port identifier",
2447 [COMMON_GROUP_ID] = {
2448 .name = "{group_id}",
2450 .help = "group identifier",
2454 [COMMON_PRIORITY_LEVEL] = {
2457 .help = "priority level",
2461 [COMMON_INDIRECT_ACTION_ID] = {
2462 .name = "{indirect_action_id}",
2463 .type = "INDIRECT_ACTION_ID",
2464 .help = "indirect action id",
2468 [COMMON_POLICY_ID] = {
2469 .name = "{policy_id}",
2470 .type = "POLICY_ID",
2471 .help = "policy id",
2475 [COMMON_FLEX_TOKEN] = {
2476 .name = "{flex token}",
2477 .type = "flex token",
2478 .help = "flex token",
2482 [COMMON_FLEX_HANDLE] = {
2483 .name = "{flex handle}",
2484 .type = "FLEX HANDLE",
2485 .help = "fill flex item data",
2486 .call = parse_flex_handle,
2489 [COMMON_PATTERN_TEMPLATE_ID] = {
2490 .name = "{pattern_template_id}",
2491 .type = "PATTERN_TEMPLATE_ID",
2492 .help = "pattern template id",
2494 .comp = comp_pattern_template_id,
2496 [COMMON_ACTIONS_TEMPLATE_ID] = {
2497 .name = "{actions_template_id}",
2498 .type = "ACTIONS_TEMPLATE_ID",
2499 .help = "actions template id",
2501 .comp = comp_actions_template_id,
2503 [COMMON_TABLE_ID] = {
2504 .name = "{table_id}",
2508 .comp = comp_table_id,
2510 [COMMON_QUEUE_ID] = {
2511 .name = "{queue_id}",
2515 .comp = comp_queue_id,
2517 /* Top-level command. */
2520 .type = "{command} {port_id} [{arg} [...]]",
2521 .help = "manage ingress/egress flow rules",
2522 .next = NEXT(NEXT_ENTRY
2544 /* Top-level command. */
2547 .help = "get information about flow engine",
2548 .next = NEXT(NEXT_ENTRY(END),
2549 NEXT_ENTRY(COMMON_PORT_ID)),
2550 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2551 .call = parse_configure,
2553 /* Top-level command. */
2555 .name = "configure",
2556 .help = "configure flow engine",
2557 .next = NEXT(next_config_attr,
2558 NEXT_ENTRY(COMMON_PORT_ID)),
2559 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2560 .call = parse_configure,
2562 /* Configure arguments. */
2563 [CONFIG_QUEUES_NUMBER] = {
2564 .name = "queues_number",
2565 .help = "number of queues",
2566 .next = NEXT(next_config_attr,
2567 NEXT_ENTRY(COMMON_UNSIGNED)),
2568 .args = ARGS(ARGS_ENTRY(struct buffer,
2569 args.configure.nb_queue)),
2571 [CONFIG_QUEUES_SIZE] = {
2572 .name = "queues_size",
2573 .help = "number of elements in queues",
2574 .next = NEXT(next_config_attr,
2575 NEXT_ENTRY(COMMON_UNSIGNED)),
2576 .args = ARGS(ARGS_ENTRY(struct buffer,
2577 args.configure.queue_attr.size)),
2579 [CONFIG_COUNTERS_NUMBER] = {
2580 .name = "counters_number",
2581 .help = "number of counters",
2582 .next = NEXT(next_config_attr,
2583 NEXT_ENTRY(COMMON_UNSIGNED)),
2584 .args = ARGS(ARGS_ENTRY(struct buffer,
2585 args.configure.port_attr.nb_counters)),
2587 [CONFIG_AGING_OBJECTS_NUMBER] = {
2588 .name = "aging_counters_number",
2589 .help = "number of aging objects",
2590 .next = NEXT(next_config_attr,
2591 NEXT_ENTRY(COMMON_UNSIGNED)),
2592 .args = ARGS(ARGS_ENTRY(struct buffer,
2593 args.configure.port_attr.nb_aging_objects)),
2595 [CONFIG_METERS_NUMBER] = {
2596 .name = "meters_number",
2597 .help = "number of meters",
2598 .next = NEXT(next_config_attr,
2599 NEXT_ENTRY(COMMON_UNSIGNED)),
2600 .args = ARGS(ARGS_ENTRY(struct buffer,
2601 args.configure.port_attr.nb_meters)),
2603 /* Top-level command. */
2604 [PATTERN_TEMPLATE] = {
2605 .name = "pattern_template",
2606 .type = "{command} {port_id} [{arg} [...]]",
2607 .help = "manage pattern templates",
2608 .next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2609 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2610 .call = parse_template,
2612 /* Sub-level commands. */
2613 [PATTERN_TEMPLATE_CREATE] = {
2615 .help = "create pattern template",
2616 .next = NEXT(next_pt_attr),
2617 .call = parse_template,
2619 [PATTERN_TEMPLATE_DESTROY] = {
2621 .help = "destroy pattern template",
2622 .next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
2623 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2624 .call = parse_template_destroy,
2626 /* Pattern template arguments. */
2627 [PATTERN_TEMPLATE_CREATE_ID] = {
2628 .name = "pattern_template_id",
2629 .help = "specify a pattern template id to create",
2630 .next = NEXT(next_pt_attr,
2631 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2632 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
2634 [PATTERN_TEMPLATE_DESTROY_ID] = {
2635 .name = "pattern_template",
2636 .help = "specify a pattern template id to destroy",
2637 .next = NEXT(next_pt_destroy_attr,
2638 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2639 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2640 args.templ_destroy.template_id)),
2641 .call = parse_template_destroy,
2643 [PATTERN_TEMPLATE_RELAXED_MATCHING] = {
2645 .help = "is matching relaxed",
2646 .next = NEXT(next_pt_attr,
2647 NEXT_ENTRY(COMMON_BOOLEAN)),
2648 .args = ARGS(ARGS_ENTRY_BF(struct buffer,
2649 args.vc.attr.reserved, 1)),
2651 [PATTERN_TEMPLATE_INGRESS] = {
2653 .help = "attribute pattern to ingress",
2654 .next = NEXT(next_pt_attr),
2655 .call = parse_template,
2657 [PATTERN_TEMPLATE_EGRESS] = {
2659 .help = "attribute pattern to egress",
2660 .next = NEXT(next_pt_attr),
2661 .call = parse_template,
2663 [PATTERN_TEMPLATE_TRANSFER] = {
2665 .help = "attribute pattern to transfer",
2666 .next = NEXT(next_pt_attr),
2667 .call = parse_template,
2669 [PATTERN_TEMPLATE_SPEC] = {
2671 .help = "specify item to create pattern template",
2672 .next = NEXT(next_item),
2674 /* Top-level command. */
2675 [ACTIONS_TEMPLATE] = {
2676 .name = "actions_template",
2677 .type = "{command} {port_id} [{arg} [...]]",
2678 .help = "manage actions templates",
2679 .next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2680 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2681 .call = parse_template,
2683 /* Sub-level commands. */
2684 [ACTIONS_TEMPLATE_CREATE] = {
2686 .help = "create actions template",
2687 .next = NEXT(next_at_attr),
2688 .call = parse_template,
2690 [ACTIONS_TEMPLATE_DESTROY] = {
2692 .help = "destroy actions template",
2693 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
2694 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2695 .call = parse_template_destroy,
2697 /* Actions template arguments. */
2698 [ACTIONS_TEMPLATE_CREATE_ID] = {
2699 .name = "actions_template_id",
2700 .help = "specify an actions template id to create",
2701 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
2702 NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
2703 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2704 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
2706 [ACTIONS_TEMPLATE_DESTROY_ID] = {
2707 .name = "actions_template",
2708 .help = "specify an actions template id to destroy",
2709 .next = NEXT(next_at_destroy_attr,
2710 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2711 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2712 args.templ_destroy.template_id)),
2713 .call = parse_template_destroy,
2715 [ACTIONS_TEMPLATE_INGRESS] = {
2717 .help = "attribute actions to ingress",
2718 .next = NEXT(next_at_attr),
2719 .call = parse_template,
2721 [ACTIONS_TEMPLATE_EGRESS] = {
2723 .help = "attribute actions to egress",
2724 .next = NEXT(next_at_attr),
2725 .call = parse_template,
2727 [ACTIONS_TEMPLATE_TRANSFER] = {
2729 .help = "attribute actions to transfer",
2730 .next = NEXT(next_at_attr),
2731 .call = parse_template,
2733 [ACTIONS_TEMPLATE_SPEC] = {
2735 .help = "specify action to create actions template",
2736 .next = NEXT(next_action),
2737 .call = parse_template,
2739 [ACTIONS_TEMPLATE_MASK] = {
2741 .help = "specify action mask to create actions template",
2742 .next = NEXT(next_action),
2743 .call = parse_template,
2745 /* Top-level command. */
2747 .name = "template_table",
2748 .type = "{command} {port_id} [{arg} [...]]",
2749 .help = "manage template tables",
2750 .next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2751 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2752 .call = parse_table,
2754 /* Sub-level commands. */
2757 .help = "create template table",
2758 .next = NEXT(next_table_attr),
2759 .call = parse_table,
2763 .help = "destroy template table",
2764 .next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
2765 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2766 .call = parse_table_destroy,
2768 /* Table arguments. */
2769 [TABLE_CREATE_ID] = {
2771 .help = "specify table id to create",
2772 .next = NEXT(next_table_attr,
2773 NEXT_ENTRY(COMMON_TABLE_ID)),
2774 .args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
2776 [TABLE_DESTROY_ID] = {
2778 .help = "specify table id to destroy",
2779 .next = NEXT(next_table_destroy_attr,
2780 NEXT_ENTRY(COMMON_TABLE_ID)),
2781 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2782 args.table_destroy.table_id)),
2783 .call = parse_table_destroy,
2787 .help = "specify a group",
2788 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2789 .args = ARGS(ARGS_ENTRY(struct buffer,
2790 args.table.attr.flow_attr.group)),
2792 [TABLE_PRIORITY] = {
2794 .help = "specify a priority level",
2795 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2796 .args = ARGS(ARGS_ENTRY(struct buffer,
2797 args.table.attr.flow_attr.priority)),
2801 .help = "affect rule to egress",
2802 .next = NEXT(next_table_attr),
2803 .call = parse_table,
2807 .help = "affect rule to ingress",
2808 .next = NEXT(next_table_attr),
2809 .call = parse_table,
2811 [TABLE_TRANSFER] = {
2813 .help = "affect rule to transfer",
2814 .next = NEXT(next_table_attr),
2815 .call = parse_table,
2817 [TABLE_RULES_NUMBER] = {
2818 .name = "rules_number",
2819 .help = "number of rules in table",
2820 .next = NEXT(next_table_attr,
2821 NEXT_ENTRY(COMMON_UNSIGNED)),
2822 .args = ARGS(ARGS_ENTRY(struct buffer,
2823 args.table.attr.nb_flows)),
2825 [TABLE_PATTERN_TEMPLATE] = {
2826 .name = "pattern_template",
2827 .help = "specify pattern template id",
2828 .next = NEXT(next_table_attr,
2829 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2830 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2831 args.table.pat_templ_id)),
2832 .call = parse_table,
2834 [TABLE_ACTIONS_TEMPLATE] = {
2835 .name = "actions_template",
2836 .help = "specify actions template id",
2837 .next = NEXT(next_table_attr,
2838 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2839 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2840 args.table.act_templ_id)),
2841 .call = parse_table,
2843 /* Top-level command. */
2846 .help = "queue a flow rule operation",
2847 .next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2848 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2851 /* Sub-level commands. */
2854 .help = "create a flow rule",
2855 .next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
2856 NEXT_ENTRY(COMMON_QUEUE_ID)),
2857 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2862 .help = "destroy a flow rule",
2863 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
2864 NEXT_ENTRY(COMMON_QUEUE_ID)),
2865 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2866 .call = parse_qo_destroy,
2868 /* Queue arguments. */
2869 [QUEUE_TEMPLATE_TABLE] = {
2870 .name = "template table",
2871 .help = "specify table id",
2872 .next = NEXT(NEXT_ENTRY(QUEUE_PATTERN_TEMPLATE),
2873 NEXT_ENTRY(COMMON_TABLE_ID)),
2874 .args = ARGS(ARGS_ENTRY(struct buffer,
2878 [QUEUE_PATTERN_TEMPLATE] = {
2879 .name = "pattern_template",
2880 .help = "specify pattern template index",
2881 .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
2882 NEXT_ENTRY(COMMON_UNSIGNED)),
2883 .args = ARGS(ARGS_ENTRY(struct buffer,
2884 args.vc.pat_templ_id)),
2887 [QUEUE_ACTIONS_TEMPLATE] = {
2888 .name = "actions_template",
2889 .help = "specify actions template index",
2890 .next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
2891 NEXT_ENTRY(COMMON_UNSIGNED)),
2892 .args = ARGS(ARGS_ENTRY(struct buffer,
2893 args.vc.act_templ_id)),
2896 [QUEUE_CREATE_POSTPONE] = {
2898 .help = "postpone create operation",
2899 .next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
2900 NEXT_ENTRY(COMMON_BOOLEAN)),
2901 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
2904 [QUEUE_DESTROY_POSTPONE] = {
2906 .help = "postpone destroy operation",
2907 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
2908 NEXT_ENTRY(COMMON_BOOLEAN)),
2909 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
2910 .call = parse_qo_destroy,
2912 [QUEUE_DESTROY_ID] = {
2914 .help = "specify rule id to destroy",
2915 .next = NEXT(next_queue_destroy_attr,
2916 NEXT_ENTRY(COMMON_UNSIGNED)),
2917 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2918 args.destroy.rule)),
2919 .call = parse_qo_destroy,
2921 /* Top-level command. */
2924 .help = "push enqueued operations",
2925 .next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
2926 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2929 /* Sub-level commands. */
2932 .help = "specify queue id",
2933 .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
2934 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2936 /* Top-level command. */
2937 [INDIRECT_ACTION] = {
2938 .name = "indirect_action",
2939 .type = "{command} {port_id} [{arg} [...]]",
2940 .help = "manage indirect actions",
2941 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2942 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2945 /* Sub-level commands. */
2946 [INDIRECT_ACTION_CREATE] = {
2948 .help = "create indirect action",
2949 .next = NEXT(next_ia_create_attr),
2952 [INDIRECT_ACTION_UPDATE] = {
2954 .help = "update indirect action",
2955 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2956 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2957 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2960 [INDIRECT_ACTION_DESTROY] = {
2962 .help = "destroy indirect action",
2963 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2964 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2965 .call = parse_ia_destroy,
2967 [INDIRECT_ACTION_QUERY] = {
2969 .help = "query indirect action",
2970 .next = NEXT(NEXT_ENTRY(END),
2971 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2972 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2977 .help = "check whether a flow rule can be created",
2978 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2979 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2984 .help = "create a flow rule",
2985 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2986 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2991 .help = "destroy specific flow rules",
2992 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2993 NEXT_ENTRY(COMMON_PORT_ID)),
2994 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2995 .call = parse_destroy,
2999 .help = "destroy all flow rules",
3000 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3001 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3002 .call = parse_flush,
3006 .help = "dump single/all flow rules to file",
3007 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3008 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3013 .help = "query an existing flow rule",
3014 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
3015 NEXT_ENTRY(COMMON_RULE_ID),
3016 NEXT_ENTRY(COMMON_PORT_ID)),
3017 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
3018 ARGS_ENTRY(struct buffer, args.query.rule),
3019 ARGS_ENTRY(struct buffer, port)),
3020 .call = parse_query,
3024 .help = "list existing flow rules",
3025 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3026 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3031 .help = "list and destroy aged flows",
3032 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3033 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3038 .help = "restrict ingress traffic to the defined flow rules",
3039 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
3040 NEXT_ENTRY(COMMON_PORT_ID)),
3041 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
3042 ARGS_ENTRY(struct buffer, port)),
3043 .call = parse_isolate,
3046 .name = "flex_item",
3047 .help = "flex item API",
3048 .next = NEXT(next_flex_item),
3051 [FLEX_ITEM_INIT] = {
3053 .help = "flex item init",
3054 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3055 ARGS_ENTRY(struct buffer, port)),
3056 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3057 NEXT_ENTRY(COMMON_PORT_ID)),
3060 [FLEX_ITEM_CREATE] = {
3062 .help = "flex item create",
3063 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
3064 ARGS_ENTRY(struct buffer, args.flex.token),
3065 ARGS_ENTRY(struct buffer, port)),
3066 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
3067 NEXT_ENTRY(COMMON_FLEX_TOKEN),
3068 NEXT_ENTRY(COMMON_PORT_ID)),
3071 [FLEX_ITEM_DESTROY] = {
3073 .help = "flex item destroy",
3074 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3075 ARGS_ENTRY(struct buffer, port)),
3076 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3077 NEXT_ENTRY(COMMON_PORT_ID)),
3082 .help = "new tunnel API",
3083 .next = NEXT(NEXT_ENTRY
3084 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
3085 .call = parse_tunnel,
3087 /* Tunnel arguments. */
3090 .help = "create new tunnel object",
3091 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
3092 NEXT_ENTRY(COMMON_PORT_ID)),
3093 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3094 .call = parse_tunnel,
3096 [TUNNEL_CREATE_TYPE] = {
3098 .help = "create new tunnel",
3099 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
3100 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
3101 .call = parse_tunnel,
3103 [TUNNEL_DESTROY] = {
3105 .help = "destroy tunnel",
3106 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
3107 NEXT_ENTRY(COMMON_PORT_ID)),
3108 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3109 .call = parse_tunnel,
3111 [TUNNEL_DESTROY_ID] = {
3113 .help = "tunnel identifier to destroy",
3114 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
3115 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3116 .call = parse_tunnel,
3120 .help = "list existing tunnels",
3121 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3122 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3123 .call = parse_tunnel,
3125 /* Destroy arguments. */
3128 .help = "specify a rule identifier",
3129 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3130 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
3131 .call = parse_destroy,
3133 /* Dump arguments. */
3137 .next = NEXT(next_dump_attr),
3138 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
3143 .help = "dump one rule",
3144 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3145 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
3146 ARGS_ENTRY(struct buffer, args.dump.rule)),
3149 /* Query arguments. */
3153 .help = "action to query, must be part of the rule",
3154 .call = parse_action,
3155 .comp = comp_action,
3157 /* List arguments. */
3160 .help = "specify a group",
3161 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3162 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
3167 .help = "specify aged flows need be destroyed",
3171 /* Validate/create attributes. */
3174 .help = "specify a group",
3175 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3176 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
3181 .help = "specify a priority level",
3182 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3183 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
3188 .help = "affect rule to ingress",
3189 .next = NEXT(next_vc_attr),
3194 .help = "affect rule to egress",
3195 .next = NEXT(next_vc_attr),
3200 .help = "apply rule directly to endpoints found in pattern",
3201 .next = NEXT(next_vc_attr),
3205 .name = "tunnel_set",
3206 .help = "tunnel steer rule",
3207 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3208 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3211 [VC_TUNNEL_MATCH] = {
3212 .name = "tunnel_match",
3213 .help = "tunnel match rule",
3214 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3215 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3218 /* Validate/create pattern. */
3221 .help = "submit a list of pattern items",
3222 .next = NEXT(next_item),
3227 .help = "match value perfectly (with full bit-mask)",
3228 .call = parse_vc_spec,
3230 [ITEM_PARAM_SPEC] = {
3232 .help = "match value according to configured bit-mask",
3233 .call = parse_vc_spec,
3235 [ITEM_PARAM_LAST] = {
3237 .help = "specify upper bound to establish a range",
3238 .call = parse_vc_spec,
3240 [ITEM_PARAM_MASK] = {
3242 .help = "specify bit-mask with relevant bits set to one",
3243 .call = parse_vc_spec,
3245 [ITEM_PARAM_PREFIX] = {
3247 .help = "generate bit-mask from a prefix length",
3248 .call = parse_vc_spec,
3252 .help = "specify next pattern item",
3253 .next = NEXT(next_item),
3257 .help = "end list of pattern items",
3258 .priv = PRIV_ITEM(END, 0),
3259 .next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3264 .help = "no-op pattern item",
3265 .priv = PRIV_ITEM(VOID, 0),
3266 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3271 .help = "perform actions when pattern does not match",
3272 .priv = PRIV_ITEM(INVERT, 0),
3273 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3278 .help = "match any protocol for the current layer",
3279 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
3280 .next = NEXT(item_any),
3285 .help = "number of layers covered",
3286 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3287 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
3291 .help = "match traffic from/to the physical function",
3292 .priv = PRIV_ITEM(PF, 0),
3293 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3298 .help = "match traffic from/to a virtual function ID",
3299 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
3300 .next = NEXT(item_vf),
3306 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3307 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
3311 .help = "match traffic from/to a specific physical port",
3312 .priv = PRIV_ITEM(PHY_PORT,
3313 sizeof(struct rte_flow_item_phy_port)),
3314 .next = NEXT(item_phy_port),
3317 [ITEM_PHY_PORT_INDEX] = {
3319 .help = "physical port index",
3320 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
3322 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
3326 .help = "match traffic from/to a given DPDK port ID",
3327 .priv = PRIV_ITEM(PORT_ID,
3328 sizeof(struct rte_flow_item_port_id)),
3329 .next = NEXT(item_port_id),
3332 [ITEM_PORT_ID_ID] = {
3334 .help = "DPDK port ID",
3335 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
3337 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
3341 .help = "match traffic against value set in previously matched rule",
3342 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
3343 .next = NEXT(item_mark),
3348 .help = "Integer value to match against",
3349 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
3351 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
3355 .help = "match an arbitrary byte string",
3356 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
3357 .next = NEXT(item_raw),
3360 [ITEM_RAW_RELATIVE] = {
3362 .help = "look for pattern after the previous item",
3363 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3364 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3367 [ITEM_RAW_SEARCH] = {
3369 .help = "search pattern from offset (see also limit)",
3370 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3371 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3374 [ITEM_RAW_OFFSET] = {
3376 .help = "absolute or relative offset for pattern",
3377 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
3378 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
3380 [ITEM_RAW_LIMIT] = {
3382 .help = "search area limit for start of pattern",
3383 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3384 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
3386 [ITEM_RAW_PATTERN] = {
3388 .help = "byte string to look for",
3389 .next = NEXT(item_raw,
3390 NEXT_ENTRY(COMMON_STRING),
3391 NEXT_ENTRY(ITEM_PARAM_IS,
3394 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3395 ARGS_ENTRY(struct rte_flow_item_raw, length),
3396 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3397 ITEM_RAW_PATTERN_SIZE)),
3399 [ITEM_RAW_PATTERN_HEX] = {
3400 .name = "pattern_hex",
3401 .help = "hex string to look for",
3402 .next = NEXT(item_raw,
3403 NEXT_ENTRY(COMMON_HEX),
3404 NEXT_ENTRY(ITEM_PARAM_IS,
3407 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3408 ARGS_ENTRY(struct rte_flow_item_raw, length),
3409 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3410 ITEM_RAW_PATTERN_SIZE)),
3414 .help = "match Ethernet header",
3415 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
3416 .next = NEXT(item_eth),
3421 .help = "destination MAC",
3422 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3423 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
3427 .help = "source MAC",
3428 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3429 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
3433 .help = "EtherType",
3434 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3435 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
3437 [ITEM_ETH_HAS_VLAN] = {
3439 .help = "packet header contains VLAN",
3440 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3441 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
3446 .help = "match 802.1Q/ad VLAN tag",
3447 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
3448 .next = NEXT(item_vlan),
3453 .help = "tag control information",
3454 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3456 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
3460 .help = "priority code point",
3461 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3463 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3468 .help = "drop eligible indicator",
3469 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3471 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3476 .help = "VLAN identifier",
3477 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3479 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3482 [ITEM_VLAN_INNER_TYPE] = {
3483 .name = "inner_type",
3484 .help = "inner EtherType",
3485 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3487 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
3490 [ITEM_VLAN_HAS_MORE_VLAN] = {
3491 .name = "has_more_vlan",
3492 .help = "packet header contains another VLAN",
3493 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3495 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
3500 .help = "match IPv4 header",
3501 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
3502 .next = NEXT(item_ipv4),
3505 [ITEM_IPV4_VER_IHL] = {
3506 .name = "version_ihl",
3507 .help = "match header length",
3508 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3510 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
3515 .help = "type of service",
3516 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3518 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3519 hdr.type_of_service)),
3522 .name = "packet_id",
3523 .help = "fragment packet id",
3524 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3526 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3529 [ITEM_IPV4_FRAGMENT_OFFSET] = {
3530 .name = "fragment_offset",
3531 .help = "fragmentation flags and fragment offset",
3532 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3534 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3535 hdr.fragment_offset)),
3539 .help = "time to live",
3540 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3542 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3545 [ITEM_IPV4_PROTO] = {
3547 .help = "next protocol ID",
3548 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3550 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3551 hdr.next_proto_id)),
3555 .help = "source address",
3556 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3558 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3563 .help = "destination address",
3564 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3566 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3571 .help = "match IPv6 header",
3572 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
3573 .next = NEXT(item_ipv6),
3578 .help = "traffic class",
3579 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3581 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3583 "\x0f\xf0\x00\x00")),
3585 [ITEM_IPV6_FLOW] = {
3587 .help = "flow label",
3588 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3590 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3592 "\x00\x0f\xff\xff")),
3594 [ITEM_IPV6_PROTO] = {
3596 .help = "protocol (next header)",
3597 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3599 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3604 .help = "hop limit",
3605 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3607 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3612 .help = "source address",
3613 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3615 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3620 .help = "destination address",
3621 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3623 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3626 [ITEM_IPV6_HAS_FRAG_EXT] = {
3627 .name = "has_frag_ext",
3628 .help = "fragment packet attribute",
3629 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3631 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
3636 .help = "match ICMP header",
3637 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
3638 .next = NEXT(item_icmp),
3641 [ITEM_ICMP_TYPE] = {
3643 .help = "ICMP packet type",
3644 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3646 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3649 [ITEM_ICMP_CODE] = {
3651 .help = "ICMP packet code",
3652 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3654 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3657 [ITEM_ICMP_IDENT] = {
3659 .help = "ICMP packet identifier",
3660 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3662 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3667 .help = "ICMP packet sequence number",
3668 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3670 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3675 .help = "match UDP header",
3676 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
3677 .next = NEXT(item_udp),
3682 .help = "UDP source port",
3683 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
3685 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3690 .help = "UDP destination port",
3691 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3692 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3697 .help = "match TCP header",
3698 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
3699 .next = NEXT(item_tcp),
3704 .help = "TCP source port",
3705 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3706 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3711 .help = "TCP destination port",
3712 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3713 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3716 [ITEM_TCP_FLAGS] = {
3718 .help = "TCP flags",
3719 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3720 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3725 .help = "match SCTP header",
3726 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
3727 .next = NEXT(item_sctp),
3732 .help = "SCTP source port",
3733 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3735 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3740 .help = "SCTP destination port",
3741 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3743 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3748 .help = "validation tag",
3749 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3751 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3754 [ITEM_SCTP_CKSUM] = {
3757 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3759 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3764 .help = "match VXLAN header",
3765 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
3766 .next = NEXT(item_vxlan),
3769 [ITEM_VXLAN_VNI] = {
3771 .help = "VXLAN identifier",
3772 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3774 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
3776 [ITEM_VXLAN_LAST_RSVD] = {
3777 .name = "last_rsvd",
3778 .help = "VXLAN last reserved bits",
3779 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3781 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
3786 .help = "match E-Tag header",
3787 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
3788 .next = NEXT(item_e_tag),
3791 [ITEM_E_TAG_GRP_ECID_B] = {
3792 .name = "grp_ecid_b",
3793 .help = "GRP and E-CID base",
3794 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3796 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
3802 .help = "match NVGRE header",
3803 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
3804 .next = NEXT(item_nvgre),
3807 [ITEM_NVGRE_TNI] = {
3809 .help = "virtual subnet ID",
3810 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
3812 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
3816 .help = "match MPLS header",
3817 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
3818 .next = NEXT(item_mpls),
3821 [ITEM_MPLS_LABEL] = {
3823 .help = "MPLS label",
3824 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3826 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3832 .help = "MPLS Traffic Class",
3833 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3835 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3841 .help = "MPLS Bottom-of-Stack",
3842 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3844 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3850 .help = "match GRE header",
3851 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
3852 .next = NEXT(item_gre),
3855 [ITEM_GRE_PROTO] = {
3857 .help = "GRE protocol type",
3858 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3860 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3863 [ITEM_GRE_C_RSVD0_VER] = {
3864 .name = "c_rsvd0_ver",
3866 "checksum (1b), undefined (1b), key bit (1b),"
3867 " sequence number (1b), reserved 0 (9b),"
3869 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3871 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3874 [ITEM_GRE_C_BIT] = {
3876 .help = "checksum bit (C)",
3877 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
3879 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3881 "\x80\x00\x00\x00")),
3883 [ITEM_GRE_S_BIT] = {
3885 .help = "sequence number bit (S)",
3886 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3887 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3889 "\x10\x00\x00\x00")),
3891 [ITEM_GRE_K_BIT] = {
3893 .help = "key bit (K)",
3894 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3895 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3897 "\x20\x00\x00\x00")),
3901 .help = "fuzzy pattern match, expect faster than default",
3902 .priv = PRIV_ITEM(FUZZY,
3903 sizeof(struct rte_flow_item_fuzzy)),
3904 .next = NEXT(item_fuzzy),
3907 [ITEM_FUZZY_THRESH] = {
3909 .help = "match accuracy threshold",
3910 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
3912 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
3917 .help = "match GTP header",
3918 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
3919 .next = NEXT(item_gtp),
3922 [ITEM_GTP_FLAGS] = {
3923 .name = "v_pt_rsv_flags",
3924 .help = "GTP flags",
3925 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3926 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3929 [ITEM_GTP_MSG_TYPE] = {
3931 .help = "GTP message type",
3932 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3933 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3937 .help = "tunnel endpoint identifier",
3938 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3939 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3943 .help = "match GTP header",
3944 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3945 .next = NEXT(item_gtp),
3950 .help = "match GTP header",
3951 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3952 .next = NEXT(item_gtp),
3957 .help = "match GENEVE header",
3958 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3959 .next = NEXT(item_geneve),
3962 [ITEM_GENEVE_VNI] = {
3964 .help = "virtual network identifier",
3965 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3967 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3969 [ITEM_GENEVE_PROTO] = {
3971 .help = "GENEVE protocol type",
3972 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3974 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3977 [ITEM_GENEVE_OPTLEN] = {
3979 .help = "GENEVE options length in dwords",
3980 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3982 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3983 ver_opt_len_o_c_rsvd0,
3986 [ITEM_VXLAN_GPE] = {
3987 .name = "vxlan-gpe",
3988 .help = "match VXLAN-GPE header",
3989 .priv = PRIV_ITEM(VXLAN_GPE,
3990 sizeof(struct rte_flow_item_vxlan_gpe)),
3991 .next = NEXT(item_vxlan_gpe),
3994 [ITEM_VXLAN_GPE_VNI] = {
3996 .help = "VXLAN-GPE identifier",
3997 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3999 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
4002 [ITEM_ARP_ETH_IPV4] = {
4003 .name = "arp_eth_ipv4",
4004 .help = "match ARP header for Ethernet/IPv4",
4005 .priv = PRIV_ITEM(ARP_ETH_IPV4,
4006 sizeof(struct rte_flow_item_arp_eth_ipv4)),
4007 .next = NEXT(item_arp_eth_ipv4),
4010 [ITEM_ARP_ETH_IPV4_SHA] = {
4012 .help = "sender hardware address",
4013 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4015 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4018 [ITEM_ARP_ETH_IPV4_SPA] = {
4020 .help = "sender IPv4 address",
4021 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4023 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4026 [ITEM_ARP_ETH_IPV4_THA] = {
4028 .help = "target hardware address",
4029 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4031 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4034 [ITEM_ARP_ETH_IPV4_TPA] = {
4036 .help = "target IPv4 address",
4037 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4039 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4044 .help = "match presence of any IPv6 extension header",
4045 .priv = PRIV_ITEM(IPV6_EXT,
4046 sizeof(struct rte_flow_item_ipv6_ext)),
4047 .next = NEXT(item_ipv6_ext),
4050 [ITEM_IPV6_EXT_NEXT_HDR] = {
4052 .help = "next header",
4053 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4055 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
4058 [ITEM_IPV6_FRAG_EXT] = {
4059 .name = "ipv6_frag_ext",
4060 .help = "match presence of IPv6 fragment extension header",
4061 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
4062 sizeof(struct rte_flow_item_ipv6_frag_ext)),
4063 .next = NEXT(item_ipv6_frag_ext),
4066 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
4068 .help = "next header",
4069 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4071 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
4074 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
4075 .name = "frag_data",
4076 .help = "fragment flags and offset",
4077 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4079 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4082 [ITEM_IPV6_FRAG_EXT_ID] = {
4083 .name = "packet_id",
4084 .help = "fragment packet id",
4085 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4087 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4092 .help = "match any ICMPv6 header",
4093 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
4094 .next = NEXT(item_icmp6),
4097 [ITEM_ICMP6_TYPE] = {
4099 .help = "ICMPv6 type",
4100 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4102 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4105 [ITEM_ICMP6_CODE] = {
4107 .help = "ICMPv6 code",
4108 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4110 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4113 [ITEM_ICMP6_ND_NS] = {
4114 .name = "icmp6_nd_ns",
4115 .help = "match ICMPv6 neighbor discovery solicitation",
4116 .priv = PRIV_ITEM(ICMP6_ND_NS,
4117 sizeof(struct rte_flow_item_icmp6_nd_ns)),
4118 .next = NEXT(item_icmp6_nd_ns),
4121 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
4122 .name = "target_addr",
4123 .help = "target address",
4124 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
4126 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
4129 [ITEM_ICMP6_ND_NA] = {
4130 .name = "icmp6_nd_na",
4131 .help = "match ICMPv6 neighbor discovery advertisement",
4132 .priv = PRIV_ITEM(ICMP6_ND_NA,
4133 sizeof(struct rte_flow_item_icmp6_nd_na)),
4134 .next = NEXT(item_icmp6_nd_na),
4137 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
4138 .name = "target_addr",
4139 .help = "target address",
4140 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
4142 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
4145 [ITEM_ICMP6_ND_OPT] = {
4146 .name = "icmp6_nd_opt",
4147 .help = "match presence of any ICMPv6 neighbor discovery"
4149 .priv = PRIV_ITEM(ICMP6_ND_OPT,
4150 sizeof(struct rte_flow_item_icmp6_nd_opt)),
4151 .next = NEXT(item_icmp6_nd_opt),
4154 [ITEM_ICMP6_ND_OPT_TYPE] = {
4156 .help = "ND option type",
4157 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4159 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
4162 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
4163 .name = "icmp6_nd_opt_sla_eth",
4164 .help = "match ICMPv6 neighbor discovery source Ethernet"
4165 " link-layer address option",
4167 (ICMP6_ND_OPT_SLA_ETH,
4168 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
4169 .next = NEXT(item_icmp6_nd_opt_sla_eth),
4172 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
4174 .help = "source Ethernet LLA",
4175 .next = NEXT(item_icmp6_nd_opt_sla_eth,
4176 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4177 .args = ARGS(ARGS_ENTRY_HTON
4178 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
4180 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
4181 .name = "icmp6_nd_opt_tla_eth",
4182 .help = "match ICMPv6 neighbor discovery target Ethernet"
4183 " link-layer address option",
4185 (ICMP6_ND_OPT_TLA_ETH,
4186 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
4187 .next = NEXT(item_icmp6_nd_opt_tla_eth),
4190 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
4192 .help = "target Ethernet LLA",
4193 .next = NEXT(item_icmp6_nd_opt_tla_eth,
4194 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4195 .args = ARGS(ARGS_ENTRY_HTON
4196 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
4200 .help = "match metadata header",
4201 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
4202 .next = NEXT(item_meta),
4205 [ITEM_META_DATA] = {
4207 .help = "metadata value",
4208 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
4210 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
4211 data, "\xff\xff\xff\xff")),
4215 .help = "match GRE key",
4216 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
4217 .next = NEXT(item_gre_key),
4220 [ITEM_GRE_KEY_VALUE] = {
4222 .help = "key value",
4223 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
4225 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4227 [ITEM_GRE_OPTION] = {
4228 .name = "gre_option",
4229 .help = "match GRE optional fields",
4230 .priv = PRIV_ITEM(GRE_OPTION,
4231 sizeof(struct rte_flow_item_gre_opt)),
4232 .next = NEXT(item_gre_option),
4235 [ITEM_GRE_OPTION_CHECKSUM] = {
4237 .help = "match GRE checksum",
4238 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4240 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4241 checksum_rsvd.checksum)),
4243 [ITEM_GRE_OPTION_KEY] = {
4245 .help = "match GRE key",
4246 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4248 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4251 [ITEM_GRE_OPTION_SEQUENCE] = {
4253 .help = "match GRE sequence",
4254 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4256 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4257 sequence.sequence)),
4261 .help = "match GTP extension header with type 0x85",
4262 .priv = PRIV_ITEM(GTP_PSC,
4263 sizeof(struct rte_flow_item_gtp_psc)),
4264 .next = NEXT(item_gtp_psc),
4267 [ITEM_GTP_PSC_QFI] = {
4269 .help = "QoS flow identifier",
4270 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4272 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4275 [ITEM_GTP_PSC_PDU_T] = {
4278 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4280 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4285 .help = "match PPPoE session header",
4286 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
4287 .next = NEXT(item_pppoes),
4292 .help = "match PPPoE discovery header",
4293 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
4294 .next = NEXT(item_pppoed),
4297 [ITEM_PPPOE_SEID] = {
4299 .help = "session identifier",
4300 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
4302 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
4305 [ITEM_PPPOE_PROTO_ID] = {
4306 .name = "pppoe_proto_id",
4307 .help = "match PPPoE session protocol identifier",
4308 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
4309 sizeof(struct rte_flow_item_pppoe_proto_id)),
4310 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
4312 .args = ARGS(ARGS_ENTRY_HTON
4313 (struct rte_flow_item_pppoe_proto_id, proto_id)),
4318 .help = "matches higig2 header",
4319 .priv = PRIV_ITEM(HIGIG2,
4320 sizeof(struct rte_flow_item_higig2_hdr)),
4321 .next = NEXT(item_higig2),
4324 [ITEM_HIGIG2_CLASSIFICATION] = {
4325 .name = "classification",
4326 .help = "matches classification of higig2 header",
4327 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4329 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4330 hdr.ppt1.classification)),
4332 [ITEM_HIGIG2_VID] = {
4334 .help = "matches vid of higig2 header",
4335 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4337 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4342 .help = "match tag value",
4343 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
4344 .next = NEXT(item_tag),
4349 .help = "tag value to match",
4350 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4351 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
4353 [ITEM_TAG_INDEX] = {
4355 .help = "index of tag array to match",
4356 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4357 NEXT_ENTRY(ITEM_PARAM_IS)),
4358 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
4360 [ITEM_L2TPV3OIP] = {
4361 .name = "l2tpv3oip",
4362 .help = "match L2TPv3 over IP header",
4363 .priv = PRIV_ITEM(L2TPV3OIP,
4364 sizeof(struct rte_flow_item_l2tpv3oip)),
4365 .next = NEXT(item_l2tpv3oip),
4368 [ITEM_L2TPV3OIP_SESSION_ID] = {
4369 .name = "session_id",
4370 .help = "session identifier",
4371 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
4373 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
4378 .help = "match ESP header",
4379 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
4380 .next = NEXT(item_esp),
4385 .help = "security policy index",
4386 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4387 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
4392 .help = "match AH header",
4393 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
4394 .next = NEXT(item_ah),
4399 .help = "security parameters index",
4400 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4401 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
4405 .help = "match pfcp header",
4406 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
4407 .next = NEXT(item_pfcp),
4410 [ITEM_PFCP_S_FIELD] = {
4413 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
4415 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
4418 [ITEM_PFCP_SEID] = {
4420 .help = "session endpoint identifier",
4421 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
4423 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
4427 .help = "match eCPRI header",
4428 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
4429 .next = NEXT(item_ecpri),
4432 [ITEM_ECPRI_COMMON] = {
4434 .help = "eCPRI common header",
4435 .next = NEXT(item_ecpri_common),
4437 [ITEM_ECPRI_COMMON_TYPE] = {
4439 .help = "type of common header",
4440 .next = NEXT(item_ecpri_common_type),
4441 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
4443 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
4445 .help = "Type #0: IQ Data",
4446 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
4448 .call = parse_vc_item_ecpri_type,
4450 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
4452 .help = "Physical Channel ID",
4453 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
4454 ITEM_ECPRI_COMMON, ITEM_NEXT),
4455 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4456 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4459 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
4461 .help = "Type #2: Real-Time Control Data",
4462 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
4464 .call = parse_vc_item_ecpri_type,
4466 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
4468 .help = "Real-Time Control Data ID",
4469 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
4470 ITEM_ECPRI_COMMON, ITEM_NEXT),
4471 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4472 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4475 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
4476 .name = "delay_measure",
4477 .help = "Type #5: One-Way Delay Measurement",
4478 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
4480 .call = parse_vc_item_ecpri_type,
4482 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
4484 .help = "Measurement ID",
4485 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
4486 ITEM_ECPRI_COMMON, ITEM_NEXT),
4487 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4488 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4491 [ITEM_GENEVE_OPT] = {
4492 .name = "geneve-opt",
4493 .help = "GENEVE header option",
4494 .priv = PRIV_ITEM(GENEVE_OPT,
4495 sizeof(struct rte_flow_item_geneve_opt) +
4496 ITEM_GENEVE_OPT_DATA_SIZE),
4497 .next = NEXT(item_geneve_opt),
4500 [ITEM_GENEVE_OPT_CLASS] = {
4502 .help = "GENEVE option class",
4503 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4505 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
4508 [ITEM_GENEVE_OPT_TYPE] = {
4510 .help = "GENEVE option type",
4511 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4513 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
4516 [ITEM_GENEVE_OPT_LENGTH] = {
4518 .help = "GENEVE option data length (in 32b words)",
4519 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4521 .args = ARGS(ARGS_ENTRY_BOUNDED(
4522 struct rte_flow_item_geneve_opt, option_len,
4525 [ITEM_GENEVE_OPT_DATA] = {
4527 .help = "GENEVE option data pattern",
4528 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
4530 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
4531 ARGS_ENTRY_ARB(0, 0),
4533 (sizeof(struct rte_flow_item_geneve_opt),
4534 ITEM_GENEVE_OPT_DATA_SIZE)),
4536 [ITEM_INTEGRITY] = {
4537 .name = "integrity",
4538 .help = "match packet integrity",
4539 .priv = PRIV_ITEM(INTEGRITY,
4540 sizeof(struct rte_flow_item_integrity)),
4541 .next = NEXT(item_integrity),
4544 [ITEM_INTEGRITY_LEVEL] = {
4546 .help = "integrity level",
4547 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
4549 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
4551 [ITEM_INTEGRITY_VALUE] = {
4553 .help = "integrity value",
4554 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
4556 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
4558 [ITEM_CONNTRACK] = {
4559 .name = "conntrack",
4560 .help = "conntrack state",
4561 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
4563 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
4565 [ITEM_PORT_REPRESENTOR] = {
4566 .name = "port_representor",
4567 .help = "match traffic entering the embedded switch from the given ethdev",
4568 .priv = PRIV_ITEM(PORT_REPRESENTOR,
4569 sizeof(struct rte_flow_item_ethdev)),
4570 .next = NEXT(item_port_representor),
4573 [ITEM_PORT_REPRESENTOR_PORT_ID] = {
4575 .help = "ethdev port ID",
4576 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
4578 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4580 [ITEM_REPRESENTED_PORT] = {
4581 .name = "represented_port",
4582 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
4583 .priv = PRIV_ITEM(REPRESENTED_PORT,
4584 sizeof(struct rte_flow_item_ethdev)),
4585 .next = NEXT(item_represented_port),
4588 [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
4589 .name = "ethdev_port_id",
4590 .help = "ethdev port ID",
4591 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
4593 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4597 .help = "match flex header",
4598 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
4599 .next = NEXT(item_flex),
4602 [ITEM_FLEX_ITEM_HANDLE] = {
4604 .help = "flex item handle",
4605 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4606 NEXT_ENTRY(ITEM_PARAM_IS)),
4607 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
4609 [ITEM_FLEX_PATTERN_HANDLE] = {
4611 .help = "flex pattern handle",
4612 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4613 NEXT_ENTRY(ITEM_PARAM_IS)),
4614 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
4618 .help = "match L2TPv2 header",
4619 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
4620 .next = NEXT(item_l2tpv2),
4623 [ITEM_L2TPV2_TYPE] = {
4625 .help = "type of l2tpv2",
4626 .next = NEXT(item_l2tpv2_type),
4627 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
4629 [ITEM_L2TPV2_TYPE_DATA] = {
4631 .help = "Type #7: data message without any options",
4632 .next = NEXT(item_l2tpv2_type_data),
4633 .call = parse_vc_item_l2tpv2_type,
4635 [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
4636 .name = "tunnel_id",
4637 .help = "tunnel identifier",
4638 .next = NEXT(item_l2tpv2_type_data,
4639 NEXT_ENTRY(COMMON_UNSIGNED),
4641 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4642 hdr.type7.tunnel_id)),
4644 [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
4645 .name = "session_id",
4646 .help = "session identifier",
4647 .next = NEXT(item_l2tpv2_type_data,
4648 NEXT_ENTRY(COMMON_UNSIGNED),
4650 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4651 hdr.type7.session_id)),
4653 [ITEM_L2TPV2_TYPE_DATA_L] = {
4655 .help = "Type #6: data message with length option",
4656 .next = NEXT(item_l2tpv2_type_data_l),
4657 .call = parse_vc_item_l2tpv2_type,
4659 [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
4661 .help = "message length",
4662 .next = NEXT(item_l2tpv2_type_data_l,
4663 NEXT_ENTRY(COMMON_UNSIGNED),
4665 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4668 [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
4669 .name = "tunnel_id",
4670 .help = "tunnel identifier",
4671 .next = NEXT(item_l2tpv2_type_data_l,
4672 NEXT_ENTRY(COMMON_UNSIGNED),
4674 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4675 hdr.type6.tunnel_id)),
4677 [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
4678 .name = "session_id",
4679 .help = "session identifier",
4680 .next = NEXT(item_l2tpv2_type_data_l,
4681 NEXT_ENTRY(COMMON_UNSIGNED),
4683 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4684 hdr.type6.session_id)),
4686 [ITEM_L2TPV2_TYPE_DATA_S] = {
4688 .help = "Type #5: data message with ns, nr option",
4689 .next = NEXT(item_l2tpv2_type_data_s),
4690 .call = parse_vc_item_l2tpv2_type,
4692 [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
4693 .name = "tunnel_id",
4694 .help = "tunnel identifier",
4695 .next = NEXT(item_l2tpv2_type_data_s,
4696 NEXT_ENTRY(COMMON_UNSIGNED),
4698 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4699 hdr.type5.tunnel_id)),
4701 [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
4702 .name = "session_id",
4703 .help = "session identifier",
4704 .next = NEXT(item_l2tpv2_type_data_s,
4705 NEXT_ENTRY(COMMON_UNSIGNED),
4707 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4708 hdr.type5.session_id)),
4710 [ITEM_L2TPV2_MSG_DATA_S_NS] = {
4712 .help = "sequence number for message",
4713 .next = NEXT(item_l2tpv2_type_data_s,
4714 NEXT_ENTRY(COMMON_UNSIGNED),
4716 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4719 [ITEM_L2TPV2_MSG_DATA_S_NR] = {
4721 .help = "sequence number for next receive message",
4722 .next = NEXT(item_l2tpv2_type_data_s,
4723 NEXT_ENTRY(COMMON_UNSIGNED),
4725 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4728 [ITEM_L2TPV2_TYPE_DATA_O] = {
4730 .help = "Type #4: data message with offset option",
4731 .next = NEXT(item_l2tpv2_type_data_o),
4732 .call = parse_vc_item_l2tpv2_type,
4734 [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
4735 .name = "tunnel_id",
4736 .help = "tunnel identifier",
4737 .next = NEXT(item_l2tpv2_type_data_o,
4738 NEXT_ENTRY(COMMON_UNSIGNED),
4740 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4741 hdr.type4.tunnel_id)),
4743 [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
4744 .name = "session_id",
4745 .help = "session identifier",
4746 .next = NEXT(item_l2tpv2_type_data_o,
4747 NEXT_ENTRY(COMMON_UNSIGNED),
4749 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4750 hdr.type5.session_id)),
4752 [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
4753 .name = "offset_size",
4754 .help = "the size of offset padding",
4755 .next = NEXT(item_l2tpv2_type_data_o,
4756 NEXT_ENTRY(COMMON_UNSIGNED),
4758 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4759 hdr.type4.offset_size)),
4761 [ITEM_L2TPV2_TYPE_DATA_L_S] = {
4763 .help = "Type #3: data message contains length, ns, nr "
4765 .next = NEXT(item_l2tpv2_type_data_l_s),
4766 .call = parse_vc_item_l2tpv2_type,
4768 [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
4770 .help = "message length",
4771 .next = NEXT(item_l2tpv2_type_data_l_s,
4772 NEXT_ENTRY(COMMON_UNSIGNED),
4774 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4777 [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
4778 .name = "tunnel_id",
4779 .help = "tunnel identifier",
4780 .next = NEXT(item_l2tpv2_type_data_l_s,
4781 NEXT_ENTRY(COMMON_UNSIGNED),
4783 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4784 hdr.type3.tunnel_id)),
4786 [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
4787 .name = "session_id",
4788 .help = "session identifier",
4789 .next = NEXT(item_l2tpv2_type_data_l_s,
4790 NEXT_ENTRY(COMMON_UNSIGNED),
4792 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4793 hdr.type3.session_id)),
4795 [ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
4797 .help = "sequence number for message",
4798 .next = NEXT(item_l2tpv2_type_data_l_s,
4799 NEXT_ENTRY(COMMON_UNSIGNED),
4801 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4804 [ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
4806 .help = "sequence number for next receive message",
4807 .next = NEXT(item_l2tpv2_type_data_l_s,
4808 NEXT_ENTRY(COMMON_UNSIGNED),
4810 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4813 [ITEM_L2TPV2_TYPE_CTRL] = {
4815 .help = "Type #3: conrtol message contains length, ns, nr "
4817 .next = NEXT(item_l2tpv2_type_ctrl),
4818 .call = parse_vc_item_l2tpv2_type,
4820 [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
4822 .help = "message length",
4823 .next = NEXT(item_l2tpv2_type_ctrl,
4824 NEXT_ENTRY(COMMON_UNSIGNED),
4826 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4829 [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
4830 .name = "tunnel_id",
4831 .help = "tunnel identifier",
4832 .next = NEXT(item_l2tpv2_type_ctrl,
4833 NEXT_ENTRY(COMMON_UNSIGNED),
4835 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4836 hdr.type3.tunnel_id)),
4838 [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
4839 .name = "session_id",
4840 .help = "session identifier",
4841 .next = NEXT(item_l2tpv2_type_ctrl,
4842 NEXT_ENTRY(COMMON_UNSIGNED),
4844 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4845 hdr.type3.session_id)),
4847 [ITEM_L2TPV2_MSG_CTRL_NS] = {
4849 .help = "sequence number for message",
4850 .next = NEXT(item_l2tpv2_type_ctrl,
4851 NEXT_ENTRY(COMMON_UNSIGNED),
4853 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4856 [ITEM_L2TPV2_MSG_CTRL_NR] = {
4858 .help = "sequence number for next receive message",
4859 .next = NEXT(item_l2tpv2_type_ctrl,
4860 NEXT_ENTRY(COMMON_UNSIGNED),
4862 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4867 .help = "match PPP header",
4868 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
4869 .next = NEXT(item_ppp),
4874 .help = "PPP address",
4875 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4877 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
4881 .help = "PPP control",
4882 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4884 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
4886 [ITEM_PPP_PROTO_ID] = {
4888 .help = "PPP protocol identifier",
4889 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4891 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
4894 /* Validate/create actions. */
4897 .help = "submit a list of associated actions",
4898 .next = NEXT(next_action),
4903 .help = "specify next action",
4904 .next = NEXT(next_action),
4908 .help = "end list of actions",
4909 .priv = PRIV_ACTION(END, 0),
4914 .help = "no-op action",
4915 .priv = PRIV_ACTION(VOID, 0),
4916 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4919 [ACTION_PASSTHRU] = {
4921 .help = "let subsequent rule process matched packets",
4922 .priv = PRIV_ACTION(PASSTHRU, 0),
4923 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4928 .help = "redirect traffic to a given group",
4929 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
4930 .next = NEXT(action_jump),
4933 [ACTION_JUMP_GROUP] = {
4935 .help = "group to redirect traffic to",
4936 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
4937 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
4938 .call = parse_vc_conf,
4942 .help = "attach 32 bit value to packets",
4943 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
4944 .next = NEXT(action_mark),
4947 [ACTION_MARK_ID] = {
4949 .help = "32 bit value to return with packets",
4950 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
4951 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
4952 .call = parse_vc_conf,
4956 .help = "flag packets",
4957 .priv = PRIV_ACTION(FLAG, 0),
4958 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4963 .help = "assign packets to a given queue index",
4964 .priv = PRIV_ACTION(QUEUE,
4965 sizeof(struct rte_flow_action_queue)),
4966 .next = NEXT(action_queue),
4969 [ACTION_QUEUE_INDEX] = {
4971 .help = "queue index to use",
4972 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
4973 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
4974 .call = parse_vc_conf,
4978 .help = "drop packets (note: passthru has priority)",
4979 .priv = PRIV_ACTION(DROP, 0),
4980 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4985 .help = "enable counters for this rule",
4986 .priv = PRIV_ACTION(COUNT,
4987 sizeof(struct rte_flow_action_count)),
4988 .next = NEXT(action_count),
4991 [ACTION_COUNT_ID] = {
4992 .name = "identifier",
4993 .help = "counter identifier to use",
4994 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
4995 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
4996 .call = parse_vc_conf,
5000 .help = "spread packets among several queues",
5001 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
5002 .next = NEXT(action_rss),
5003 .call = parse_vc_action_rss,
5005 [ACTION_RSS_FUNC] = {
5007 .help = "RSS hash function to apply",
5008 .next = NEXT(action_rss,
5009 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
5010 ACTION_RSS_FUNC_TOEPLITZ,
5011 ACTION_RSS_FUNC_SIMPLE_XOR,
5012 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
5014 [ACTION_RSS_FUNC_DEFAULT] = {
5016 .help = "default hash function",
5017 .call = parse_vc_action_rss_func,
5019 [ACTION_RSS_FUNC_TOEPLITZ] = {
5021 .help = "Toeplitz hash function",
5022 .call = parse_vc_action_rss_func,
5024 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
5025 .name = "simple_xor",
5026 .help = "simple XOR hash function",
5027 .call = parse_vc_action_rss_func,
5029 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
5030 .name = "symmetric_toeplitz",
5031 .help = "Symmetric Toeplitz hash function",
5032 .call = parse_vc_action_rss_func,
5034 [ACTION_RSS_LEVEL] = {
5036 .help = "encapsulation level for \"types\"",
5037 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5038 .args = ARGS(ARGS_ENTRY_ARB
5039 (offsetof(struct action_rss_data, conf) +
5040 offsetof(struct rte_flow_action_rss, level),
5041 sizeof(((struct rte_flow_action_rss *)0)->
5044 [ACTION_RSS_TYPES] = {
5046 .help = "specific RSS hash types",
5047 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
5049 [ACTION_RSS_TYPE] = {
5051 .help = "RSS hash type",
5052 .call = parse_vc_action_rss_type,
5053 .comp = comp_vc_action_rss_type,
5055 [ACTION_RSS_KEY] = {
5057 .help = "RSS hash key",
5058 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
5059 .args = ARGS(ARGS_ENTRY_ARB
5060 (offsetof(struct action_rss_data, conf) +
5061 offsetof(struct rte_flow_action_rss, key),
5062 sizeof(((struct rte_flow_action_rss *)0)->key)),
5064 (offsetof(struct action_rss_data, conf) +
5065 offsetof(struct rte_flow_action_rss, key_len),
5066 sizeof(((struct rte_flow_action_rss *)0)->
5068 ARGS_ENTRY(struct action_rss_data, key)),
5070 [ACTION_RSS_KEY_LEN] = {
5072 .help = "RSS hash key length in bytes",
5073 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5074 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5075 (offsetof(struct action_rss_data, conf) +
5076 offsetof(struct rte_flow_action_rss, key_len),
5077 sizeof(((struct rte_flow_action_rss *)0)->
5080 RSS_HASH_KEY_LENGTH)),
5082 [ACTION_RSS_QUEUES] = {
5084 .help = "queue indices to use",
5085 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
5086 .call = parse_vc_conf,
5088 [ACTION_RSS_QUEUE] = {
5090 .help = "queue index",
5091 .call = parse_vc_action_rss_queue,
5092 .comp = comp_vc_action_rss_queue,
5096 .help = "direct traffic to physical function",
5097 .priv = PRIV_ACTION(PF, 0),
5098 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5103 .help = "direct traffic to a virtual function ID",
5104 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
5105 .next = NEXT(action_vf),
5108 [ACTION_VF_ORIGINAL] = {
5110 .help = "use original VF ID if possible",
5111 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
5112 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
5114 .call = parse_vc_conf,
5119 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
5120 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
5121 .call = parse_vc_conf,
5123 [ACTION_PHY_PORT] = {
5125 .help = "direct packets to physical port index",
5126 .priv = PRIV_ACTION(PHY_PORT,
5127 sizeof(struct rte_flow_action_phy_port)),
5128 .next = NEXT(action_phy_port),
5131 [ACTION_PHY_PORT_ORIGINAL] = {
5133 .help = "use original port index if possible",
5134 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
5135 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
5137 .call = parse_vc_conf,
5139 [ACTION_PHY_PORT_INDEX] = {
5141 .help = "physical port index",
5142 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
5143 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
5145 .call = parse_vc_conf,
5147 [ACTION_PORT_ID] = {
5149 .help = "direct matching traffic to a given DPDK port ID",
5150 .priv = PRIV_ACTION(PORT_ID,
5151 sizeof(struct rte_flow_action_port_id)),
5152 .next = NEXT(action_port_id),
5155 [ACTION_PORT_ID_ORIGINAL] = {
5157 .help = "use original DPDK port ID if possible",
5158 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
5159 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
5161 .call = parse_vc_conf,
5163 [ACTION_PORT_ID_ID] = {
5165 .help = "DPDK port ID",
5166 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
5167 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
5168 .call = parse_vc_conf,
5172 .help = "meter the directed packets at given id",
5173 .priv = PRIV_ACTION(METER,
5174 sizeof(struct rte_flow_action_meter)),
5175 .next = NEXT(action_meter),
5178 [ACTION_METER_COLOR] = {
5180 .help = "meter color for the packets",
5181 .priv = PRIV_ACTION(METER_COLOR,
5182 sizeof(struct rte_flow_action_meter_color)),
5183 .next = NEXT(action_meter_color),
5186 [ACTION_METER_COLOR_TYPE] = {
5188 .help = "specific meter color",
5189 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5190 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
5191 ACTION_METER_COLOR_YELLOW,
5192 ACTION_METER_COLOR_RED)),
5194 [ACTION_METER_COLOR_GREEN] = {
5196 .help = "meter color green",
5197 .call = parse_vc_action_meter_color_type,
5199 [ACTION_METER_COLOR_YELLOW] = {
5201 .help = "meter color yellow",
5202 .call = parse_vc_action_meter_color_type,
5204 [ACTION_METER_COLOR_RED] = {
5206 .help = "meter color red",
5207 .call = parse_vc_action_meter_color_type,
5209 [ACTION_METER_ID] = {
5211 .help = "meter id to use",
5212 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
5213 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
5214 .call = parse_vc_conf,
5216 [ACTION_OF_SET_MPLS_TTL] = {
5217 .name = "of_set_mpls_ttl",
5218 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
5221 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
5222 .next = NEXT(action_of_set_mpls_ttl),
5225 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
5228 .next = NEXT(action_of_set_mpls_ttl,
5229 NEXT_ENTRY(COMMON_UNSIGNED)),
5230 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
5232 .call = parse_vc_conf,
5234 [ACTION_OF_DEC_MPLS_TTL] = {
5235 .name = "of_dec_mpls_ttl",
5236 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
5237 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
5238 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5241 [ACTION_OF_SET_NW_TTL] = {
5242 .name = "of_set_nw_ttl",
5243 .help = "OpenFlow's OFPAT_SET_NW_TTL",
5246 sizeof(struct rte_flow_action_of_set_nw_ttl)),
5247 .next = NEXT(action_of_set_nw_ttl),
5250 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
5253 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5254 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
5256 .call = parse_vc_conf,
5258 [ACTION_OF_DEC_NW_TTL] = {
5259 .name = "of_dec_nw_ttl",
5260 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
5261 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
5262 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5265 [ACTION_OF_COPY_TTL_OUT] = {
5266 .name = "of_copy_ttl_out",
5267 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
5268 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
5269 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5272 [ACTION_OF_COPY_TTL_IN] = {
5273 .name = "of_copy_ttl_in",
5274 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
5275 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
5276 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5279 [ACTION_OF_POP_VLAN] = {
5280 .name = "of_pop_vlan",
5281 .help = "OpenFlow's OFPAT_POP_VLAN",
5282 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
5283 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5286 [ACTION_OF_PUSH_VLAN] = {
5287 .name = "of_push_vlan",
5288 .help = "OpenFlow's OFPAT_PUSH_VLAN",
5291 sizeof(struct rte_flow_action_of_push_vlan)),
5292 .next = NEXT(action_of_push_vlan),
5295 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
5296 .name = "ethertype",
5297 .help = "EtherType",
5298 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
5299 .args = ARGS(ARGS_ENTRY_HTON
5300 (struct rte_flow_action_of_push_vlan,
5302 .call = parse_vc_conf,
5304 [ACTION_OF_SET_VLAN_VID] = {
5305 .name = "of_set_vlan_vid",
5306 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
5309 sizeof(struct rte_flow_action_of_set_vlan_vid)),
5310 .next = NEXT(action_of_set_vlan_vid),
5313 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
5316 .next = NEXT(action_of_set_vlan_vid,
5317 NEXT_ENTRY(COMMON_UNSIGNED)),
5318 .args = ARGS(ARGS_ENTRY_HTON
5319 (struct rte_flow_action_of_set_vlan_vid,
5321 .call = parse_vc_conf,
5323 [ACTION_OF_SET_VLAN_PCP] = {
5324 .name = "of_set_vlan_pcp",
5325 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
5328 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
5329 .next = NEXT(action_of_set_vlan_pcp),
5332 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
5334 .help = "VLAN priority",
5335 .next = NEXT(action_of_set_vlan_pcp,
5336 NEXT_ENTRY(COMMON_UNSIGNED)),
5337 .args = ARGS(ARGS_ENTRY_HTON
5338 (struct rte_flow_action_of_set_vlan_pcp,
5340 .call = parse_vc_conf,
5342 [ACTION_OF_POP_MPLS] = {
5343 .name = "of_pop_mpls",
5344 .help = "OpenFlow's OFPAT_POP_MPLS",
5345 .priv = PRIV_ACTION(OF_POP_MPLS,
5346 sizeof(struct rte_flow_action_of_pop_mpls)),
5347 .next = NEXT(action_of_pop_mpls),
5350 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
5351 .name = "ethertype",
5352 .help = "EtherType",
5353 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5354 .args = ARGS(ARGS_ENTRY_HTON
5355 (struct rte_flow_action_of_pop_mpls,
5357 .call = parse_vc_conf,
5359 [ACTION_OF_PUSH_MPLS] = {
5360 .name = "of_push_mpls",
5361 .help = "OpenFlow's OFPAT_PUSH_MPLS",
5364 sizeof(struct rte_flow_action_of_push_mpls)),
5365 .next = NEXT(action_of_push_mpls),
5368 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
5369 .name = "ethertype",
5370 .help = "EtherType",
5371 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5372 .args = ARGS(ARGS_ENTRY_HTON
5373 (struct rte_flow_action_of_push_mpls,
5375 .call = parse_vc_conf,
5377 [ACTION_VXLAN_ENCAP] = {
5378 .name = "vxlan_encap",
5379 .help = "VXLAN encapsulation, uses configuration set by \"set"
5381 .priv = PRIV_ACTION(VXLAN_ENCAP,
5382 sizeof(struct action_vxlan_encap_data)),
5383 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5384 .call = parse_vc_action_vxlan_encap,
5386 [ACTION_VXLAN_DECAP] = {
5387 .name = "vxlan_decap",
5388 .help = "Performs a decapsulation action by stripping all"
5389 " headers of the VXLAN tunnel network overlay from the"
5391 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
5392 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5395 [ACTION_NVGRE_ENCAP] = {
5396 .name = "nvgre_encap",
5397 .help = "NVGRE encapsulation, uses configuration set by \"set"
5399 .priv = PRIV_ACTION(NVGRE_ENCAP,
5400 sizeof(struct action_nvgre_encap_data)),
5401 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5402 .call = parse_vc_action_nvgre_encap,
5404 [ACTION_NVGRE_DECAP] = {
5405 .name = "nvgre_decap",
5406 .help = "Performs a decapsulation action by stripping all"
5407 " headers of the NVGRE tunnel network overlay from the"
5409 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
5410 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5413 [ACTION_L2_ENCAP] = {
5415 .help = "l2 encap, uses configuration set by"
5416 " \"set l2_encap\"",
5417 .priv = PRIV_ACTION(RAW_ENCAP,
5418 sizeof(struct action_raw_encap_data)),
5419 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5420 .call = parse_vc_action_l2_encap,
5422 [ACTION_L2_DECAP] = {
5424 .help = "l2 decap, uses configuration set by"
5425 " \"set l2_decap\"",
5426 .priv = PRIV_ACTION(RAW_DECAP,
5427 sizeof(struct action_raw_decap_data)),
5428 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5429 .call = parse_vc_action_l2_decap,
5431 [ACTION_MPLSOGRE_ENCAP] = {
5432 .name = "mplsogre_encap",
5433 .help = "mplsogre encapsulation, uses configuration set by"
5434 " \"set mplsogre_encap\"",
5435 .priv = PRIV_ACTION(RAW_ENCAP,
5436 sizeof(struct action_raw_encap_data)),
5437 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5438 .call = parse_vc_action_mplsogre_encap,
5440 [ACTION_MPLSOGRE_DECAP] = {
5441 .name = "mplsogre_decap",
5442 .help = "mplsogre decapsulation, uses configuration set by"
5443 " \"set mplsogre_decap\"",
5444 .priv = PRIV_ACTION(RAW_DECAP,
5445 sizeof(struct action_raw_decap_data)),
5446 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5447 .call = parse_vc_action_mplsogre_decap,
5449 [ACTION_MPLSOUDP_ENCAP] = {
5450 .name = "mplsoudp_encap",
5451 .help = "mplsoudp encapsulation, uses configuration set by"
5452 " \"set mplsoudp_encap\"",
5453 .priv = PRIV_ACTION(RAW_ENCAP,
5454 sizeof(struct action_raw_encap_data)),
5455 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5456 .call = parse_vc_action_mplsoudp_encap,
5458 [ACTION_MPLSOUDP_DECAP] = {
5459 .name = "mplsoudp_decap",
5460 .help = "mplsoudp decapsulation, uses configuration set by"
5461 " \"set mplsoudp_decap\"",
5462 .priv = PRIV_ACTION(RAW_DECAP,
5463 sizeof(struct action_raw_decap_data)),
5464 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5465 .call = parse_vc_action_mplsoudp_decap,
5467 [ACTION_SET_IPV4_SRC] = {
5468 .name = "set_ipv4_src",
5469 .help = "Set a new IPv4 source address in the outermost"
5471 .priv = PRIV_ACTION(SET_IPV4_SRC,
5472 sizeof(struct rte_flow_action_set_ipv4)),
5473 .next = NEXT(action_set_ipv4_src),
5476 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
5477 .name = "ipv4_addr",
5478 .help = "new IPv4 source address to set",
5479 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
5480 .args = ARGS(ARGS_ENTRY_HTON
5481 (struct rte_flow_action_set_ipv4, ipv4_addr)),
5482 .call = parse_vc_conf,
5484 [ACTION_SET_IPV4_DST] = {
5485 .name = "set_ipv4_dst",
5486 .help = "Set a new IPv4 destination address in the outermost"
5488 .priv = PRIV_ACTION(SET_IPV4_DST,
5489 sizeof(struct rte_flow_action_set_ipv4)),
5490 .next = NEXT(action_set_ipv4_dst),
5493 [ACTION_SET_IPV4_DST_IPV4_DST] = {
5494 .name = "ipv4_addr",
5495 .help = "new IPv4 destination address to set",
5496 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
5497 .args = ARGS(ARGS_ENTRY_HTON
5498 (struct rte_flow_action_set_ipv4, ipv4_addr)),
5499 .call = parse_vc_conf,
5501 [ACTION_SET_IPV6_SRC] = {
5502 .name = "set_ipv6_src",
5503 .help = "Set a new IPv6 source address in the outermost"
5505 .priv = PRIV_ACTION(SET_IPV6_SRC,
5506 sizeof(struct rte_flow_action_set_ipv6)),
5507 .next = NEXT(action_set_ipv6_src),
5510 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
5511 .name = "ipv6_addr",
5512 .help = "new IPv6 source address to set",
5513 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
5514 .args = ARGS(ARGS_ENTRY_HTON
5515 (struct rte_flow_action_set_ipv6, ipv6_addr)),
5516 .call = parse_vc_conf,
5518 [ACTION_SET_IPV6_DST] = {
5519 .name = "set_ipv6_dst",
5520 .help = "Set a new IPv6 destination address in the outermost"
5522 .priv = PRIV_ACTION(SET_IPV6_DST,
5523 sizeof(struct rte_flow_action_set_ipv6)),
5524 .next = NEXT(action_set_ipv6_dst),
5527 [ACTION_SET_IPV6_DST_IPV6_DST] = {
5528 .name = "ipv6_addr",
5529 .help = "new IPv6 destination address to set",
5530 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
5531 .args = ARGS(ARGS_ENTRY_HTON
5532 (struct rte_flow_action_set_ipv6, ipv6_addr)),
5533 .call = parse_vc_conf,
5535 [ACTION_SET_TP_SRC] = {
5536 .name = "set_tp_src",
5537 .help = "set a new source port number in the outermost"
5539 .priv = PRIV_ACTION(SET_TP_SRC,
5540 sizeof(struct rte_flow_action_set_tp)),
5541 .next = NEXT(action_set_tp_src),
5544 [ACTION_SET_TP_SRC_TP_SRC] = {
5546 .help = "new source port number to set",
5547 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
5548 .args = ARGS(ARGS_ENTRY_HTON
5549 (struct rte_flow_action_set_tp, port)),
5550 .call = parse_vc_conf,
5552 [ACTION_SET_TP_DST] = {
5553 .name = "set_tp_dst",
5554 .help = "set a new destination port number in the outermost"
5556 .priv = PRIV_ACTION(SET_TP_DST,
5557 sizeof(struct rte_flow_action_set_tp)),
5558 .next = NEXT(action_set_tp_dst),
5561 [ACTION_SET_TP_DST_TP_DST] = {
5563 .help = "new destination port number to set",
5564 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
5565 .args = ARGS(ARGS_ENTRY_HTON
5566 (struct rte_flow_action_set_tp, port)),
5567 .call = parse_vc_conf,
5569 [ACTION_MAC_SWAP] = {
5571 .help = "Swap the source and destination MAC addresses"
5572 " in the outermost Ethernet header",
5573 .priv = PRIV_ACTION(MAC_SWAP, 0),
5574 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5577 [ACTION_DEC_TTL] = {
5579 .help = "decrease network TTL if available",
5580 .priv = PRIV_ACTION(DEC_TTL, 0),
5581 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5584 [ACTION_SET_TTL] = {
5586 .help = "set ttl value",
5587 .priv = PRIV_ACTION(SET_TTL,
5588 sizeof(struct rte_flow_action_set_ttl)),
5589 .next = NEXT(action_set_ttl),
5592 [ACTION_SET_TTL_TTL] = {
5593 .name = "ttl_value",
5594 .help = "new ttl value to set",
5595 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5596 .args = ARGS(ARGS_ENTRY_HTON
5597 (struct rte_flow_action_set_ttl, ttl_value)),
5598 .call = parse_vc_conf,
5600 [ACTION_SET_MAC_SRC] = {
5601 .name = "set_mac_src",
5602 .help = "set source mac address",
5603 .priv = PRIV_ACTION(SET_MAC_SRC,
5604 sizeof(struct rte_flow_action_set_mac)),
5605 .next = NEXT(action_set_mac_src),
5608 [ACTION_SET_MAC_SRC_MAC_SRC] = {
5610 .help = "new source mac address",
5611 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
5612 .args = ARGS(ARGS_ENTRY_HTON
5613 (struct rte_flow_action_set_mac, mac_addr)),
5614 .call = parse_vc_conf,
5616 [ACTION_SET_MAC_DST] = {
5617 .name = "set_mac_dst",
5618 .help = "set destination mac address",
5619 .priv = PRIV_ACTION(SET_MAC_DST,
5620 sizeof(struct rte_flow_action_set_mac)),
5621 .next = NEXT(action_set_mac_dst),
5624 [ACTION_SET_MAC_DST_MAC_DST] = {
5626 .help = "new destination mac address to set",
5627 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
5628 .args = ARGS(ARGS_ENTRY_HTON
5629 (struct rte_flow_action_set_mac, mac_addr)),
5630 .call = parse_vc_conf,
5632 [ACTION_INC_TCP_SEQ] = {
5633 .name = "inc_tcp_seq",
5634 .help = "increase TCP sequence number",
5635 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
5636 .next = NEXT(action_inc_tcp_seq),
5639 [ACTION_INC_TCP_SEQ_VALUE] = {
5641 .help = "the value to increase TCP sequence number by",
5642 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5643 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5644 .call = parse_vc_conf,
5646 [ACTION_DEC_TCP_SEQ] = {
5647 .name = "dec_tcp_seq",
5648 .help = "decrease TCP sequence number",
5649 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
5650 .next = NEXT(action_dec_tcp_seq),
5653 [ACTION_DEC_TCP_SEQ_VALUE] = {
5655 .help = "the value to decrease TCP sequence number by",
5656 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5657 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5658 .call = parse_vc_conf,
5660 [ACTION_INC_TCP_ACK] = {
5661 .name = "inc_tcp_ack",
5662 .help = "increase TCP acknowledgment number",
5663 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
5664 .next = NEXT(action_inc_tcp_ack),
5667 [ACTION_INC_TCP_ACK_VALUE] = {
5669 .help = "the value to increase TCP acknowledgment number by",
5670 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5671 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5672 .call = parse_vc_conf,
5674 [ACTION_DEC_TCP_ACK] = {
5675 .name = "dec_tcp_ack",
5676 .help = "decrease TCP acknowledgment number",
5677 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
5678 .next = NEXT(action_dec_tcp_ack),
5681 [ACTION_DEC_TCP_ACK_VALUE] = {
5683 .help = "the value to decrease TCP acknowledgment number by",
5684 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5685 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5686 .call = parse_vc_conf,
5688 [ACTION_RAW_ENCAP] = {
5689 .name = "raw_encap",
5690 .help = "encapsulation data, defined by set raw_encap",
5691 .priv = PRIV_ACTION(RAW_ENCAP,
5692 sizeof(struct action_raw_encap_data)),
5693 .next = NEXT(action_raw_encap),
5694 .call = parse_vc_action_raw_encap,
5696 [ACTION_RAW_ENCAP_INDEX] = {
5698 .help = "the index of raw_encap_confs",
5699 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
5701 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
5704 .help = "unsigned integer value",
5705 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5706 .call = parse_vc_action_raw_encap_index,
5707 .comp = comp_set_raw_index,
5709 [ACTION_RAW_DECAP] = {
5710 .name = "raw_decap",
5711 .help = "decapsulation data, defined by set raw_encap",
5712 .priv = PRIV_ACTION(RAW_DECAP,
5713 sizeof(struct action_raw_decap_data)),
5714 .next = NEXT(action_raw_decap),
5715 .call = parse_vc_action_raw_decap,
5717 [ACTION_RAW_DECAP_INDEX] = {
5719 .help = "the index of raw_encap_confs",
5720 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
5722 [ACTION_RAW_DECAP_INDEX_VALUE] = {
5725 .help = "unsigned integer value",
5726 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5727 .call = parse_vc_action_raw_decap_index,
5728 .comp = comp_set_raw_index,
5730 [ACTION_MODIFY_FIELD] = {
5731 .name = "modify_field",
5732 .help = "modify destination field with data from source field",
5733 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
5734 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
5737 [ACTION_MODIFY_FIELD_OP] = {
5739 .help = "operation type",
5740 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
5741 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
5742 .call = parse_vc_conf,
5744 [ACTION_MODIFY_FIELD_OP_VALUE] = {
5745 .name = "{operation}",
5746 .help = "operation type value",
5747 .call = parse_vc_modify_field_op,
5748 .comp = comp_set_modify_field_op,
5750 [ACTION_MODIFY_FIELD_DST_TYPE] = {
5752 .help = "destination field type",
5753 .next = NEXT(action_modify_field_dst,
5754 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
5755 .call = parse_vc_conf,
5757 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
5758 .name = "{dst_type}",
5759 .help = "destination field type value",
5760 .call = parse_vc_modify_field_id,
5761 .comp = comp_set_modify_field_id,
5763 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
5764 .name = "dst_level",
5765 .help = "destination field level",
5766 .next = NEXT(action_modify_field_dst,
5767 NEXT_ENTRY(COMMON_UNSIGNED)),
5768 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5770 .call = parse_vc_conf,
5772 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
5773 .name = "dst_offset",
5774 .help = "destination field bit offset",
5775 .next = NEXT(action_modify_field_dst,
5776 NEXT_ENTRY(COMMON_UNSIGNED)),
5777 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5779 .call = parse_vc_conf,
5781 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
5783 .help = "source field type",
5784 .next = NEXT(action_modify_field_src,
5785 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
5786 .call = parse_vc_conf,
5788 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
5789 .name = "{src_type}",
5790 .help = "source field type value",
5791 .call = parse_vc_modify_field_id,
5792 .comp = comp_set_modify_field_id,
5794 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
5795 .name = "src_level",
5796 .help = "source field level",
5797 .next = NEXT(action_modify_field_src,
5798 NEXT_ENTRY(COMMON_UNSIGNED)),
5799 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5801 .call = parse_vc_conf,
5803 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
5804 .name = "src_offset",
5805 .help = "source field bit offset",
5806 .next = NEXT(action_modify_field_src,
5807 NEXT_ENTRY(COMMON_UNSIGNED)),
5808 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5810 .call = parse_vc_conf,
5812 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
5813 .name = "src_value",
5814 .help = "source immediate value",
5815 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5816 NEXT_ENTRY(COMMON_HEX)),
5817 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
5818 ARGS_ENTRY_ARB(0, 0),
5819 ARGS_ENTRY(struct rte_flow_action_modify_field,
5821 .call = parse_vc_conf,
5823 [ACTION_MODIFY_FIELD_SRC_POINTER] = {
5825 .help = "pointer to source immediate value",
5826 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5827 NEXT_ENTRY(COMMON_HEX)),
5828 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5830 ARGS_ENTRY_ARB(0, 0),
5832 (sizeof(struct rte_flow_action_modify_field),
5833 ACTION_MODIFY_PATTERN_SIZE)),
5834 .call = parse_vc_conf,
5836 [ACTION_MODIFY_FIELD_WIDTH] = {
5838 .help = "number of bits to copy",
5839 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5840 NEXT_ENTRY(COMMON_UNSIGNED)),
5841 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5843 .call = parse_vc_conf,
5845 /* Top level command. */
5848 .help = "set raw encap/decap/sample data",
5849 .type = "set raw_encap|raw_decap <index> <pattern>"
5850 " or set sample_actions <index> <action>",
5851 .next = NEXT(NEXT_ENTRY
5854 SET_SAMPLE_ACTIONS)),
5855 .call = parse_set_init,
5857 /* Sub-level commands. */
5859 .name = "raw_encap",
5860 .help = "set raw encap data",
5861 .next = NEXT(next_set_raw),
5862 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5863 (offsetof(struct buffer, port),
5864 sizeof(((struct buffer *)0)->port),
5865 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5866 .call = parse_set_raw_encap_decap,
5869 .name = "raw_decap",
5870 .help = "set raw decap data",
5871 .next = NEXT(next_set_raw),
5872 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5873 (offsetof(struct buffer, port),
5874 sizeof(((struct buffer *)0)->port),
5875 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5876 .call = parse_set_raw_encap_decap,
5880 .type = "COMMON_UNSIGNED",
5881 .help = "index of raw_encap/raw_decap data",
5882 .next = NEXT(next_item),
5885 [SET_SAMPLE_INDEX] = {
5888 .help = "index of sample actions",
5889 .next = NEXT(next_action_sample),
5892 [SET_SAMPLE_ACTIONS] = {
5893 .name = "sample_actions",
5894 .help = "set sample actions list",
5895 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
5896 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5897 (offsetof(struct buffer, port),
5898 sizeof(((struct buffer *)0)->port),
5899 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
5900 .call = parse_set_sample_action,
5902 [ACTION_SET_TAG] = {
5905 .priv = PRIV_ACTION(SET_TAG,
5906 sizeof(struct rte_flow_action_set_tag)),
5907 .next = NEXT(action_set_tag),
5910 [ACTION_SET_TAG_INDEX] = {
5912 .help = "index of tag array",
5913 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5914 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
5915 .call = parse_vc_conf,
5917 [ACTION_SET_TAG_DATA] = {
5919 .help = "tag value",
5920 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5921 .args = ARGS(ARGS_ENTRY
5922 (struct rte_flow_action_set_tag, data)),
5923 .call = parse_vc_conf,
5925 [ACTION_SET_TAG_MASK] = {
5927 .help = "mask for tag value",
5928 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5929 .args = ARGS(ARGS_ENTRY
5930 (struct rte_flow_action_set_tag, mask)),
5931 .call = parse_vc_conf,
5933 [ACTION_SET_META] = {
5935 .help = "set metadata",
5936 .priv = PRIV_ACTION(SET_META,
5937 sizeof(struct rte_flow_action_set_meta)),
5938 .next = NEXT(action_set_meta),
5939 .call = parse_vc_action_set_meta,
5941 [ACTION_SET_META_DATA] = {
5943 .help = "metadata value",
5944 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5945 .args = ARGS(ARGS_ENTRY
5946 (struct rte_flow_action_set_meta, data)),
5947 .call = parse_vc_conf,
5949 [ACTION_SET_META_MASK] = {
5951 .help = "mask for metadata value",
5952 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5953 .args = ARGS(ARGS_ENTRY
5954 (struct rte_flow_action_set_meta, mask)),
5955 .call = parse_vc_conf,
5957 [ACTION_SET_IPV4_DSCP] = {
5958 .name = "set_ipv4_dscp",
5959 .help = "set DSCP value",
5960 .priv = PRIV_ACTION(SET_IPV4_DSCP,
5961 sizeof(struct rte_flow_action_set_dscp)),
5962 .next = NEXT(action_set_ipv4_dscp),
5965 [ACTION_SET_IPV4_DSCP_VALUE] = {
5966 .name = "dscp_value",
5967 .help = "new IPv4 DSCP value to set",
5968 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5969 .args = ARGS(ARGS_ENTRY
5970 (struct rte_flow_action_set_dscp, dscp)),
5971 .call = parse_vc_conf,
5973 [ACTION_SET_IPV6_DSCP] = {
5974 .name = "set_ipv6_dscp",
5975 .help = "set DSCP value",
5976 .priv = PRIV_ACTION(SET_IPV6_DSCP,
5977 sizeof(struct rte_flow_action_set_dscp)),
5978 .next = NEXT(action_set_ipv6_dscp),
5981 [ACTION_SET_IPV6_DSCP_VALUE] = {
5982 .name = "dscp_value",
5983 .help = "new IPv6 DSCP value to set",
5984 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5985 .args = ARGS(ARGS_ENTRY
5986 (struct rte_flow_action_set_dscp, dscp)),
5987 .call = parse_vc_conf,
5991 .help = "set a specific metadata header",
5992 .next = NEXT(action_age),
5993 .priv = PRIV_ACTION(AGE,
5994 sizeof(struct rte_flow_action_age)),
5997 [ACTION_AGE_TIMEOUT] = {
5999 .help = "flow age timeout value",
6000 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
6002 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
6003 .call = parse_vc_conf,
6007 .help = "set a sample action",
6008 .next = NEXT(action_sample),
6009 .priv = PRIV_ACTION(SAMPLE,
6010 sizeof(struct action_sample_data)),
6011 .call = parse_vc_action_sample,
6013 [ACTION_SAMPLE_RATIO] = {
6015 .help = "flow sample ratio value",
6016 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
6017 .args = ARGS(ARGS_ENTRY_ARB
6018 (offsetof(struct action_sample_data, conf) +
6019 offsetof(struct rte_flow_action_sample, ratio),
6020 sizeof(((struct rte_flow_action_sample *)0)->
6023 [ACTION_SAMPLE_INDEX] = {
6025 .help = "the index of sample actions list",
6026 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
6028 [ACTION_SAMPLE_INDEX_VALUE] = {
6030 .type = "COMMON_UNSIGNED",
6031 .help = "unsigned integer value",
6032 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6033 .call = parse_vc_action_sample_index,
6034 .comp = comp_set_sample_index,
6036 [ACTION_CONNTRACK] = {
6037 .name = "conntrack",
6038 .help = "create a conntrack object",
6039 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6040 .priv = PRIV_ACTION(CONNTRACK,
6041 sizeof(struct rte_flow_action_conntrack)),
6044 [ACTION_CONNTRACK_UPDATE] = {
6045 .name = "conntrack_update",
6046 .help = "update a conntrack object",
6047 .next = NEXT(action_update_conntrack),
6048 .priv = PRIV_ACTION(CONNTRACK,
6049 sizeof(struct rte_flow_modify_conntrack)),
6052 [ACTION_CONNTRACK_UPDATE_DIR] = {
6054 .help = "update a conntrack object direction",
6055 .next = NEXT(action_update_conntrack),
6056 .call = parse_vc_action_conntrack_update,
6058 [ACTION_CONNTRACK_UPDATE_CTX] = {
6060 .help = "update a conntrack object context",
6061 .next = NEXT(action_update_conntrack),
6062 .call = parse_vc_action_conntrack_update,
6064 [ACTION_PORT_REPRESENTOR] = {
6065 .name = "port_representor",
6066 .help = "at embedded switch level, send matching traffic to the given ethdev",
6067 .priv = PRIV_ACTION(PORT_REPRESENTOR,
6068 sizeof(struct rte_flow_action_ethdev)),
6069 .next = NEXT(action_port_representor),
6072 [ACTION_PORT_REPRESENTOR_PORT_ID] = {
6074 .help = "ethdev port ID",
6075 .next = NEXT(action_port_representor,
6076 NEXT_ENTRY(COMMON_UNSIGNED)),
6077 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6079 .call = parse_vc_conf,
6081 [ACTION_REPRESENTED_PORT] = {
6082 .name = "represented_port",
6083 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
6084 .priv = PRIV_ACTION(REPRESENTED_PORT,
6085 sizeof(struct rte_flow_action_ethdev)),
6086 .next = NEXT(action_represented_port),
6089 [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
6090 .name = "ethdev_port_id",
6091 .help = "ethdev port ID",
6092 .next = NEXT(action_represented_port,
6093 NEXT_ENTRY(COMMON_UNSIGNED)),
6094 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6096 .call = parse_vc_conf,
6098 /* Indirect action destroy arguments. */
6099 [INDIRECT_ACTION_DESTROY_ID] = {
6100 .name = "action_id",
6101 .help = "specify a indirect action id to destroy",
6102 .next = NEXT(next_ia_destroy_attr,
6103 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6104 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
6105 args.ia_destroy.action_id)),
6106 .call = parse_ia_destroy,
6108 /* Indirect action create arguments. */
6109 [INDIRECT_ACTION_CREATE_ID] = {
6110 .name = "action_id",
6111 .help = "specify a indirect action id to create",
6112 .next = NEXT(next_ia_create_attr,
6113 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6114 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
6116 [ACTION_INDIRECT] = {
6118 .help = "apply indirect action by id",
6119 .priv = PRIV_ACTION(INDIRECT, 0),
6120 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
6121 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6124 [INDIRECT_ACTION_ID2PTR] = {
6125 .name = "{action_id}",
6126 .type = "INDIRECT_ACTION_ID",
6127 .help = "indirect action id",
6128 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6129 .call = parse_ia_id2ptr,
6132 [INDIRECT_ACTION_INGRESS] = {
6134 .help = "affect rule to ingress",
6135 .next = NEXT(next_ia_create_attr),
6138 [INDIRECT_ACTION_EGRESS] = {
6140 .help = "affect rule to egress",
6141 .next = NEXT(next_ia_create_attr),
6144 [INDIRECT_ACTION_TRANSFER] = {
6146 .help = "affect rule to transfer",
6147 .next = NEXT(next_ia_create_attr),
6150 [INDIRECT_ACTION_SPEC] = {
6152 .help = "specify action to create indirect handle",
6153 .next = NEXT(next_action),
6156 .name = "g_actions",
6157 .help = "submit a list of associated actions for green",
6158 .next = NEXT(next_action),
6162 .name = "y_actions",
6163 .help = "submit a list of associated actions for yellow",
6164 .next = NEXT(next_action),
6167 .name = "r_actions",
6168 .help = "submit a list of associated actions for red",
6169 .next = NEXT(next_action),
6172 /* Top-level command. */
6175 .type = "port meter policy {port_id} {arg}",
6176 .help = "add port meter policy",
6177 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
6180 /* Sub-level commands. */
6183 .help = "add port meter policy",
6184 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
6186 [ITEM_POL_METER] = {
6188 .help = "add port meter policy",
6189 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
6191 [ITEM_POL_POLICY] = {
6193 .help = "add port meter policy",
6194 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
6195 NEXT_ENTRY(ACTION_POL_Y),
6196 NEXT_ENTRY(ACTION_POL_G),
6197 NEXT_ENTRY(COMMON_POLICY_ID),
6198 NEXT_ENTRY(COMMON_PORT_ID)),
6199 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
6200 ARGS_ENTRY(struct buffer, port)),
6205 /** Remove and return last entry from argument stack. */
6206 static const struct arg *
6207 pop_args(struct context *ctx)
6209 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
6212 /** Add entry on top of the argument stack. */
6214 push_args(struct context *ctx, const struct arg *arg)
6216 if (ctx->args_num == CTX_STACK_SIZE)
6218 ctx->args[ctx->args_num++] = arg;
6222 /** Spread value into buffer according to bit-mask. */
6224 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
6226 uint32_t i = arg->size;
6234 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6243 unsigned int shift = 0;
6244 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
6246 for (shift = 0; arg->mask[i] >> shift; ++shift) {
6247 if (!(arg->mask[i] & (1 << shift)))
6252 *buf &= ~(1 << shift);
6253 *buf |= (val & 1) << shift;
6261 /** Compare a string with a partial one of a given length. */
6263 strcmp_partial(const char *full, const char *partial, size_t partial_len)
6265 int r = strncmp(full, partial, partial_len);
6269 if (strlen(full) <= partial_len)
6271 return full[partial_len];
6275 * Parse a prefix length and generate a bit-mask.
6277 * Last argument (ctx->args) is retrieved to determine mask size, storage
6278 * location and whether the result must use network byte ordering.
6281 parse_prefix(struct context *ctx, const struct token *token,
6282 const char *str, unsigned int len,
6283 void *buf, unsigned int size)
6285 const struct arg *arg = pop_args(ctx);
6286 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
6293 /* Argument is expected. */
6297 u = strtoumax(str, &end, 0);
6298 if (errno || (size_t)(end - str) != len)
6303 extra = arg_entry_bf_fill(NULL, 0, arg);
6312 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
6313 !arg_entry_bf_fill(ctx->objmask, -1, arg))
6320 if (bytes > size || bytes + !!extra > size)
6324 buf = (uint8_t *)ctx->object + arg->offset;
6325 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6327 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
6328 memset(buf, 0x00, size - bytes);
6330 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
6334 memset(buf, 0xff, bytes);
6335 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
6337 ((uint8_t *)buf)[bytes] = conv[extra];
6340 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
6343 push_args(ctx, arg);
6347 /** Default parsing function for token name matching. */
6349 parse_default(struct context *ctx, const struct token *token,
6350 const char *str, unsigned int len,
6351 void *buf, unsigned int size)
6356 if (strcmp_partial(token->name, str, len))
6361 /** Parse flow command, initialize output buffer for subsequent tokens. */
6363 parse_init(struct context *ctx, const struct token *token,
6364 const char *str, unsigned int len,
6365 void *buf, unsigned int size)
6367 struct buffer *out = buf;
6369 /* Token name must match. */
6370 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6372 /* Nothing else to do if there is no buffer. */
6375 /* Make sure buffer is large enough. */
6376 if (size < sizeof(*out))
6378 /* Initialize buffer. */
6379 memset(out, 0x00, sizeof(*out));
6380 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
6383 ctx->objmask = NULL;
6387 /** Parse tokens for indirect action commands. */
6389 parse_ia(struct context *ctx, const struct token *token,
6390 const char *str, unsigned int len,
6391 void *buf, unsigned int size)
6393 struct buffer *out = buf;
6395 /* Token name must match. */
6396 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6398 /* Nothing else to do if there is no buffer. */
6401 if (!out->command) {
6402 if (ctx->curr != INDIRECT_ACTION)
6404 if (sizeof(*out) > size)
6406 out->command = ctx->curr;
6409 ctx->objmask = NULL;
6410 out->args.vc.data = (uint8_t *)out + size;
6413 switch (ctx->curr) {
6414 case INDIRECT_ACTION_CREATE:
6415 case INDIRECT_ACTION_UPDATE:
6416 out->args.vc.actions =
6417 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6419 out->args.vc.attr.group = UINT32_MAX;
6421 case INDIRECT_ACTION_QUERY:
6422 out->command = ctx->curr;
6425 ctx->objmask = NULL;
6427 case INDIRECT_ACTION_EGRESS:
6428 out->args.vc.attr.egress = 1;
6430 case INDIRECT_ACTION_INGRESS:
6431 out->args.vc.attr.ingress = 1;
6433 case INDIRECT_ACTION_TRANSFER:
6434 out->args.vc.attr.transfer = 1;
6442 /** Parse tokens for indirect action destroy command. */
6444 parse_ia_destroy(struct context *ctx, const struct token *token,
6445 const char *str, unsigned int len,
6446 void *buf, unsigned int size)
6448 struct buffer *out = buf;
6449 uint32_t *action_id;
6451 /* Token name must match. */
6452 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6454 /* Nothing else to do if there is no buffer. */
6457 if (!out->command || out->command == INDIRECT_ACTION) {
6458 if (ctx->curr != INDIRECT_ACTION_DESTROY)
6460 if (sizeof(*out) > size)
6462 out->command = ctx->curr;
6465 ctx->objmask = NULL;
6466 out->args.ia_destroy.action_id =
6467 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6471 action_id = out->args.ia_destroy.action_id
6472 + out->args.ia_destroy.action_id_n++;
6473 if ((uint8_t *)action_id > (uint8_t *)out + size)
6476 ctx->object = action_id;
6477 ctx->objmask = NULL;
6481 /** Parse tokens for meter policy action commands. */
6483 parse_mp(struct context *ctx, const struct token *token,
6484 const char *str, unsigned int len,
6485 void *buf, unsigned int size)
6487 struct buffer *out = buf;
6489 /* Token name must match. */
6490 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6492 /* Nothing else to do if there is no buffer. */
6495 if (!out->command) {
6496 if (ctx->curr != ITEM_POL_POLICY)
6498 if (sizeof(*out) > size)
6500 out->command = ctx->curr;
6503 ctx->objmask = NULL;
6504 out->args.vc.data = (uint8_t *)out + size;
6507 switch (ctx->curr) {
6509 out->args.vc.actions =
6510 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6512 out->command = ctx->curr;
6515 ctx->objmask = NULL;
6522 /** Parse tokens for validate/create commands. */
6524 parse_vc(struct context *ctx, const struct token *token,
6525 const char *str, unsigned int len,
6526 void *buf, unsigned int size)
6528 struct buffer *out = buf;
6532 /* Token name must match. */
6533 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6535 /* Nothing else to do if there is no buffer. */
6538 if (!out->command) {
6539 if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
6540 ctx->curr != PATTERN_TEMPLATE_CREATE &&
6541 ctx->curr != ACTIONS_TEMPLATE_CREATE)
6543 if (sizeof(*out) > size)
6545 out->command = ctx->curr;
6548 ctx->objmask = NULL;
6549 out->args.vc.data = (uint8_t *)out + size;
6553 switch (ctx->curr) {
6555 ctx->object = &out->args.vc.attr;
6558 case VC_TUNNEL_MATCH:
6559 ctx->object = &out->args.vc.tunnel_ops;
6562 ctx->objmask = NULL;
6563 switch (ctx->curr) {
6568 out->args.vc.tunnel_ops.enabled = 1;
6569 out->args.vc.tunnel_ops.actions = 1;
6571 case VC_TUNNEL_MATCH:
6572 out->args.vc.tunnel_ops.enabled = 1;
6573 out->args.vc.tunnel_ops.items = 1;
6576 out->args.vc.attr.ingress = 1;
6579 out->args.vc.attr.egress = 1;
6582 out->args.vc.attr.transfer = 1;
6585 out->args.vc.pattern =
6586 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6588 ctx->object = out->args.vc.pattern;
6589 ctx->objmask = NULL;
6592 out->args.vc.actions =
6593 (void *)RTE_ALIGN_CEIL((uintptr_t)
6594 (out->args.vc.pattern +
6595 out->args.vc.pattern_n),
6597 ctx->object = out->args.vc.actions;
6598 ctx->objmask = NULL;
6605 if (!out->args.vc.actions) {
6606 const struct parse_item_priv *priv = token->priv;
6607 struct rte_flow_item *item =
6608 out->args.vc.pattern + out->args.vc.pattern_n;
6610 data_size = priv->size * 3; /* spec, last, mask */
6611 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6612 (out->args.vc.data - data_size),
6614 if ((uint8_t *)item + sizeof(*item) > data)
6616 *item = (struct rte_flow_item){
6619 ++out->args.vc.pattern_n;
6621 ctx->objmask = NULL;
6623 const struct parse_action_priv *priv = token->priv;
6624 struct rte_flow_action *action =
6625 out->args.vc.actions + out->args.vc.actions_n;
6627 data_size = priv->size; /* configuration */
6628 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6629 (out->args.vc.data - data_size),
6631 if ((uint8_t *)action + sizeof(*action) > data)
6633 *action = (struct rte_flow_action){
6635 .conf = data_size ? data : NULL,
6637 ++out->args.vc.actions_n;
6638 ctx->object = action;
6639 ctx->objmask = NULL;
6641 memset(data, 0, data_size);
6642 out->args.vc.data = data;
6643 ctx->objdata = data_size;
6647 /** Parse pattern item parameter type. */
6649 parse_vc_spec(struct context *ctx, const struct token *token,
6650 const char *str, unsigned int len,
6651 void *buf, unsigned int size)
6653 struct buffer *out = buf;
6654 struct rte_flow_item *item;
6660 /* Token name must match. */
6661 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6663 /* Parse parameter types. */
6664 switch (ctx->curr) {
6665 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
6671 case ITEM_PARAM_SPEC:
6674 case ITEM_PARAM_LAST:
6677 case ITEM_PARAM_PREFIX:
6678 /* Modify next token to expect a prefix. */
6679 if (ctx->next_num < 2)
6681 ctx->next[ctx->next_num - 2] = prefix;
6683 case ITEM_PARAM_MASK:
6689 /* Nothing else to do if there is no buffer. */
6692 if (!out->args.vc.pattern_n)
6694 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6695 data_size = ctx->objdata / 3; /* spec, last, mask */
6696 /* Point to selected object. */
6697 ctx->object = out->args.vc.data + (data_size * index);
6699 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
6700 item->mask = ctx->objmask;
6702 ctx->objmask = NULL;
6703 /* Update relevant item pointer. */
6704 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
6709 /** Parse action configuration field. */
6711 parse_vc_conf(struct context *ctx, const struct token *token,
6712 const char *str, unsigned int len,
6713 void *buf, unsigned int size)
6715 struct buffer *out = buf;
6718 /* Token name must match. */
6719 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6721 /* Nothing else to do if there is no buffer. */
6724 /* Point to selected object. */
6725 ctx->object = out->args.vc.data;
6726 ctx->objmask = NULL;
6730 /** Parse eCPRI common header type field. */
6732 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
6733 const char *str, unsigned int len,
6734 void *buf, unsigned int size)
6736 struct rte_flow_item_ecpri *ecpri;
6737 struct rte_flow_item_ecpri *ecpri_mask;
6738 struct rte_flow_item *item;
6741 struct buffer *out = buf;
6742 const struct arg *arg;
6745 /* Token name must match. */
6746 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6748 switch (ctx->curr) {
6749 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
6750 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
6752 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
6753 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
6755 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
6756 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
6763 arg = pop_args(ctx);
6766 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
6767 ecpri->hdr.common.type = msg_type;
6768 data_size = ctx->objdata / 3; /* spec, last, mask */
6769 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
6771 ecpri_mask->hdr.common.type = 0xFF;
6773 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
6774 ecpri_mask->hdr.common.u32 =
6775 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
6777 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6779 item->mask = ecpri_mask;
6783 /** Parse L2TPv2 common header type field. */
6785 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
6786 const char *str, unsigned int len,
6787 void *buf, unsigned int size)
6789 struct rte_flow_item_l2tpv2 *l2tpv2;
6790 struct rte_flow_item_l2tpv2 *l2tpv2_mask;
6791 struct rte_flow_item *item;
6793 uint16_t msg_type = 0;
6794 struct buffer *out = buf;
6795 const struct arg *arg;
6798 /* Token name must match. */
6799 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6801 switch (ctx->curr) {
6802 case ITEM_L2TPV2_TYPE_DATA:
6803 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
6805 case ITEM_L2TPV2_TYPE_DATA_L:
6806 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
6808 case ITEM_L2TPV2_TYPE_DATA_S:
6809 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
6811 case ITEM_L2TPV2_TYPE_DATA_O:
6812 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
6814 case ITEM_L2TPV2_TYPE_DATA_L_S:
6815 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
6817 case ITEM_L2TPV2_TYPE_CTRL:
6818 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
6825 arg = pop_args(ctx);
6828 l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
6829 l2tpv2->hdr.common.flags_version |= msg_type;
6830 data_size = ctx->objdata / 3; /* spec, last, mask */
6831 l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
6833 l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
6835 l2tpv2->hdr.common.flags_version =
6836 rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
6837 l2tpv2_mask->hdr.common.flags_version =
6838 rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
6840 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6841 item->spec = l2tpv2;
6842 item->mask = l2tpv2_mask;
6846 /** Parse meter color action type. */
6848 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
6849 const char *str, unsigned int len,
6850 void *buf, unsigned int size)
6852 struct rte_flow_action *action_data;
6853 struct rte_flow_action_meter_color *conf;
6854 enum rte_color color;
6858 /* Token name must match. */
6859 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6861 switch (ctx->curr) {
6862 case ACTION_METER_COLOR_GREEN:
6863 color = RTE_COLOR_GREEN;
6865 case ACTION_METER_COLOR_YELLOW:
6866 color = RTE_COLOR_YELLOW;
6868 case ACTION_METER_COLOR_RED:
6869 color = RTE_COLOR_RED;
6877 action_data = ctx->object;
6878 conf = (struct rte_flow_action_meter_color *)
6879 (uintptr_t)(action_data->conf);
6880 conf->color = color;
6884 /** Parse RSS action. */
6886 parse_vc_action_rss(struct context *ctx, const struct token *token,
6887 const char *str, unsigned int len,
6888 void *buf, unsigned int size)
6890 struct buffer *out = buf;
6891 struct rte_flow_action *action;
6892 struct action_rss_data *action_rss_data;
6896 ret = parse_vc(ctx, token, str, len, buf, size);
6899 /* Nothing else to do if there is no buffer. */
6902 if (!out->args.vc.actions_n)
6904 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6905 /* Point to selected object. */
6906 ctx->object = out->args.vc.data;
6907 ctx->objmask = NULL;
6908 /* Set up default configuration. */
6909 action_rss_data = ctx->object;
6910 *action_rss_data = (struct action_rss_data){
6911 .conf = (struct rte_flow_action_rss){
6912 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
6916 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
6918 .queue = action_rss_data->queue,
6922 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
6923 action_rss_data->queue[i] = i;
6924 action->conf = &action_rss_data->conf;
6929 * Parse func field for RSS action.
6931 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
6932 * ACTION_RSS_FUNC_* index that called this function.
6935 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
6936 const char *str, unsigned int len,
6937 void *buf, unsigned int size)
6939 struct action_rss_data *action_rss_data;
6940 enum rte_eth_hash_function func;
6944 /* Token name must match. */
6945 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6947 switch (ctx->curr) {
6948 case ACTION_RSS_FUNC_DEFAULT:
6949 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
6951 case ACTION_RSS_FUNC_TOEPLITZ:
6952 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
6954 case ACTION_RSS_FUNC_SIMPLE_XOR:
6955 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
6957 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
6958 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
6965 action_rss_data = ctx->object;
6966 action_rss_data->conf.func = func;
6971 * Parse type field for RSS action.
6973 * Valid tokens are type field names and the "end" token.
6976 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
6977 const char *str, unsigned int len,
6978 void *buf, unsigned int size)
6980 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
6981 struct action_rss_data *action_rss_data;
6987 if (ctx->curr != ACTION_RSS_TYPE)
6989 if (!(ctx->objdata >> 16) && ctx->object) {
6990 action_rss_data = ctx->object;
6991 action_rss_data->conf.types = 0;
6993 if (!strcmp_partial("end", str, len)) {
6994 ctx->objdata &= 0xffff;
6997 for (i = 0; rss_type_table[i].str; ++i)
6998 if (!strcmp_partial(rss_type_table[i].str, str, len))
7000 if (!rss_type_table[i].str)
7002 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
7004 if (ctx->next_num == RTE_DIM(ctx->next))
7006 ctx->next[ctx->next_num++] = next;
7009 action_rss_data = ctx->object;
7010 action_rss_data->conf.types |= rss_type_table[i].rss_type;
7015 * Parse queue field for RSS action.
7017 * Valid tokens are queue indices and the "end" token.
7020 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
7021 const char *str, unsigned int len,
7022 void *buf, unsigned int size)
7024 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
7025 struct action_rss_data *action_rss_data;
7026 const struct arg *arg;
7033 if (ctx->curr != ACTION_RSS_QUEUE)
7035 i = ctx->objdata >> 16;
7036 if (!strcmp_partial("end", str, len)) {
7037 ctx->objdata &= 0xffff;
7040 if (i >= ACTION_RSS_QUEUE_NUM)
7042 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
7043 i * sizeof(action_rss_data->queue[i]),
7044 sizeof(action_rss_data->queue[i]));
7045 if (push_args(ctx, arg))
7047 ret = parse_int(ctx, token, str, len, NULL, 0);
7053 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
7055 if (ctx->next_num == RTE_DIM(ctx->next))
7057 ctx->next[ctx->next_num++] = next;
7061 action_rss_data = ctx->object;
7062 action_rss_data->conf.queue_num = i;
7063 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
7067 /** Setup VXLAN encap configuration. */
7069 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
7071 /* Set up default configuration. */
7072 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
7073 .conf = (struct rte_flow_action_vxlan_encap){
7074 .definition = action_vxlan_encap_data->items,
7078 .type = RTE_FLOW_ITEM_TYPE_ETH,
7079 .spec = &action_vxlan_encap_data->item_eth,
7080 .mask = &rte_flow_item_eth_mask,
7083 .type = RTE_FLOW_ITEM_TYPE_VLAN,
7084 .spec = &action_vxlan_encap_data->item_vlan,
7085 .mask = &rte_flow_item_vlan_mask,
7088 .type = RTE_FLOW_ITEM_TYPE_IPV4,
7089 .spec = &action_vxlan_encap_data->item_ipv4,
7090 .mask = &rte_flow_item_ipv4_mask,
7093 .type = RTE_FLOW_ITEM_TYPE_UDP,
7094 .spec = &action_vxlan_encap_data->item_udp,
7095 .mask = &rte_flow_item_udp_mask,
7098 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
7099 .spec = &action_vxlan_encap_data->item_vxlan,
7100 .mask = &rte_flow_item_vxlan_mask,
7103 .type = RTE_FLOW_ITEM_TYPE_END,
7108 .tci = vxlan_encap_conf.vlan_tci,
7112 .src_addr = vxlan_encap_conf.ipv4_src,
7113 .dst_addr = vxlan_encap_conf.ipv4_dst,
7116 .src_port = vxlan_encap_conf.udp_src,
7117 .dst_port = vxlan_encap_conf.udp_dst,
7119 .item_vxlan.flags = 0,
7121 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
7122 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7123 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
7124 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7125 if (!vxlan_encap_conf.select_ipv4) {
7126 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
7127 &vxlan_encap_conf.ipv6_src,
7128 sizeof(vxlan_encap_conf.ipv6_src));
7129 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
7130 &vxlan_encap_conf.ipv6_dst,
7131 sizeof(vxlan_encap_conf.ipv6_dst));
7132 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
7133 .type = RTE_FLOW_ITEM_TYPE_IPV6,
7134 .spec = &action_vxlan_encap_data->item_ipv6,
7135 .mask = &rte_flow_item_ipv6_mask,
7138 if (!vxlan_encap_conf.select_vlan)
7139 action_vxlan_encap_data->items[1].type =
7140 RTE_FLOW_ITEM_TYPE_VOID;
7141 if (vxlan_encap_conf.select_tos_ttl) {
7142 if (vxlan_encap_conf.select_ipv4) {
7143 static struct rte_flow_item_ipv4 ipv4_mask_tos;
7145 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
7146 sizeof(ipv4_mask_tos));
7147 ipv4_mask_tos.hdr.type_of_service = 0xff;
7148 ipv4_mask_tos.hdr.time_to_live = 0xff;
7149 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
7150 vxlan_encap_conf.ip_tos;
7151 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
7152 vxlan_encap_conf.ip_ttl;
7153 action_vxlan_encap_data->items[2].mask =
7156 static struct rte_flow_item_ipv6 ipv6_mask_tos;
7158 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
7159 sizeof(ipv6_mask_tos));
7160 ipv6_mask_tos.hdr.vtc_flow |=
7161 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
7162 ipv6_mask_tos.hdr.hop_limits = 0xff;
7163 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
7165 ((uint32_t)vxlan_encap_conf.ip_tos <<
7166 RTE_IPV6_HDR_TC_SHIFT);
7167 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
7168 vxlan_encap_conf.ip_ttl;
7169 action_vxlan_encap_data->items[2].mask =
7173 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
7174 RTE_DIM(vxlan_encap_conf.vni));
7178 /** Parse VXLAN encap action. */
7180 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
7181 const char *str, unsigned int len,
7182 void *buf, unsigned int size)
7184 struct buffer *out = buf;
7185 struct rte_flow_action *action;
7186 struct action_vxlan_encap_data *action_vxlan_encap_data;
7189 ret = parse_vc(ctx, token, str, len, buf, size);
7192 /* Nothing else to do if there is no buffer. */
7195 if (!out->args.vc.actions_n)
7197 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7198 /* Point to selected object. */
7199 ctx->object = out->args.vc.data;
7200 ctx->objmask = NULL;
7201 action_vxlan_encap_data = ctx->object;
7202 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
7203 action->conf = &action_vxlan_encap_data->conf;
7207 /** Setup NVGRE encap configuration. */
7209 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
7211 /* Set up default configuration. */
7212 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
7213 .conf = (struct rte_flow_action_nvgre_encap){
7214 .definition = action_nvgre_encap_data->items,
7218 .type = RTE_FLOW_ITEM_TYPE_ETH,
7219 .spec = &action_nvgre_encap_data->item_eth,
7220 .mask = &rte_flow_item_eth_mask,
7223 .type = RTE_FLOW_ITEM_TYPE_VLAN,
7224 .spec = &action_nvgre_encap_data->item_vlan,
7225 .mask = &rte_flow_item_vlan_mask,
7228 .type = RTE_FLOW_ITEM_TYPE_IPV4,
7229 .spec = &action_nvgre_encap_data->item_ipv4,
7230 .mask = &rte_flow_item_ipv4_mask,
7233 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
7234 .spec = &action_nvgre_encap_data->item_nvgre,
7235 .mask = &rte_flow_item_nvgre_mask,
7238 .type = RTE_FLOW_ITEM_TYPE_END,
7243 .tci = nvgre_encap_conf.vlan_tci,
7247 .src_addr = nvgre_encap_conf.ipv4_src,
7248 .dst_addr = nvgre_encap_conf.ipv4_dst,
7250 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
7251 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
7252 .item_nvgre.flow_id = 0,
7254 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
7255 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7256 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
7257 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7258 if (!nvgre_encap_conf.select_ipv4) {
7259 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
7260 &nvgre_encap_conf.ipv6_src,
7261 sizeof(nvgre_encap_conf.ipv6_src));
7262 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
7263 &nvgre_encap_conf.ipv6_dst,
7264 sizeof(nvgre_encap_conf.ipv6_dst));
7265 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
7266 .type = RTE_FLOW_ITEM_TYPE_IPV6,
7267 .spec = &action_nvgre_encap_data->item_ipv6,
7268 .mask = &rte_flow_item_ipv6_mask,
7271 if (!nvgre_encap_conf.select_vlan)
7272 action_nvgre_encap_data->items[1].type =
7273 RTE_FLOW_ITEM_TYPE_VOID;
7274 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
7275 RTE_DIM(nvgre_encap_conf.tni));
7279 /** Parse NVGRE encap action. */
7281 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
7282 const char *str, unsigned int len,
7283 void *buf, unsigned int size)
7285 struct buffer *out = buf;
7286 struct rte_flow_action *action;
7287 struct action_nvgre_encap_data *action_nvgre_encap_data;
7290 ret = parse_vc(ctx, token, str, len, buf, size);
7293 /* Nothing else to do if there is no buffer. */
7296 if (!out->args.vc.actions_n)
7298 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7299 /* Point to selected object. */
7300 ctx->object = out->args.vc.data;
7301 ctx->objmask = NULL;
7302 action_nvgre_encap_data = ctx->object;
7303 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
7304 action->conf = &action_nvgre_encap_data->conf;
7308 /** Parse l2 encap action. */
7310 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
7311 const char *str, unsigned int len,
7312 void *buf, unsigned int size)
7314 struct buffer *out = buf;
7315 struct rte_flow_action *action;
7316 struct action_raw_encap_data *action_encap_data;
7317 struct rte_flow_item_eth eth = { .type = 0, };
7318 struct rte_flow_item_vlan vlan = {
7319 .tci = mplsoudp_encap_conf.vlan_tci,
7325 ret = parse_vc(ctx, token, str, len, buf, size);
7328 /* Nothing else to do if there is no buffer. */
7331 if (!out->args.vc.actions_n)
7333 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7334 /* Point to selected object. */
7335 ctx->object = out->args.vc.data;
7336 ctx->objmask = NULL;
7337 /* Copy the headers to the buffer. */
7338 action_encap_data = ctx->object;
7339 *action_encap_data = (struct action_raw_encap_data) {
7340 .conf = (struct rte_flow_action_raw_encap){
7341 .data = action_encap_data->data,
7345 header = action_encap_data->data;
7346 if (l2_encap_conf.select_vlan)
7347 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7348 else if (l2_encap_conf.select_ipv4)
7349 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7351 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7352 memcpy(eth.dst.addr_bytes,
7353 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7354 memcpy(eth.src.addr_bytes,
7355 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7356 memcpy(header, ð, sizeof(eth));
7357 header += sizeof(eth);
7358 if (l2_encap_conf.select_vlan) {
7359 if (l2_encap_conf.select_ipv4)
7360 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7362 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7363 memcpy(header, &vlan, sizeof(vlan));
7364 header += sizeof(vlan);
7366 action_encap_data->conf.size = header -
7367 action_encap_data->data;
7368 action->conf = &action_encap_data->conf;
7372 /** Parse l2 decap action. */
7374 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
7375 const char *str, unsigned int len,
7376 void *buf, unsigned int size)
7378 struct buffer *out = buf;
7379 struct rte_flow_action *action;
7380 struct action_raw_decap_data *action_decap_data;
7381 struct rte_flow_item_eth eth = { .type = 0, };
7382 struct rte_flow_item_vlan vlan = {
7383 .tci = mplsoudp_encap_conf.vlan_tci,
7389 ret = parse_vc(ctx, token, str, len, buf, size);
7392 /* Nothing else to do if there is no buffer. */
7395 if (!out->args.vc.actions_n)
7397 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7398 /* Point to selected object. */
7399 ctx->object = out->args.vc.data;
7400 ctx->objmask = NULL;
7401 /* Copy the headers to the buffer. */
7402 action_decap_data = ctx->object;
7403 *action_decap_data = (struct action_raw_decap_data) {
7404 .conf = (struct rte_flow_action_raw_decap){
7405 .data = action_decap_data->data,
7409 header = action_decap_data->data;
7410 if (l2_decap_conf.select_vlan)
7411 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7412 memcpy(header, ð, sizeof(eth));
7413 header += sizeof(eth);
7414 if (l2_decap_conf.select_vlan) {
7415 memcpy(header, &vlan, sizeof(vlan));
7416 header += sizeof(vlan);
7418 action_decap_data->conf.size = header -
7419 action_decap_data->data;
7420 action->conf = &action_decap_data->conf;
7424 #define ETHER_TYPE_MPLS_UNICAST 0x8847
7426 /** Parse MPLSOGRE encap action. */
7428 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
7429 const char *str, unsigned int len,
7430 void *buf, unsigned int size)
7432 struct buffer *out = buf;
7433 struct rte_flow_action *action;
7434 struct action_raw_encap_data *action_encap_data;
7435 struct rte_flow_item_eth eth = { .type = 0, };
7436 struct rte_flow_item_vlan vlan = {
7437 .tci = mplsogre_encap_conf.vlan_tci,
7440 struct rte_flow_item_ipv4 ipv4 = {
7442 .src_addr = mplsogre_encap_conf.ipv4_src,
7443 .dst_addr = mplsogre_encap_conf.ipv4_dst,
7444 .next_proto_id = IPPROTO_GRE,
7445 .version_ihl = RTE_IPV4_VHL_DEF,
7446 .time_to_live = IPDEFTTL,
7449 struct rte_flow_item_ipv6 ipv6 = {
7451 .proto = IPPROTO_GRE,
7452 .hop_limits = IPDEFTTL,
7455 struct rte_flow_item_gre gre = {
7456 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
7458 struct rte_flow_item_mpls mpls = {
7464 ret = parse_vc(ctx, token, str, len, buf, size);
7467 /* Nothing else to do if there is no buffer. */
7470 if (!out->args.vc.actions_n)
7472 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7473 /* Point to selected object. */
7474 ctx->object = out->args.vc.data;
7475 ctx->objmask = NULL;
7476 /* Copy the headers to the buffer. */
7477 action_encap_data = ctx->object;
7478 *action_encap_data = (struct action_raw_encap_data) {
7479 .conf = (struct rte_flow_action_raw_encap){
7480 .data = action_encap_data->data,
7485 header = action_encap_data->data;
7486 if (mplsogre_encap_conf.select_vlan)
7487 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7488 else if (mplsogre_encap_conf.select_ipv4)
7489 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7491 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7492 memcpy(eth.dst.addr_bytes,
7493 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7494 memcpy(eth.src.addr_bytes,
7495 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7496 memcpy(header, ð, sizeof(eth));
7497 header += sizeof(eth);
7498 if (mplsogre_encap_conf.select_vlan) {
7499 if (mplsogre_encap_conf.select_ipv4)
7500 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7502 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7503 memcpy(header, &vlan, sizeof(vlan));
7504 header += sizeof(vlan);
7506 if (mplsogre_encap_conf.select_ipv4) {
7507 memcpy(header, &ipv4, sizeof(ipv4));
7508 header += sizeof(ipv4);
7510 memcpy(&ipv6.hdr.src_addr,
7511 &mplsogre_encap_conf.ipv6_src,
7512 sizeof(mplsogre_encap_conf.ipv6_src));
7513 memcpy(&ipv6.hdr.dst_addr,
7514 &mplsogre_encap_conf.ipv6_dst,
7515 sizeof(mplsogre_encap_conf.ipv6_dst));
7516 memcpy(header, &ipv6, sizeof(ipv6));
7517 header += sizeof(ipv6);
7519 memcpy(header, &gre, sizeof(gre));
7520 header += sizeof(gre);
7521 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
7522 RTE_DIM(mplsogre_encap_conf.label));
7523 mpls.label_tc_s[2] |= 0x1;
7524 memcpy(header, &mpls, sizeof(mpls));
7525 header += sizeof(mpls);
7526 action_encap_data->conf.size = header -
7527 action_encap_data->data;
7528 action->conf = &action_encap_data->conf;
7532 /** Parse MPLSOGRE decap action. */
7534 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
7535 const char *str, unsigned int len,
7536 void *buf, unsigned int size)
7538 struct buffer *out = buf;
7539 struct rte_flow_action *action;
7540 struct action_raw_decap_data *action_decap_data;
7541 struct rte_flow_item_eth eth = { .type = 0, };
7542 struct rte_flow_item_vlan vlan = {.tci = 0};
7543 struct rte_flow_item_ipv4 ipv4 = {
7545 .next_proto_id = IPPROTO_GRE,
7548 struct rte_flow_item_ipv6 ipv6 = {
7550 .proto = IPPROTO_GRE,
7553 struct rte_flow_item_gre gre = {
7554 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
7556 struct rte_flow_item_mpls mpls;
7560 ret = parse_vc(ctx, token, str, len, buf, size);
7563 /* Nothing else to do if there is no buffer. */
7566 if (!out->args.vc.actions_n)
7568 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7569 /* Point to selected object. */
7570 ctx->object = out->args.vc.data;
7571 ctx->objmask = NULL;
7572 /* Copy the headers to the buffer. */
7573 action_decap_data = ctx->object;
7574 *action_decap_data = (struct action_raw_decap_data) {
7575 .conf = (struct rte_flow_action_raw_decap){
7576 .data = action_decap_data->data,
7580 header = action_decap_data->data;
7581 if (mplsogre_decap_conf.select_vlan)
7582 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7583 else if (mplsogre_encap_conf.select_ipv4)
7584 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7586 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7587 memcpy(eth.dst.addr_bytes,
7588 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7589 memcpy(eth.src.addr_bytes,
7590 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7591 memcpy(header, ð, sizeof(eth));
7592 header += sizeof(eth);
7593 if (mplsogre_encap_conf.select_vlan) {
7594 if (mplsogre_encap_conf.select_ipv4)
7595 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7597 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7598 memcpy(header, &vlan, sizeof(vlan));
7599 header += sizeof(vlan);
7601 if (mplsogre_encap_conf.select_ipv4) {
7602 memcpy(header, &ipv4, sizeof(ipv4));
7603 header += sizeof(ipv4);
7605 memcpy(header, &ipv6, sizeof(ipv6));
7606 header += sizeof(ipv6);
7608 memcpy(header, &gre, sizeof(gre));
7609 header += sizeof(gre);
7610 memset(&mpls, 0, sizeof(mpls));
7611 memcpy(header, &mpls, sizeof(mpls));
7612 header += sizeof(mpls);
7613 action_decap_data->conf.size = header -
7614 action_decap_data->data;
7615 action->conf = &action_decap_data->conf;
7619 /** Parse MPLSOUDP encap action. */
7621 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
7622 const char *str, unsigned int len,
7623 void *buf, unsigned int size)
7625 struct buffer *out = buf;
7626 struct rte_flow_action *action;
7627 struct action_raw_encap_data *action_encap_data;
7628 struct rte_flow_item_eth eth = { .type = 0, };
7629 struct rte_flow_item_vlan vlan = {
7630 .tci = mplsoudp_encap_conf.vlan_tci,
7633 struct rte_flow_item_ipv4 ipv4 = {
7635 .src_addr = mplsoudp_encap_conf.ipv4_src,
7636 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
7637 .next_proto_id = IPPROTO_UDP,
7638 .version_ihl = RTE_IPV4_VHL_DEF,
7639 .time_to_live = IPDEFTTL,
7642 struct rte_flow_item_ipv6 ipv6 = {
7644 .proto = IPPROTO_UDP,
7645 .hop_limits = IPDEFTTL,
7648 struct rte_flow_item_udp udp = {
7650 .src_port = mplsoudp_encap_conf.udp_src,
7651 .dst_port = mplsoudp_encap_conf.udp_dst,
7654 struct rte_flow_item_mpls mpls;
7658 ret = parse_vc(ctx, token, str, len, buf, size);
7661 /* Nothing else to do if there is no buffer. */
7664 if (!out->args.vc.actions_n)
7666 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7667 /* Point to selected object. */
7668 ctx->object = out->args.vc.data;
7669 ctx->objmask = NULL;
7670 /* Copy the headers to the buffer. */
7671 action_encap_data = ctx->object;
7672 *action_encap_data = (struct action_raw_encap_data) {
7673 .conf = (struct rte_flow_action_raw_encap){
7674 .data = action_encap_data->data,
7679 header = action_encap_data->data;
7680 if (mplsoudp_encap_conf.select_vlan)
7681 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7682 else if (mplsoudp_encap_conf.select_ipv4)
7683 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7685 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7686 memcpy(eth.dst.addr_bytes,
7687 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7688 memcpy(eth.src.addr_bytes,
7689 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7690 memcpy(header, ð, sizeof(eth));
7691 header += sizeof(eth);
7692 if (mplsoudp_encap_conf.select_vlan) {
7693 if (mplsoudp_encap_conf.select_ipv4)
7694 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7696 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7697 memcpy(header, &vlan, sizeof(vlan));
7698 header += sizeof(vlan);
7700 if (mplsoudp_encap_conf.select_ipv4) {
7701 memcpy(header, &ipv4, sizeof(ipv4));
7702 header += sizeof(ipv4);
7704 memcpy(&ipv6.hdr.src_addr,
7705 &mplsoudp_encap_conf.ipv6_src,
7706 sizeof(mplsoudp_encap_conf.ipv6_src));
7707 memcpy(&ipv6.hdr.dst_addr,
7708 &mplsoudp_encap_conf.ipv6_dst,
7709 sizeof(mplsoudp_encap_conf.ipv6_dst));
7710 memcpy(header, &ipv6, sizeof(ipv6));
7711 header += sizeof(ipv6);
7713 memcpy(header, &udp, sizeof(udp));
7714 header += sizeof(udp);
7715 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
7716 RTE_DIM(mplsoudp_encap_conf.label));
7717 mpls.label_tc_s[2] |= 0x1;
7718 memcpy(header, &mpls, sizeof(mpls));
7719 header += sizeof(mpls);
7720 action_encap_data->conf.size = header -
7721 action_encap_data->data;
7722 action->conf = &action_encap_data->conf;
7726 /** Parse MPLSOUDP decap action. */
7728 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
7729 const char *str, unsigned int len,
7730 void *buf, unsigned int size)
7732 struct buffer *out = buf;
7733 struct rte_flow_action *action;
7734 struct action_raw_decap_data *action_decap_data;
7735 struct rte_flow_item_eth eth = { .type = 0, };
7736 struct rte_flow_item_vlan vlan = {.tci = 0};
7737 struct rte_flow_item_ipv4 ipv4 = {
7739 .next_proto_id = IPPROTO_UDP,
7742 struct rte_flow_item_ipv6 ipv6 = {
7744 .proto = IPPROTO_UDP,
7747 struct rte_flow_item_udp udp = {
7749 .dst_port = rte_cpu_to_be_16(6635),
7752 struct rte_flow_item_mpls mpls;
7756 ret = parse_vc(ctx, token, str, len, buf, size);
7759 /* Nothing else to do if there is no buffer. */
7762 if (!out->args.vc.actions_n)
7764 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7765 /* Point to selected object. */
7766 ctx->object = out->args.vc.data;
7767 ctx->objmask = NULL;
7768 /* Copy the headers to the buffer. */
7769 action_decap_data = ctx->object;
7770 *action_decap_data = (struct action_raw_decap_data) {
7771 .conf = (struct rte_flow_action_raw_decap){
7772 .data = action_decap_data->data,
7776 header = action_decap_data->data;
7777 if (mplsoudp_decap_conf.select_vlan)
7778 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7779 else if (mplsoudp_encap_conf.select_ipv4)
7780 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7782 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7783 memcpy(eth.dst.addr_bytes,
7784 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7785 memcpy(eth.src.addr_bytes,
7786 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7787 memcpy(header, ð, sizeof(eth));
7788 header += sizeof(eth);
7789 if (mplsoudp_encap_conf.select_vlan) {
7790 if (mplsoudp_encap_conf.select_ipv4)
7791 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7793 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7794 memcpy(header, &vlan, sizeof(vlan));
7795 header += sizeof(vlan);
7797 if (mplsoudp_encap_conf.select_ipv4) {
7798 memcpy(header, &ipv4, sizeof(ipv4));
7799 header += sizeof(ipv4);
7801 memcpy(header, &ipv6, sizeof(ipv6));
7802 header += sizeof(ipv6);
7804 memcpy(header, &udp, sizeof(udp));
7805 header += sizeof(udp);
7806 memset(&mpls, 0, sizeof(mpls));
7807 memcpy(header, &mpls, sizeof(mpls));
7808 header += sizeof(mpls);
7809 action_decap_data->conf.size = header -
7810 action_decap_data->data;
7811 action->conf = &action_decap_data->conf;
7816 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
7817 const char *str, unsigned int len, void *buf,
7820 struct action_raw_decap_data *action_raw_decap_data;
7821 struct rte_flow_action *action;
7822 const struct arg *arg;
7823 struct buffer *out = buf;
7827 RTE_SET_USED(token);
7830 arg = ARGS_ENTRY_ARB_BOUNDED
7831 (offsetof(struct action_raw_decap_data, idx),
7832 sizeof(((struct action_raw_decap_data *)0)->idx),
7833 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7834 if (push_args(ctx, arg))
7836 ret = parse_int(ctx, token, str, len, NULL, 0);
7843 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7844 action_raw_decap_data = ctx->object;
7845 idx = action_raw_decap_data->idx;
7846 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
7847 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
7848 action->conf = &action_raw_decap_data->conf;
7854 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
7855 const char *str, unsigned int len, void *buf,
7858 struct action_raw_encap_data *action_raw_encap_data;
7859 struct rte_flow_action *action;
7860 const struct arg *arg;
7861 struct buffer *out = buf;
7865 RTE_SET_USED(token);
7868 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
7870 arg = ARGS_ENTRY_ARB_BOUNDED
7871 (offsetof(struct action_raw_encap_data, idx),
7872 sizeof(((struct action_raw_encap_data *)0)->idx),
7873 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7874 if (push_args(ctx, arg))
7876 ret = parse_int(ctx, token, str, len, NULL, 0);
7883 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7884 action_raw_encap_data = ctx->object;
7885 idx = action_raw_encap_data->idx;
7886 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
7887 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
7888 action_raw_encap_data->conf.preserve = NULL;
7889 action->conf = &action_raw_encap_data->conf;
7894 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
7895 const char *str, unsigned int len, void *buf,
7898 struct buffer *out = buf;
7899 struct rte_flow_action *action;
7900 struct action_raw_encap_data *action_raw_encap_data = NULL;
7903 ret = parse_vc(ctx, token, str, len, buf, size);
7906 /* Nothing else to do if there is no buffer. */
7909 if (!out->args.vc.actions_n)
7911 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7912 /* Point to selected object. */
7913 ctx->object = out->args.vc.data;
7914 ctx->objmask = NULL;
7915 /* Copy the headers to the buffer. */
7916 action_raw_encap_data = ctx->object;
7917 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
7918 action_raw_encap_data->conf.preserve = NULL;
7919 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
7920 action->conf = &action_raw_encap_data->conf;
7925 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
7926 const char *str, unsigned int len, void *buf,
7929 struct buffer *out = buf;
7930 struct rte_flow_action *action;
7931 struct action_raw_decap_data *action_raw_decap_data = NULL;
7934 ret = parse_vc(ctx, token, str, len, buf, size);
7937 /* Nothing else to do if there is no buffer. */
7940 if (!out->args.vc.actions_n)
7942 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7943 /* Point to selected object. */
7944 ctx->object = out->args.vc.data;
7945 ctx->objmask = NULL;
7946 /* Copy the headers to the buffer. */
7947 action_raw_decap_data = ctx->object;
7948 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
7949 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
7950 action->conf = &action_raw_decap_data->conf;
7955 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
7956 const char *str, unsigned int len, void *buf,
7961 ret = parse_vc(ctx, token, str, len, buf, size);
7964 ret = rte_flow_dynf_metadata_register();
7971 parse_vc_action_sample(struct context *ctx, const struct token *token,
7972 const char *str, unsigned int len, void *buf,
7975 struct buffer *out = buf;
7976 struct rte_flow_action *action;
7977 struct action_sample_data *action_sample_data = NULL;
7978 static struct rte_flow_action end_action = {
7979 RTE_FLOW_ACTION_TYPE_END, 0
7983 ret = parse_vc(ctx, token, str, len, buf, size);
7986 /* Nothing else to do if there is no buffer. */
7989 if (!out->args.vc.actions_n)
7991 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7992 /* Point to selected object. */
7993 ctx->object = out->args.vc.data;
7994 ctx->objmask = NULL;
7995 /* Copy the headers to the buffer. */
7996 action_sample_data = ctx->object;
7997 action_sample_data->conf.actions = &end_action;
7998 action->conf = &action_sample_data->conf;
8003 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
8004 const char *str, unsigned int len, void *buf,
8007 struct action_sample_data *action_sample_data;
8008 struct rte_flow_action *action;
8009 const struct arg *arg;
8010 struct buffer *out = buf;
8014 RTE_SET_USED(token);
8017 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
8019 arg = ARGS_ENTRY_ARB_BOUNDED
8020 (offsetof(struct action_sample_data, idx),
8021 sizeof(((struct action_sample_data *)0)->idx),
8022 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
8023 if (push_args(ctx, arg))
8025 ret = parse_int(ctx, token, str, len, NULL, 0);
8032 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8033 action_sample_data = ctx->object;
8034 idx = action_sample_data->idx;
8035 action_sample_data->conf.actions = raw_sample_confs[idx].data;
8036 action->conf = &action_sample_data->conf;
8040 /** Parse operation for modify_field command. */
8042 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
8043 const char *str, unsigned int len, void *buf,
8046 struct rte_flow_action_modify_field *action_modify_field;
8052 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
8054 for (i = 0; modify_field_ops[i]; ++i)
8055 if (!strcmp_partial(modify_field_ops[i], str, len))
8057 if (!modify_field_ops[i])
8061 action_modify_field = ctx->object;
8062 action_modify_field->operation = (enum rte_flow_modify_op)i;
8066 /** Parse id for modify_field command. */
8068 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
8069 const char *str, unsigned int len, void *buf,
8072 struct rte_flow_action_modify_field *action_modify_field;
8078 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
8079 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
8081 for (i = 0; modify_field_ids[i]; ++i)
8082 if (!strcmp_partial(modify_field_ids[i], str, len))
8084 if (!modify_field_ids[i])
8088 action_modify_field = ctx->object;
8089 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
8090 action_modify_field->dst.field = (enum rte_flow_field_id)i;
8092 action_modify_field->src.field = (enum rte_flow_field_id)i;
8096 /** Parse the conntrack update, not a rte_flow_action. */
8098 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
8099 const char *str, unsigned int len, void *buf,
8102 struct buffer *out = buf;
8103 struct rte_flow_modify_conntrack *ct_modify = NULL;
8106 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
8107 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
8109 /* Token name must match. */
8110 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8112 /* Nothing else to do if there is no buffer. */
8115 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
8116 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
8117 ct_modify->new_ct.is_original_dir =
8118 conntrack_context.is_original_dir;
8119 ct_modify->direction = 1;
8123 old_dir = ct_modify->new_ct.is_original_dir;
8124 memcpy(&ct_modify->new_ct, &conntrack_context,
8125 sizeof(conntrack_context));
8126 ct_modify->new_ct.is_original_dir = old_dir;
8127 ct_modify->state = 1;
8132 /** Parse tokens for destroy command. */
8134 parse_destroy(struct context *ctx, const struct token *token,
8135 const char *str, unsigned int len,
8136 void *buf, unsigned int size)
8138 struct buffer *out = buf;
8140 /* Token name must match. */
8141 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8143 /* Nothing else to do if there is no buffer. */
8146 if (!out->command) {
8147 if (ctx->curr != DESTROY)
8149 if (sizeof(*out) > size)
8151 out->command = ctx->curr;
8154 ctx->objmask = NULL;
8155 out->args.destroy.rule =
8156 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8160 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
8161 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
8164 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
8165 ctx->objmask = NULL;
8169 /** Parse tokens for flush command. */
8171 parse_flush(struct context *ctx, const struct token *token,
8172 const char *str, unsigned int len,
8173 void *buf, unsigned int size)
8175 struct buffer *out = buf;
8177 /* Token name must match. */
8178 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8180 /* Nothing else to do if there is no buffer. */
8183 if (!out->command) {
8184 if (ctx->curr != FLUSH)
8186 if (sizeof(*out) > size)
8188 out->command = ctx->curr;
8191 ctx->objmask = NULL;
8196 /** Parse tokens for dump command. */
8198 parse_dump(struct context *ctx, const struct token *token,
8199 const char *str, unsigned int len,
8200 void *buf, unsigned int size)
8202 struct buffer *out = buf;
8204 /* Token name must match. */
8205 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8207 /* Nothing else to do if there is no buffer. */
8210 if (!out->command) {
8211 if (ctx->curr != DUMP)
8213 if (sizeof(*out) > size)
8215 out->command = ctx->curr;
8218 ctx->objmask = NULL;
8221 switch (ctx->curr) {
8224 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
8225 out->command = ctx->curr;
8228 ctx->objmask = NULL;
8235 /** Parse tokens for query command. */
8237 parse_query(struct context *ctx, const struct token *token,
8238 const char *str, unsigned int len,
8239 void *buf, unsigned int size)
8241 struct buffer *out = buf;
8243 /* Token name must match. */
8244 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8246 /* Nothing else to do if there is no buffer. */
8249 if (!out->command) {
8250 if (ctx->curr != QUERY)
8252 if (sizeof(*out) > size)
8254 out->command = ctx->curr;
8257 ctx->objmask = NULL;
8262 /** Parse action names. */
8264 parse_action(struct context *ctx, const struct token *token,
8265 const char *str, unsigned int len,
8266 void *buf, unsigned int size)
8268 struct buffer *out = buf;
8269 const struct arg *arg = pop_args(ctx);
8273 /* Argument is expected. */
8276 /* Parse action name. */
8277 for (i = 0; next_action[i]; ++i) {
8278 const struct parse_action_priv *priv;
8280 token = &token_list[next_action[i]];
8281 if (strcmp_partial(token->name, str, len))
8287 memcpy((uint8_t *)ctx->object + arg->offset,
8293 push_args(ctx, arg);
8297 /** Parse tokens for list command. */
8299 parse_list(struct context *ctx, const struct token *token,
8300 const char *str, unsigned int len,
8301 void *buf, unsigned int size)
8303 struct buffer *out = buf;
8305 /* Token name must match. */
8306 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8308 /* Nothing else to do if there is no buffer. */
8311 if (!out->command) {
8312 if (ctx->curr != LIST)
8314 if (sizeof(*out) > size)
8316 out->command = ctx->curr;
8319 ctx->objmask = NULL;
8320 out->args.list.group =
8321 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8325 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
8326 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
8329 ctx->object = out->args.list.group + out->args.list.group_n++;
8330 ctx->objmask = NULL;
8334 /** Parse tokens for list all aged flows command. */
8336 parse_aged(struct context *ctx, const struct token *token,
8337 const char *str, unsigned int len,
8338 void *buf, unsigned int size)
8340 struct buffer *out = buf;
8342 /* Token name must match. */
8343 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8345 /* Nothing else to do if there is no buffer. */
8348 if (!out->command) {
8349 if (ctx->curr != AGED)
8351 if (sizeof(*out) > size)
8353 out->command = ctx->curr;
8356 ctx->objmask = NULL;
8358 if (ctx->curr == AGED_DESTROY)
8359 out->args.aged.destroy = 1;
8363 /** Parse tokens for isolate command. */
8365 parse_isolate(struct context *ctx, const struct token *token,
8366 const char *str, unsigned int len,
8367 void *buf, unsigned int size)
8369 struct buffer *out = buf;
8371 /* Token name must match. */
8372 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8374 /* Nothing else to do if there is no buffer. */
8377 if (!out->command) {
8378 if (ctx->curr != ISOLATE)
8380 if (sizeof(*out) > size)
8382 out->command = ctx->curr;
8385 ctx->objmask = NULL;
8390 /** Parse tokens for info/configure command. */
8392 parse_configure(struct context *ctx, const struct token *token,
8393 const char *str, unsigned int len,
8394 void *buf, unsigned int size)
8396 struct buffer *out = buf;
8398 /* Token name must match. */
8399 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8401 /* Nothing else to do if there is no buffer. */
8404 if (!out->command) {
8405 if (ctx->curr != INFO && ctx->curr != CONFIGURE)
8407 if (sizeof(*out) > size)
8409 out->command = ctx->curr;
8412 ctx->objmask = NULL;
8417 /** Parse tokens for template create command. */
8419 parse_template(struct context *ctx, const struct token *token,
8420 const char *str, unsigned int len,
8421 void *buf, unsigned int size)
8423 struct buffer *out = buf;
8425 /* Token name must match. */
8426 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8428 /* Nothing else to do if there is no buffer. */
8431 if (!out->command) {
8432 if (ctx->curr != PATTERN_TEMPLATE &&
8433 ctx->curr != ACTIONS_TEMPLATE)
8435 if (sizeof(*out) > size)
8437 out->command = ctx->curr;
8440 ctx->objmask = NULL;
8441 out->args.vc.data = (uint8_t *)out + size;
8444 switch (ctx->curr) {
8445 case PATTERN_TEMPLATE_CREATE:
8446 out->args.vc.pattern =
8447 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8449 out->args.vc.pat_templ_id = UINT32_MAX;
8450 out->command = ctx->curr;
8453 ctx->objmask = NULL;
8455 case PATTERN_TEMPLATE_EGRESS:
8456 out->args.vc.attr.egress = 1;
8458 case PATTERN_TEMPLATE_INGRESS:
8459 out->args.vc.attr.ingress = 1;
8461 case PATTERN_TEMPLATE_TRANSFER:
8462 out->args.vc.attr.transfer = 1;
8464 case ACTIONS_TEMPLATE_CREATE:
8465 out->args.vc.act_templ_id = UINT32_MAX;
8466 out->command = ctx->curr;
8469 ctx->objmask = NULL;
8471 case ACTIONS_TEMPLATE_SPEC:
8472 out->args.vc.actions =
8473 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8475 ctx->object = out->args.vc.actions;
8476 ctx->objmask = NULL;
8478 case ACTIONS_TEMPLATE_MASK:
8479 out->args.vc.masks =
8480 (void *)RTE_ALIGN_CEIL((uintptr_t)
8481 (out->args.vc.actions +
8482 out->args.vc.actions_n),
8484 ctx->object = out->args.vc.masks;
8485 ctx->objmask = NULL;
8487 case ACTIONS_TEMPLATE_EGRESS:
8488 out->args.vc.attr.egress = 1;
8490 case ACTIONS_TEMPLATE_INGRESS:
8491 out->args.vc.attr.ingress = 1;
8493 case ACTIONS_TEMPLATE_TRANSFER:
8494 out->args.vc.attr.transfer = 1;
8501 /** Parse tokens for template destroy command. */
8503 parse_template_destroy(struct context *ctx, const struct token *token,
8504 const char *str, unsigned int len,
8505 void *buf, unsigned int size)
8507 struct buffer *out = buf;
8508 uint32_t *template_id;
8510 /* Token name must match. */
8511 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8513 /* Nothing else to do if there is no buffer. */
8516 if (!out->command ||
8517 out->command == PATTERN_TEMPLATE ||
8518 out->command == ACTIONS_TEMPLATE) {
8519 if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
8520 ctx->curr != ACTIONS_TEMPLATE_DESTROY)
8522 if (sizeof(*out) > size)
8524 out->command = ctx->curr;
8527 ctx->objmask = NULL;
8528 out->args.templ_destroy.template_id =
8529 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8533 template_id = out->args.templ_destroy.template_id
8534 + out->args.templ_destroy.template_id_n++;
8535 if ((uint8_t *)template_id > (uint8_t *)out + size)
8538 ctx->object = template_id;
8539 ctx->objmask = NULL;
8543 /** Parse tokens for table create command. */
8545 parse_table(struct context *ctx, const struct token *token,
8546 const char *str, unsigned int len,
8547 void *buf, unsigned int size)
8549 struct buffer *out = buf;
8550 uint32_t *template_id;
8552 /* Token name must match. */
8553 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8555 /* Nothing else to do if there is no buffer. */
8558 if (!out->command) {
8559 if (ctx->curr != TABLE)
8561 if (sizeof(*out) > size)
8563 out->command = ctx->curr;
8566 ctx->objmask = NULL;
8569 switch (ctx->curr) {
8571 out->command = ctx->curr;
8574 ctx->objmask = NULL;
8575 out->args.table.id = UINT32_MAX;
8577 case TABLE_PATTERN_TEMPLATE:
8578 out->args.table.pat_templ_id =
8579 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8581 template_id = out->args.table.pat_templ_id
8582 + out->args.table.pat_templ_id_n++;
8583 if ((uint8_t *)template_id > (uint8_t *)out + size)
8586 ctx->object = template_id;
8587 ctx->objmask = NULL;
8589 case TABLE_ACTIONS_TEMPLATE:
8590 out->args.table.act_templ_id =
8591 (void *)RTE_ALIGN_CEIL((uintptr_t)
8592 (out->args.table.pat_templ_id +
8593 out->args.table.pat_templ_id_n),
8595 template_id = out->args.table.act_templ_id
8596 + out->args.table.act_templ_id_n++;
8597 if ((uint8_t *)template_id > (uint8_t *)out + size)
8600 ctx->object = template_id;
8601 ctx->objmask = NULL;
8604 out->args.table.attr.flow_attr.ingress = 1;
8607 out->args.table.attr.flow_attr.egress = 1;
8609 case TABLE_TRANSFER:
8610 out->args.table.attr.flow_attr.transfer = 1;
8617 /** Parse tokens for table destroy command. */
8619 parse_table_destroy(struct context *ctx, const struct token *token,
8620 const char *str, unsigned int len,
8621 void *buf, unsigned int size)
8623 struct buffer *out = buf;
8626 /* Token name must match. */
8627 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8629 /* Nothing else to do if there is no buffer. */
8632 if (!out->command || out->command == TABLE) {
8633 if (ctx->curr != TABLE_DESTROY)
8635 if (sizeof(*out) > size)
8637 out->command = ctx->curr;
8640 ctx->objmask = NULL;
8641 out->args.table_destroy.table_id =
8642 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8646 table_id = out->args.table_destroy.table_id
8647 + out->args.table_destroy.table_id_n++;
8648 if ((uint8_t *)table_id > (uint8_t *)out + size)
8651 ctx->object = table_id;
8652 ctx->objmask = NULL;
8656 /** Parse tokens for queue create commands. */
8658 parse_qo(struct context *ctx, const struct token *token,
8659 const char *str, unsigned int len,
8660 void *buf, unsigned int size)
8662 struct buffer *out = buf;
8664 /* Token name must match. */
8665 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8667 /* Nothing else to do if there is no buffer. */
8670 if (!out->command) {
8671 if (ctx->curr != QUEUE)
8673 if (sizeof(*out) > size)
8675 out->command = ctx->curr;
8678 ctx->objmask = NULL;
8679 out->args.vc.data = (uint8_t *)out + size;
8682 switch (ctx->curr) {
8684 out->command = ctx->curr;
8687 ctx->objmask = NULL;
8689 case QUEUE_TEMPLATE_TABLE:
8690 case QUEUE_PATTERN_TEMPLATE:
8691 case QUEUE_ACTIONS_TEMPLATE:
8692 case QUEUE_CREATE_POSTPONE:
8695 out->args.vc.pattern =
8696 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8698 ctx->object = out->args.vc.pattern;
8699 ctx->objmask = NULL;
8702 out->args.vc.actions =
8703 (void *)RTE_ALIGN_CEIL((uintptr_t)
8704 (out->args.vc.pattern +
8705 out->args.vc.pattern_n),
8707 ctx->object = out->args.vc.actions;
8708 ctx->objmask = NULL;
8715 /** Parse tokens for queue destroy command. */
8717 parse_qo_destroy(struct context *ctx, const struct token *token,
8718 const char *str, unsigned int len,
8719 void *buf, unsigned int size)
8721 struct buffer *out = buf;
8724 /* Token name must match. */
8725 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8727 /* Nothing else to do if there is no buffer. */
8730 if (!out->command || out->command == QUEUE) {
8731 if (ctx->curr != QUEUE_DESTROY)
8733 if (sizeof(*out) > size)
8735 out->command = ctx->curr;
8738 ctx->objmask = NULL;
8739 out->args.destroy.rule =
8740 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8744 switch (ctx->curr) {
8745 case QUEUE_DESTROY_ID:
8746 flow_id = out->args.destroy.rule
8747 + out->args.destroy.rule_n++;
8748 if ((uint8_t *)flow_id > (uint8_t *)out + size)
8751 ctx->object = flow_id;
8752 ctx->objmask = NULL;
8754 case QUEUE_DESTROY_POSTPONE:
8761 /** Parse tokens for push queue command. */
8763 parse_push(struct context *ctx, const struct token *token,
8764 const char *str, unsigned int len,
8765 void *buf, unsigned int size)
8767 struct buffer *out = buf;
8769 /* Token name must match. */
8770 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8772 /* Nothing else to do if there is no buffer. */
8775 if (!out->command) {
8776 if (ctx->curr != PUSH)
8778 if (sizeof(*out) > size)
8780 out->command = ctx->curr;
8783 ctx->objmask = NULL;
8784 out->args.vc.data = (uint8_t *)out + size;
8790 parse_flex(struct context *ctx, const struct token *token,
8791 const char *str, unsigned int len,
8792 void *buf, unsigned int size)
8794 struct buffer *out = buf;
8796 /* Token name must match. */
8797 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8799 /* Nothing else to do if there is no buffer. */
8802 if (out->command == ZERO) {
8803 if (ctx->curr != FLEX)
8805 if (sizeof(*out) > size)
8807 out->command = ctx->curr;
8810 ctx->objmask = NULL;
8812 switch (ctx->curr) {
8815 case FLEX_ITEM_INIT:
8816 case FLEX_ITEM_CREATE:
8817 case FLEX_ITEM_DESTROY:
8818 out->command = ctx->curr;
8827 parse_tunnel(struct context *ctx, const struct token *token,
8828 const char *str, unsigned int len,
8829 void *buf, unsigned int size)
8831 struct buffer *out = buf;
8833 /* Token name must match. */
8834 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8836 /* Nothing else to do if there is no buffer. */
8839 if (!out->command) {
8840 if (ctx->curr != TUNNEL)
8842 if (sizeof(*out) > size)
8844 out->command = ctx->curr;
8847 ctx->objmask = NULL;
8849 switch (ctx->curr) {
8853 case TUNNEL_DESTROY:
8855 out->command = ctx->curr;
8857 case TUNNEL_CREATE_TYPE:
8858 case TUNNEL_DESTROY_ID:
8859 ctx->object = &out->args.vc.tunnel_ops;
8868 * Parse signed/unsigned integers 8 to 64-bit long.
8870 * Last argument (ctx->args) is retrieved to determine integer type and
8874 parse_int(struct context *ctx, const struct token *token,
8875 const char *str, unsigned int len,
8876 void *buf, unsigned int size)
8878 const struct arg *arg = pop_args(ctx);
8883 /* Argument is expected. */
8888 (uintmax_t)strtoimax(str, &end, 0) :
8889 strtoumax(str, &end, 0);
8890 if (errno || (size_t)(end - str) != len)
8893 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
8894 (intmax_t)u > (intmax_t)arg->max)) ||
8895 (!arg->sign && (u < arg->min || u > arg->max))))
8900 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
8901 !arg_entry_bf_fill(ctx->objmask, -1, arg))
8905 buf = (uint8_t *)ctx->object + arg->offset;
8907 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
8911 case sizeof(uint8_t):
8912 *(uint8_t *)buf = u;
8914 case sizeof(uint16_t):
8915 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
8917 case sizeof(uint8_t [3]):
8918 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8920 ((uint8_t *)buf)[0] = u;
8921 ((uint8_t *)buf)[1] = u >> 8;
8922 ((uint8_t *)buf)[2] = u >> 16;
8926 ((uint8_t *)buf)[0] = u >> 16;
8927 ((uint8_t *)buf)[1] = u >> 8;
8928 ((uint8_t *)buf)[2] = u;
8930 case sizeof(uint32_t):
8931 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
8933 case sizeof(uint64_t):
8934 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
8939 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
8941 buf = (uint8_t *)ctx->objmask + arg->offset;
8946 push_args(ctx, arg);
8953 * Three arguments (ctx->args) are retrieved from the stack to store data,
8954 * its actual length and address (in that order).
8957 parse_string(struct context *ctx, const struct token *token,
8958 const char *str, unsigned int len,
8959 void *buf, unsigned int size)
8961 const struct arg *arg_data = pop_args(ctx);
8962 const struct arg *arg_len = pop_args(ctx);
8963 const struct arg *arg_addr = pop_args(ctx);
8964 char tmp[16]; /* Ought to be enough. */
8967 /* Arguments are expected. */
8971 push_args(ctx, arg_data);
8975 push_args(ctx, arg_len);
8976 push_args(ctx, arg_data);
8979 size = arg_data->size;
8980 /* Bit-mask fill is not supported. */
8981 if (arg_data->mask || size < len)
8985 /* Let parse_int() fill length information first. */
8986 ret = snprintf(tmp, sizeof(tmp), "%u", len);
8989 push_args(ctx, arg_len);
8990 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
8995 buf = (uint8_t *)ctx->object + arg_data->offset;
8996 /* Output buffer is not necessarily NUL-terminated. */
8997 memcpy(buf, str, len);
8998 memset((uint8_t *)buf + len, 0x00, size - len);
9000 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
9001 /* Save address if requested. */
9002 if (arg_addr->size) {
9003 memcpy((uint8_t *)ctx->object + arg_addr->offset,
9005 (uint8_t *)ctx->object + arg_data->offset
9009 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
9011 (uint8_t *)ctx->objmask + arg_data->offset
9017 push_args(ctx, arg_addr);
9018 push_args(ctx, arg_len);
9019 push_args(ctx, arg_data);
9024 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
9026 const uint8_t *head = dst;
9029 /* Check input parameters */
9030 if ((src == NULL) ||
9038 /* Convert chars to bytes */
9040 char tmp[3], *end = tmp;
9041 uint32_t read_lim = left & 1 ? 1 : 2;
9043 snprintf(tmp, read_lim + 1, "%s", src);
9044 *dst = strtoul(tmp, &end, 16);
9047 *size = (uint32_t)(dst - head);
9055 *size = (uint32_t)(dst - head);
9060 parse_hex(struct context *ctx, const struct token *token,
9061 const char *str, unsigned int len,
9062 void *buf, unsigned int size)
9064 const struct arg *arg_data = pop_args(ctx);
9065 const struct arg *arg_len = pop_args(ctx);
9066 const struct arg *arg_addr = pop_args(ctx);
9067 char tmp[16]; /* Ought to be enough. */
9069 unsigned int hexlen = len;
9070 unsigned int length = 256;
9071 uint8_t hex_tmp[length];
9073 /* Arguments are expected. */
9077 push_args(ctx, arg_data);
9081 push_args(ctx, arg_len);
9082 push_args(ctx, arg_data);
9085 size = arg_data->size;
9086 /* Bit-mask fill is not supported. */
9092 /* translate bytes string to array. */
9093 if (str[0] == '0' && ((str[1] == 'x') ||
9098 if (hexlen > length)
9100 ret = parse_hex_string(str, hex_tmp, &hexlen);
9103 /* Check the converted binary fits into data buffer. */
9106 /* Let parse_int() fill length information first. */
9107 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
9110 /* Save length if requested. */
9111 if (arg_len->size) {
9112 push_args(ctx, arg_len);
9113 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
9119 buf = (uint8_t *)ctx->object + arg_data->offset;
9120 /* Output buffer is not necessarily NUL-terminated. */
9121 memcpy(buf, hex_tmp, hexlen);
9122 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
9124 memset((uint8_t *)ctx->objmask + arg_data->offset,
9126 /* Save address if requested. */
9127 if (arg_addr->size) {
9128 memcpy((uint8_t *)ctx->object + arg_addr->offset,
9130 (uint8_t *)ctx->object + arg_data->offset
9134 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
9136 (uint8_t *)ctx->objmask + arg_data->offset
9142 push_args(ctx, arg_addr);
9143 push_args(ctx, arg_len);
9144 push_args(ctx, arg_data);
9150 * Parse a zero-ended string.
9153 parse_string0(struct context *ctx, const struct token *token __rte_unused,
9154 const char *str, unsigned int len,
9155 void *buf, unsigned int size)
9157 const struct arg *arg_data = pop_args(ctx);
9159 /* Arguments are expected. */
9162 size = arg_data->size;
9163 /* Bit-mask fill is not supported. */
9164 if (arg_data->mask || size < len + 1)
9168 buf = (uint8_t *)ctx->object + arg_data->offset;
9169 strncpy(buf, str, len);
9171 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
9174 push_args(ctx, arg_data);
9179 * Parse a MAC address.
9181 * Last argument (ctx->args) is retrieved to determine storage size and
9185 parse_mac_addr(struct context *ctx, const struct token *token,
9186 const char *str, unsigned int len,
9187 void *buf, unsigned int size)
9189 const struct arg *arg = pop_args(ctx);
9190 struct rte_ether_addr tmp;
9194 /* Argument is expected. */
9198 /* Bit-mask fill is not supported. */
9199 if (arg->mask || size != sizeof(tmp))
9201 /* Only network endian is supported. */
9204 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
9205 if (ret < 0 || (unsigned int)ret != len)
9209 buf = (uint8_t *)ctx->object + arg->offset;
9210 memcpy(buf, &tmp, size);
9212 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9215 push_args(ctx, arg);
9220 * Parse an IPv4 address.
9222 * Last argument (ctx->args) is retrieved to determine storage size and
9226 parse_ipv4_addr(struct context *ctx, const struct token *token,
9227 const char *str, unsigned int len,
9228 void *buf, unsigned int size)
9230 const struct arg *arg = pop_args(ctx);
9235 /* Argument is expected. */
9239 /* Bit-mask fill is not supported. */
9240 if (arg->mask || size != sizeof(tmp))
9242 /* Only network endian is supported. */
9245 memcpy(str2, str, len);
9247 ret = inet_pton(AF_INET, str2, &tmp);
9249 /* Attempt integer parsing. */
9250 push_args(ctx, arg);
9251 return parse_int(ctx, token, str, len, buf, size);
9255 buf = (uint8_t *)ctx->object + arg->offset;
9256 memcpy(buf, &tmp, size);
9258 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9261 push_args(ctx, arg);
9266 * Parse an IPv6 address.
9268 * Last argument (ctx->args) is retrieved to determine storage size and
9272 parse_ipv6_addr(struct context *ctx, const struct token *token,
9273 const char *str, unsigned int len,
9274 void *buf, unsigned int size)
9276 const struct arg *arg = pop_args(ctx);
9278 struct in6_addr tmp;
9282 /* Argument is expected. */
9286 /* Bit-mask fill is not supported. */
9287 if (arg->mask || size != sizeof(tmp))
9289 /* Only network endian is supported. */
9292 memcpy(str2, str, len);
9294 ret = inet_pton(AF_INET6, str2, &tmp);
9299 buf = (uint8_t *)ctx->object + arg->offset;
9300 memcpy(buf, &tmp, size);
9302 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9305 push_args(ctx, arg);
9309 /** Boolean values (even indices stand for false). */
9310 static const char *const boolean_name[] = {
9320 * Parse a boolean value.
9322 * Last argument (ctx->args) is retrieved to determine storage size and
9326 parse_boolean(struct context *ctx, const struct token *token,
9327 const char *str, unsigned int len,
9328 void *buf, unsigned int size)
9330 const struct arg *arg = pop_args(ctx);
9334 /* Argument is expected. */
9337 for (i = 0; boolean_name[i]; ++i)
9338 if (!strcmp_partial(boolean_name[i], str, len))
9340 /* Process token as integer. */
9341 if (boolean_name[i])
9342 str = i & 1 ? "1" : "0";
9343 push_args(ctx, arg);
9344 ret = parse_int(ctx, token, str, strlen(str), buf, size);
9345 return ret > 0 ? (int)len : ret;
9348 /** Parse port and update context. */
9350 parse_port(struct context *ctx, const struct token *token,
9351 const char *str, unsigned int len,
9352 void *buf, unsigned int size)
9354 struct buffer *out = &(struct buffer){ .port = 0 };
9362 ctx->objmask = NULL;
9363 size = sizeof(*out);
9365 ret = parse_int(ctx, token, str, len, out, size);
9367 ctx->port = out->port;
9374 parse_ia_id2ptr(struct context *ctx, const struct token *token,
9375 const char *str, unsigned int len,
9376 void *buf, unsigned int size)
9378 struct rte_flow_action *action = ctx->object;
9386 ctx->objmask = NULL;
9387 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
9388 ctx->object = action;
9389 if (ret != (int)len)
9391 /* set indirect action */
9393 action->conf = port_action_handle_get_by_id(ctx->port, id);
9394 ret = (action->conf) ? ret : -1;
9399 /** Parse set command, initialize output buffer for subsequent tokens. */
9401 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
9402 const char *str, unsigned int len,
9403 void *buf, unsigned int size)
9405 struct buffer *out = buf;
9407 /* Token name must match. */
9408 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9410 /* Nothing else to do if there is no buffer. */
9413 /* Make sure buffer is large enough. */
9414 if (size < sizeof(*out))
9417 ctx->objmask = NULL;
9421 out->command = ctx->curr;
9422 /* For encap/decap we need is pattern */
9423 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9428 /** Parse set command, initialize output buffer for subsequent tokens. */
9430 parse_set_sample_action(struct context *ctx, const struct token *token,
9431 const char *str, unsigned int len,
9432 void *buf, unsigned int size)
9434 struct buffer *out = buf;
9436 /* Token name must match. */
9437 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9439 /* Nothing else to do if there is no buffer. */
9442 /* Make sure buffer is large enough. */
9443 if (size < sizeof(*out))
9446 ctx->objmask = NULL;
9450 out->command = ctx->curr;
9451 /* For sampler we need is actions */
9452 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9458 * Parse set raw_encap/raw_decap command,
9459 * initialize output buffer for subsequent tokens.
9462 parse_set_init(struct context *ctx, const struct token *token,
9463 const char *str, unsigned int len,
9464 void *buf, unsigned int size)
9466 struct buffer *out = buf;
9468 /* Token name must match. */
9469 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9471 /* Nothing else to do if there is no buffer. */
9474 /* Make sure buffer is large enough. */
9475 if (size < sizeof(*out))
9477 /* Initialize buffer. */
9478 memset(out, 0x00, sizeof(*out));
9479 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
9482 ctx->objmask = NULL;
9483 if (!out->command) {
9484 if (ctx->curr != SET)
9486 if (sizeof(*out) > size)
9488 out->command = ctx->curr;
9489 out->args.vc.data = (uint8_t *)out + size;
9490 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9497 * Replace testpmd handles in a flex flow item with real values.
9500 parse_flex_handle(struct context *ctx, const struct token *token,
9501 const char *str, unsigned int len,
9502 void *buf, unsigned int size)
9504 struct rte_flow_item_flex *spec, *mask;
9505 const struct rte_flow_item_flex *src_spec, *src_mask;
9506 const struct arg *arg = pop_args(ctx);
9512 printf("Bad environment\n");
9515 offset = arg->offset;
9516 push_args(ctx, arg);
9517 ret = parse_int(ctx, token, str, len, buf, size);
9518 if (ret <= 0 || !ctx->object)
9520 if (ctx->port >= RTE_MAX_ETHPORTS) {
9521 printf("Bad port\n");
9524 if (offset == offsetof(struct rte_flow_item_flex, handle)) {
9525 const struct flex_item *fp;
9526 struct rte_flow_item_flex *item_flex = ctx->object;
9527 handle = (uint16_t)(uintptr_t)item_flex->handle;
9528 if (handle >= FLEX_MAX_PARSERS_NUM) {
9529 printf("Bad flex item handle\n");
9532 fp = flex_items[ctx->port][handle];
9534 printf("Bad flex item handle\n");
9537 item_flex->handle = fp->flex_handle;
9538 } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
9539 handle = (uint16_t)(uintptr_t)
9540 ((struct rte_flow_item_flex *)ctx->object)->pattern;
9541 if (handle >= FLEX_MAX_PATTERNS_NUM) {
9542 printf("Bad pattern handle\n");
9545 src_spec = &flex_patterns[handle].spec;
9546 src_mask = &flex_patterns[handle].mask;
9548 mask = spec + 2; /* spec, last, mask */
9549 /* fill flow rule spec and mask parameters */
9550 spec->length = src_spec->length;
9551 spec->pattern = src_spec->pattern;
9552 mask->length = src_mask->length;
9553 mask->pattern = src_mask->pattern;
9555 printf("Bad arguments - unknown flex item offset\n");
9561 /** No completion. */
9563 comp_none(struct context *ctx, const struct token *token,
9564 unsigned int ent, char *buf, unsigned int size)
9574 /** Complete boolean values. */
9576 comp_boolean(struct context *ctx, const struct token *token,
9577 unsigned int ent, char *buf, unsigned int size)
9583 for (i = 0; boolean_name[i]; ++i)
9584 if (buf && i == ent)
9585 return strlcpy(buf, boolean_name[i], size);
9591 /** Complete action names. */
9593 comp_action(struct context *ctx, const struct token *token,
9594 unsigned int ent, char *buf, unsigned int size)
9600 for (i = 0; next_action[i]; ++i)
9601 if (buf && i == ent)
9602 return strlcpy(buf, token_list[next_action[i]].name,
9609 /** Complete available ports. */
9611 comp_port(struct context *ctx, const struct token *token,
9612 unsigned int ent, char *buf, unsigned int size)
9619 RTE_ETH_FOREACH_DEV(p) {
9620 if (buf && i == ent)
9621 return snprintf(buf, size, "%u", p);
9629 /** Complete available rule IDs. */
9631 comp_rule_id(struct context *ctx, const struct token *token,
9632 unsigned int ent, char *buf, unsigned int size)
9635 struct rte_port *port;
9636 struct port_flow *pf;
9639 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9640 ctx->port == (portid_t)RTE_PORT_ALL)
9642 port = &ports[ctx->port];
9643 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
9644 if (buf && i == ent)
9645 return snprintf(buf, size, "%u", pf->id);
9653 /** Complete type field for RSS action. */
9655 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
9656 unsigned int ent, char *buf, unsigned int size)
9662 for (i = 0; rss_type_table[i].str; ++i)
9667 return strlcpy(buf, rss_type_table[ent].str, size);
9669 return snprintf(buf, size, "end");
9673 /** Complete queue field for RSS action. */
9675 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
9676 unsigned int ent, char *buf, unsigned int size)
9683 return snprintf(buf, size, "%u", ent);
9685 return snprintf(buf, size, "end");
9689 /** Complete index number for set raw_encap/raw_decap commands. */
9691 comp_set_raw_index(struct context *ctx, const struct token *token,
9692 unsigned int ent, char *buf, unsigned int size)
9698 RTE_SET_USED(token);
9699 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
9700 if (buf && idx == ent)
9701 return snprintf(buf, size, "%u", idx);
9707 /** Complete index number for set raw_encap/raw_decap commands. */
9709 comp_set_sample_index(struct context *ctx, const struct token *token,
9710 unsigned int ent, char *buf, unsigned int size)
9716 RTE_SET_USED(token);
9717 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
9718 if (buf && idx == ent)
9719 return snprintf(buf, size, "%u", idx);
9725 /** Complete operation for modify_field command. */
9727 comp_set_modify_field_op(struct context *ctx, const struct token *token,
9728 unsigned int ent, char *buf, unsigned int size)
9731 RTE_SET_USED(token);
9733 return RTE_DIM(modify_field_ops);
9734 if (ent < RTE_DIM(modify_field_ops) - 1)
9735 return strlcpy(buf, modify_field_ops[ent], size);
9739 /** Complete field id for modify_field command. */
9741 comp_set_modify_field_id(struct context *ctx, const struct token *token,
9742 unsigned int ent, char *buf, unsigned int size)
9746 RTE_SET_USED(token);
9748 return RTE_DIM(modify_field_ids);
9749 if (ent >= RTE_DIM(modify_field_ids) - 1)
9751 name = modify_field_ids[ent];
9752 if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
9753 (strcmp(name, "pointer") && strcmp(name, "value")))
9754 return strlcpy(buf, name, size);
9758 /** Complete available pattern template IDs. */
9760 comp_pattern_template_id(struct context *ctx, const struct token *token,
9761 unsigned int ent, char *buf, unsigned int size)
9764 struct rte_port *port;
9765 struct port_template *pt;
9768 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9769 ctx->port == (portid_t)RTE_PORT_ALL)
9771 port = &ports[ctx->port];
9772 for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
9773 if (buf && i == ent)
9774 return snprintf(buf, size, "%u", pt->id);
9782 /** Complete available actions template IDs. */
9784 comp_actions_template_id(struct context *ctx, const struct token *token,
9785 unsigned int ent, char *buf, unsigned int size)
9788 struct rte_port *port;
9789 struct port_template *pt;
9792 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9793 ctx->port == (portid_t)RTE_PORT_ALL)
9795 port = &ports[ctx->port];
9796 for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
9797 if (buf && i == ent)
9798 return snprintf(buf, size, "%u", pt->id);
9806 /** Complete available table IDs. */
9808 comp_table_id(struct context *ctx, const struct token *token,
9809 unsigned int ent, char *buf, unsigned int size)
9812 struct rte_port *port;
9813 struct port_table *pt;
9816 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9817 ctx->port == (portid_t)RTE_PORT_ALL)
9819 port = &ports[ctx->port];
9820 for (pt = port->table_list; pt != NULL; pt = pt->next) {
9821 if (buf && i == ent)
9822 return snprintf(buf, size, "%u", pt->id);
9830 /** Complete available queue IDs. */
9832 comp_queue_id(struct context *ctx, const struct token *token,
9833 unsigned int ent, char *buf, unsigned int size)
9836 struct rte_port *port;
9839 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9840 ctx->port == (portid_t)RTE_PORT_ALL)
9842 port = &ports[ctx->port];
9843 for (i = 0; i < port->queue_nb; i++) {
9844 if (buf && i == ent)
9845 return snprintf(buf, size, "%u", i);
9852 /** Internal context. */
9853 static struct context cmd_flow_context;
9855 /** Global parser instance (cmdline API). */
9856 cmdline_parse_inst_t cmd_flow;
9857 cmdline_parse_inst_t cmd_set_raw;
9859 /** Initialize context. */
9861 cmd_flow_context_init(struct context *ctx)
9863 /* A full memset() is not necessary. */
9873 ctx->objmask = NULL;
9876 /** Parse a token (cmdline API). */
9878 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
9881 struct context *ctx = &cmd_flow_context;
9882 const struct token *token;
9883 const enum index *list;
9888 token = &token_list[ctx->curr];
9889 /* Check argument length. */
9892 for (len = 0; src[len]; ++len)
9893 if (src[len] == '#' || isspace(src[len]))
9897 /* Last argument and EOL detection. */
9898 for (i = len; src[i]; ++i)
9899 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
9901 else if (!isspace(src[i])) {
9906 if (src[i] == '\r' || src[i] == '\n') {
9910 /* Initialize context if necessary. */
9911 if (!ctx->next_num) {
9914 ctx->next[ctx->next_num++] = token->next[0];
9916 /* Process argument through candidates. */
9917 ctx->prev = ctx->curr;
9918 list = ctx->next[ctx->next_num - 1];
9919 for (i = 0; list[i]; ++i) {
9920 const struct token *next = &token_list[list[i]];
9923 ctx->curr = list[i];
9925 tmp = next->call(ctx, next, src, len, result, size);
9927 tmp = parse_default(ctx, next, src, len, result, size);
9928 if (tmp == -1 || tmp != len)
9936 /* Push subsequent tokens if any. */
9938 for (i = 0; token->next[i]; ++i) {
9939 if (ctx->next_num == RTE_DIM(ctx->next))
9941 ctx->next[ctx->next_num++] = token->next[i];
9943 /* Push arguments if any. */
9945 for (i = 0; token->args[i]; ++i) {
9946 if (ctx->args_num == RTE_DIM(ctx->args))
9948 ctx->args[ctx->args_num++] = token->args[i];
9954 flow_parse(const char *src, void *result, unsigned int size,
9955 struct rte_flow_attr **attr,
9956 struct rte_flow_item **pattern, struct rte_flow_action **actions)
9959 struct context saved_flow_ctx = cmd_flow_context;
9961 cmd_flow_context_init(&cmd_flow_context);
9963 ret = cmd_flow_parse(NULL, src, result, size);
9966 while (isspace(*src))
9969 } while (ret > 0 && strlen(src));
9970 cmd_flow_context = saved_flow_ctx;
9971 *attr = &((struct buffer *)result)->args.vc.attr;
9972 *pattern = ((struct buffer *)result)->args.vc.pattern;
9973 *actions = ((struct buffer *)result)->args.vc.actions;
9974 return (ret >= 0 && !strlen(src)) ? 0 : -1;
9977 /** Return number of completion entries (cmdline API). */
9979 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
9981 struct context *ctx = &cmd_flow_context;
9982 const struct token *token = &token_list[ctx->curr];
9983 const enum index *list;
9987 /* Count number of tokens in current list. */
9989 list = ctx->next[ctx->next_num - 1];
9991 list = token->next[0];
9992 for (i = 0; list[i]; ++i)
9997 * If there is a single token, use its completion callback, otherwise
9998 * return the number of entries.
10000 token = &token_list[list[0]];
10001 if (i == 1 && token->comp) {
10002 /* Save index for cmd_flow_get_help(). */
10003 ctx->prev = list[0];
10004 return token->comp(ctx, token, 0, NULL, 0);
10009 /** Return a completion entry (cmdline API). */
10011 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
10012 char *dst, unsigned int size)
10014 struct context *ctx = &cmd_flow_context;
10015 const struct token *token = &token_list[ctx->curr];
10016 const enum index *list;
10020 /* Count number of tokens in current list. */
10022 list = ctx->next[ctx->next_num - 1];
10024 list = token->next[0];
10025 for (i = 0; list[i]; ++i)
10029 /* If there is a single token, use its completion callback. */
10030 token = &token_list[list[0]];
10031 if (i == 1 && token->comp) {
10032 /* Save index for cmd_flow_get_help(). */
10033 ctx->prev = list[0];
10034 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
10036 /* Otherwise make sure the index is valid and use defaults. */
10039 token = &token_list[list[index]];
10040 strlcpy(dst, token->name, size);
10041 /* Save index for cmd_flow_get_help(). */
10042 ctx->prev = list[index];
10046 /** Populate help strings for current token (cmdline API). */
10048 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
10050 struct context *ctx = &cmd_flow_context;
10051 const struct token *token = &token_list[ctx->prev];
10056 /* Set token type and update global help with details. */
10057 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
10059 cmd_flow.help_str = token->help;
10061 cmd_flow.help_str = token->name;
10065 /** Token definition template (cmdline API). */
10066 static struct cmdline_token_hdr cmd_flow_token_hdr = {
10067 .ops = &(struct cmdline_token_ops){
10068 .parse = cmd_flow_parse,
10069 .complete_get_nb = cmd_flow_complete_get_nb,
10070 .complete_get_elt = cmd_flow_complete_get_elt,
10071 .get_help = cmd_flow_get_help,
10076 /** Populate the next dynamic token. */
10078 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
10079 cmdline_parse_token_hdr_t **hdr_inst)
10081 struct context *ctx = &cmd_flow_context;
10083 /* Always reinitialize context before requesting the first token. */
10084 if (!(hdr_inst - cmd_flow.tokens))
10085 cmd_flow_context_init(ctx);
10086 /* Return NULL when no more tokens are expected. */
10087 if (!ctx->next_num && ctx->curr) {
10091 /* Determine if command should end here. */
10092 if (ctx->eol && ctx->last && ctx->next_num) {
10093 const enum index *list = ctx->next[ctx->next_num - 1];
10096 for (i = 0; list[i]; ++i) {
10097 if (list[i] != END)
10103 *hdr = &cmd_flow_token_hdr;
10106 /** Dispatch parsed buffer to function calls. */
10108 cmd_flow_parsed(const struct buffer *in)
10110 switch (in->command) {
10112 port_flow_get_info(in->port);
10115 port_flow_configure(in->port,
10116 &in->args.configure.port_attr,
10117 in->args.configure.nb_queue,
10118 &in->args.configure.queue_attr);
10120 case PATTERN_TEMPLATE_CREATE:
10121 port_flow_pattern_template_create(in->port,
10122 in->args.vc.pat_templ_id,
10123 &((const struct rte_flow_pattern_template_attr) {
10124 .relaxed_matching = in->args.vc.attr.reserved,
10125 .ingress = in->args.vc.attr.ingress,
10126 .egress = in->args.vc.attr.egress,
10127 .transfer = in->args.vc.attr.transfer,
10129 in->args.vc.pattern);
10131 case PATTERN_TEMPLATE_DESTROY:
10132 port_flow_pattern_template_destroy(in->port,
10133 in->args.templ_destroy.template_id_n,
10134 in->args.templ_destroy.template_id);
10136 case ACTIONS_TEMPLATE_CREATE:
10137 port_flow_actions_template_create(in->port,
10138 in->args.vc.act_templ_id,
10139 &((const struct rte_flow_actions_template_attr) {
10140 .ingress = in->args.vc.attr.ingress,
10141 .egress = in->args.vc.attr.egress,
10142 .transfer = in->args.vc.attr.transfer,
10144 in->args.vc.actions,
10145 in->args.vc.masks);
10147 case ACTIONS_TEMPLATE_DESTROY:
10148 port_flow_actions_template_destroy(in->port,
10149 in->args.templ_destroy.template_id_n,
10150 in->args.templ_destroy.template_id);
10153 port_flow_template_table_create(in->port, in->args.table.id,
10154 &in->args.table.attr, in->args.table.pat_templ_id_n,
10155 in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
10156 in->args.table.act_templ_id);
10158 case TABLE_DESTROY:
10159 port_flow_template_table_destroy(in->port,
10160 in->args.table_destroy.table_id_n,
10161 in->args.table_destroy.table_id);
10164 port_queue_flow_create(in->port, in->queue, in->postpone,
10165 in->args.vc.table_id, in->args.vc.pat_templ_id,
10166 in->args.vc.act_templ_id, in->args.vc.pattern,
10167 in->args.vc.actions);
10169 case QUEUE_DESTROY:
10170 port_queue_flow_destroy(in->port, in->queue, in->postpone,
10171 in->args.destroy.rule_n,
10172 in->args.destroy.rule);
10175 port_queue_flow_push(in->port, in->queue);
10177 case INDIRECT_ACTION_CREATE:
10178 port_action_handle_create(
10179 in->port, in->args.vc.attr.group,
10180 &((const struct rte_flow_indir_action_conf) {
10181 .ingress = in->args.vc.attr.ingress,
10182 .egress = in->args.vc.attr.egress,
10183 .transfer = in->args.vc.attr.transfer,
10185 in->args.vc.actions);
10187 case INDIRECT_ACTION_DESTROY:
10188 port_action_handle_destroy(in->port,
10189 in->args.ia_destroy.action_id_n,
10190 in->args.ia_destroy.action_id);
10192 case INDIRECT_ACTION_UPDATE:
10193 port_action_handle_update(in->port, in->args.vc.attr.group,
10194 in->args.vc.actions);
10196 case INDIRECT_ACTION_QUERY:
10197 port_action_handle_query(in->port, in->args.ia.action_id);
10200 port_flow_validate(in->port, &in->args.vc.attr,
10201 in->args.vc.pattern, in->args.vc.actions,
10202 &in->args.vc.tunnel_ops);
10205 port_flow_create(in->port, &in->args.vc.attr,
10206 in->args.vc.pattern, in->args.vc.actions,
10207 &in->args.vc.tunnel_ops);
10210 port_flow_destroy(in->port, in->args.destroy.rule_n,
10211 in->args.destroy.rule);
10214 port_flow_flush(in->port);
10218 port_flow_dump(in->port, in->args.dump.mode,
10219 in->args.dump.rule, in->args.dump.file);
10222 port_flow_query(in->port, in->args.query.rule,
10223 &in->args.query.action);
10226 port_flow_list(in->port, in->args.list.group_n,
10227 in->args.list.group);
10230 port_flow_isolate(in->port, in->args.isolate.set);
10233 port_flow_aged(in->port, in->args.aged.destroy);
10235 case TUNNEL_CREATE:
10236 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
10238 case TUNNEL_DESTROY:
10239 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
10242 port_flow_tunnel_list(in->port);
10245 port_meter_policy_add(in->port, in->args.policy.policy_id,
10246 in->args.vc.actions);
10248 case FLEX_ITEM_CREATE:
10249 flex_item_create(in->port, in->args.flex.token,
10250 in->args.flex.filename);
10252 case FLEX_ITEM_DESTROY:
10253 flex_item_destroy(in->port, in->args.flex.token);
10260 /** Token generator and output processing callback (cmdline API). */
10262 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
10265 cmd_flow_tok(arg0, arg2);
10267 cmd_flow_parsed(arg0);
10270 /** Global parser instance (cmdline API). */
10271 cmdline_parse_inst_t cmd_flow = {
10273 .data = NULL, /**< Unused. */
10274 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
10277 }, /**< Tokens are returned by cmd_flow_tok(). */
10280 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
10283 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
10285 struct rte_ipv4_hdr *ipv4;
10286 struct rte_ether_hdr *eth;
10287 struct rte_ipv6_hdr *ipv6;
10288 struct rte_vxlan_hdr *vxlan;
10289 struct rte_vxlan_gpe_hdr *gpe;
10290 struct rte_flow_item_nvgre *nvgre;
10291 uint32_t ipv6_vtc_flow;
10293 switch (item->type) {
10294 case RTE_FLOW_ITEM_TYPE_ETH:
10295 eth = (struct rte_ether_hdr *)buf;
10297 eth->ether_type = rte_cpu_to_be_16(next_proto);
10299 case RTE_FLOW_ITEM_TYPE_IPV4:
10300 ipv4 = (struct rte_ipv4_hdr *)buf;
10301 if (!ipv4->version_ihl)
10302 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
10303 if (next_proto && ipv4->next_proto_id == 0)
10304 ipv4->next_proto_id = (uint8_t)next_proto;
10306 case RTE_FLOW_ITEM_TYPE_IPV6:
10307 ipv6 = (struct rte_ipv6_hdr *)buf;
10308 if (next_proto && ipv6->proto == 0)
10309 ipv6->proto = (uint8_t)next_proto;
10310 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
10311 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
10312 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
10313 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
10315 case RTE_FLOW_ITEM_TYPE_VXLAN:
10316 vxlan = (struct rte_vxlan_hdr *)buf;
10317 vxlan->vx_flags = 0x08;
10319 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10320 gpe = (struct rte_vxlan_gpe_hdr *)buf;
10321 gpe->vx_flags = 0x0C;
10323 case RTE_FLOW_ITEM_TYPE_NVGRE:
10324 nvgre = (struct rte_flow_item_nvgre *)buf;
10325 nvgre->protocol = rte_cpu_to_be_16(0x6558);
10326 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
10333 /** Helper of get item's default mask. */
10334 static const void *
10335 flow_item_default_mask(const struct rte_flow_item *item)
10337 const void *mask = NULL;
10338 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
10340 switch (item->type) {
10341 case RTE_FLOW_ITEM_TYPE_ANY:
10342 mask = &rte_flow_item_any_mask;
10344 case RTE_FLOW_ITEM_TYPE_VF:
10345 mask = &rte_flow_item_vf_mask;
10347 case RTE_FLOW_ITEM_TYPE_PORT_ID:
10348 mask = &rte_flow_item_port_id_mask;
10350 case RTE_FLOW_ITEM_TYPE_RAW:
10351 mask = &rte_flow_item_raw_mask;
10353 case RTE_FLOW_ITEM_TYPE_ETH:
10354 mask = &rte_flow_item_eth_mask;
10356 case RTE_FLOW_ITEM_TYPE_VLAN:
10357 mask = &rte_flow_item_vlan_mask;
10359 case RTE_FLOW_ITEM_TYPE_IPV4:
10360 mask = &rte_flow_item_ipv4_mask;
10362 case RTE_FLOW_ITEM_TYPE_IPV6:
10363 mask = &rte_flow_item_ipv6_mask;
10365 case RTE_FLOW_ITEM_TYPE_ICMP:
10366 mask = &rte_flow_item_icmp_mask;
10368 case RTE_FLOW_ITEM_TYPE_UDP:
10369 mask = &rte_flow_item_udp_mask;
10371 case RTE_FLOW_ITEM_TYPE_TCP:
10372 mask = &rte_flow_item_tcp_mask;
10374 case RTE_FLOW_ITEM_TYPE_SCTP:
10375 mask = &rte_flow_item_sctp_mask;
10377 case RTE_FLOW_ITEM_TYPE_VXLAN:
10378 mask = &rte_flow_item_vxlan_mask;
10380 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10381 mask = &rte_flow_item_vxlan_gpe_mask;
10383 case RTE_FLOW_ITEM_TYPE_E_TAG:
10384 mask = &rte_flow_item_e_tag_mask;
10386 case RTE_FLOW_ITEM_TYPE_NVGRE:
10387 mask = &rte_flow_item_nvgre_mask;
10389 case RTE_FLOW_ITEM_TYPE_MPLS:
10390 mask = &rte_flow_item_mpls_mask;
10392 case RTE_FLOW_ITEM_TYPE_GRE:
10393 mask = &rte_flow_item_gre_mask;
10395 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
10396 mask = &gre_key_default_mask;
10398 case RTE_FLOW_ITEM_TYPE_META:
10399 mask = &rte_flow_item_meta_mask;
10401 case RTE_FLOW_ITEM_TYPE_FUZZY:
10402 mask = &rte_flow_item_fuzzy_mask;
10404 case RTE_FLOW_ITEM_TYPE_GTP:
10405 mask = &rte_flow_item_gtp_mask;
10407 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
10408 mask = &rte_flow_item_gtp_psc_mask;
10410 case RTE_FLOW_ITEM_TYPE_GENEVE:
10411 mask = &rte_flow_item_geneve_mask;
10413 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
10414 mask = &rte_flow_item_geneve_opt_mask;
10416 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
10417 mask = &rte_flow_item_pppoe_proto_id_mask;
10419 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
10420 mask = &rte_flow_item_l2tpv3oip_mask;
10422 case RTE_FLOW_ITEM_TYPE_ESP:
10423 mask = &rte_flow_item_esp_mask;
10425 case RTE_FLOW_ITEM_TYPE_AH:
10426 mask = &rte_flow_item_ah_mask;
10428 case RTE_FLOW_ITEM_TYPE_PFCP:
10429 mask = &rte_flow_item_pfcp_mask;
10431 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
10432 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
10433 mask = &rte_flow_item_ethdev_mask;
10435 case RTE_FLOW_ITEM_TYPE_L2TPV2:
10436 mask = &rte_flow_item_l2tpv2_mask;
10438 case RTE_FLOW_ITEM_TYPE_PPP:
10439 mask = &rte_flow_item_ppp_mask;
10447 /** Dispatch parsed buffer to function calls. */
10449 cmd_set_raw_parsed_sample(const struct buffer *in)
10451 uint32_t n = in->args.vc.actions_n;
10453 struct rte_flow_action *action = NULL;
10454 struct rte_flow_action *data = NULL;
10455 const struct rte_flow_action_rss *rss = NULL;
10457 uint16_t idx = in->port; /* We borrow port field as index */
10458 uint32_t max_size = sizeof(struct rte_flow_action) *
10459 ACTION_SAMPLE_ACTIONS_NUM;
10461 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
10462 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
10463 memset(data, 0x00, max_size);
10464 for (; i <= n - 1; i++) {
10465 action = in->args.vc.actions + i;
10466 if (action->type == RTE_FLOW_ACTION_TYPE_END)
10468 switch (action->type) {
10469 case RTE_FLOW_ACTION_TYPE_MARK:
10470 size = sizeof(struct rte_flow_action_mark);
10471 rte_memcpy(&sample_mark[idx],
10472 (const void *)action->conf, size);
10473 action->conf = &sample_mark[idx];
10475 case RTE_FLOW_ACTION_TYPE_COUNT:
10476 size = sizeof(struct rte_flow_action_count);
10477 rte_memcpy(&sample_count[idx],
10478 (const void *)action->conf, size);
10479 action->conf = &sample_count[idx];
10481 case RTE_FLOW_ACTION_TYPE_QUEUE:
10482 size = sizeof(struct rte_flow_action_queue);
10483 rte_memcpy(&sample_queue[idx],
10484 (const void *)action->conf, size);
10485 action->conf = &sample_queue[idx];
10487 case RTE_FLOW_ACTION_TYPE_RSS:
10488 size = sizeof(struct rte_flow_action_rss);
10489 rss = action->conf;
10490 rte_memcpy(&sample_rss_data[idx].conf,
10491 (const void *)rss, size);
10492 if (rss->key_len && rss->key) {
10493 sample_rss_data[idx].conf.key =
10494 sample_rss_data[idx].key;
10495 rte_memcpy((void *)((uintptr_t)
10496 sample_rss_data[idx].conf.key),
10497 (const void *)rss->key,
10498 sizeof(uint8_t) * rss->key_len);
10500 if (rss->queue_num && rss->queue) {
10501 sample_rss_data[idx].conf.queue =
10502 sample_rss_data[idx].queue;
10503 rte_memcpy((void *)((uintptr_t)
10504 sample_rss_data[idx].conf.queue),
10505 (const void *)rss->queue,
10506 sizeof(uint16_t) * rss->queue_num);
10508 action->conf = &sample_rss_data[idx].conf;
10510 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
10511 size = sizeof(struct rte_flow_action_raw_encap);
10512 rte_memcpy(&sample_encap[idx],
10513 (const void *)action->conf, size);
10514 action->conf = &sample_encap[idx];
10516 case RTE_FLOW_ACTION_TYPE_PORT_ID:
10517 size = sizeof(struct rte_flow_action_port_id);
10518 rte_memcpy(&sample_port_id[idx],
10519 (const void *)action->conf, size);
10520 action->conf = &sample_port_id[idx];
10522 case RTE_FLOW_ACTION_TYPE_PF:
10524 case RTE_FLOW_ACTION_TYPE_VF:
10525 size = sizeof(struct rte_flow_action_vf);
10526 rte_memcpy(&sample_vf[idx],
10527 (const void *)action->conf, size);
10528 action->conf = &sample_vf[idx];
10530 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
10531 size = sizeof(struct rte_flow_action_vxlan_encap);
10532 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
10533 action->conf = &sample_vxlan_encap[idx].conf;
10535 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
10536 size = sizeof(struct rte_flow_action_nvgre_encap);
10537 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
10538 action->conf = &sample_nvgre_encap[idx];
10541 fprintf(stderr, "Error - Not supported action\n");
10544 rte_memcpy(data, action, sizeof(struct rte_flow_action));
10549 /** Dispatch parsed buffer to function calls. */
10551 cmd_set_raw_parsed(const struct buffer *in)
10553 uint32_t n = in->args.vc.pattern_n;
10555 struct rte_flow_item *item = NULL;
10557 uint8_t *data = NULL;
10558 uint8_t *data_tail = NULL;
10559 size_t *total_size = NULL;
10560 uint16_t upper_layer = 0;
10561 uint16_t proto = 0;
10562 uint16_t idx = in->port; /* We borrow port field as index */
10563 int gtp_psc = -1; /* GTP PSC option index. */
10565 if (in->command == SET_SAMPLE_ACTIONS)
10566 return cmd_set_raw_parsed_sample(in);
10567 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
10568 in->command == SET_RAW_DECAP);
10569 if (in->command == SET_RAW_ENCAP) {
10570 total_size = &raw_encap_confs[idx].size;
10571 data = (uint8_t *)&raw_encap_confs[idx].data;
10573 total_size = &raw_decap_confs[idx].size;
10574 data = (uint8_t *)&raw_decap_confs[idx].data;
10577 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
10578 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
10579 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
10580 for (i = n - 1 ; i >= 0; --i) {
10581 const struct rte_flow_item_gtp *gtp;
10582 const struct rte_flow_item_geneve_opt *opt;
10584 item = in->args.vc.pattern + i;
10585 if (item->spec == NULL)
10586 item->spec = flow_item_default_mask(item);
10587 switch (item->type) {
10588 case RTE_FLOW_ITEM_TYPE_ETH:
10589 size = sizeof(struct rte_ether_hdr);
10591 case RTE_FLOW_ITEM_TYPE_VLAN:
10592 size = sizeof(struct rte_vlan_hdr);
10593 proto = RTE_ETHER_TYPE_VLAN;
10595 case RTE_FLOW_ITEM_TYPE_IPV4:
10596 size = sizeof(struct rte_ipv4_hdr);
10597 proto = RTE_ETHER_TYPE_IPV4;
10599 case RTE_FLOW_ITEM_TYPE_IPV6:
10600 size = sizeof(struct rte_ipv6_hdr);
10601 proto = RTE_ETHER_TYPE_IPV6;
10603 case RTE_FLOW_ITEM_TYPE_UDP:
10604 size = sizeof(struct rte_udp_hdr);
10607 case RTE_FLOW_ITEM_TYPE_TCP:
10608 size = sizeof(struct rte_tcp_hdr);
10611 case RTE_FLOW_ITEM_TYPE_VXLAN:
10612 size = sizeof(struct rte_vxlan_hdr);
10614 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10615 size = sizeof(struct rte_vxlan_gpe_hdr);
10617 case RTE_FLOW_ITEM_TYPE_GRE:
10618 size = sizeof(struct rte_gre_hdr);
10621 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
10622 size = sizeof(rte_be32_t);
10625 case RTE_FLOW_ITEM_TYPE_MPLS:
10626 size = sizeof(struct rte_mpls_hdr);
10629 case RTE_FLOW_ITEM_TYPE_NVGRE:
10630 size = sizeof(struct rte_flow_item_nvgre);
10633 case RTE_FLOW_ITEM_TYPE_GENEVE:
10634 size = sizeof(struct rte_geneve_hdr);
10636 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
10637 opt = (const struct rte_flow_item_geneve_opt *)
10639 size = offsetof(struct rte_flow_item_geneve_opt, data);
10640 if (opt->option_len && opt->data) {
10641 *total_size += opt->option_len *
10643 rte_memcpy(data_tail - (*total_size),
10645 opt->option_len * sizeof(uint32_t));
10648 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
10649 size = sizeof(rte_be32_t);
10652 case RTE_FLOW_ITEM_TYPE_ESP:
10653 size = sizeof(struct rte_esp_hdr);
10656 case RTE_FLOW_ITEM_TYPE_AH:
10657 size = sizeof(struct rte_flow_item_ah);
10660 case RTE_FLOW_ITEM_TYPE_GTP:
10662 size = sizeof(struct rte_gtp_hdr);
10665 if (gtp_psc != i + 1) {
10667 "Error - GTP PSC does not follow GTP\n");
10671 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
10672 /* Only E flag should be set. */
10674 "Error - GTP unsupported flags\n");
10677 struct rte_gtp_hdr_ext_word ext_word = {
10681 /* We have to add GTP header extra word. */
10682 *total_size += sizeof(ext_word);
10683 rte_memcpy(data_tail - (*total_size),
10684 &ext_word, sizeof(ext_word));
10686 size = sizeof(struct rte_gtp_hdr);
10688 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
10689 if (gtp_psc >= 0) {
10691 "Error - Multiple GTP PSC items\n");
10694 const struct rte_flow_item_gtp_psc
10698 uint8_t pdu_type:4;
10702 psc.len = sizeof(psc) / 4;
10703 psc.pdu_type = opt->hdr.type;
10704 psc.qfi = opt->hdr.qfi;
10706 *total_size += sizeof(psc);
10707 rte_memcpy(data_tail - (*total_size),
10708 &psc, sizeof(psc));
10713 case RTE_FLOW_ITEM_TYPE_PFCP:
10714 size = sizeof(struct rte_flow_item_pfcp);
10716 case RTE_FLOW_ITEM_TYPE_FLEX:
10717 size = item->spec ?
10718 ((const struct rte_flow_item_flex *)
10719 item->spec)->length : 0;
10721 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
10724 const struct rte_flow_item_gre_opt
10726 if (opt->checksum_rsvd.checksum) {
10728 sizeof(opt->checksum_rsvd);
10729 rte_memcpy(data_tail - (*total_size),
10730 &opt->checksum_rsvd,
10731 sizeof(opt->checksum_rsvd));
10733 if (opt->key.key) {
10734 *total_size += sizeof(opt->key.key);
10735 rte_memcpy(data_tail - (*total_size),
10737 sizeof(opt->key.key));
10739 if (opt->sequence.sequence) {
10740 *total_size += sizeof(opt->sequence.sequence);
10741 rte_memcpy(data_tail - (*total_size),
10742 &opt->sequence.sequence,
10743 sizeof(opt->sequence.sequence));
10749 fprintf(stderr, "Error - Not supported item\n");
10752 *total_size += size;
10753 rte_memcpy(data_tail - (*total_size), item->spec, size);
10754 /* update some fields which cannot be set by cmdline */
10755 update_fields((data_tail - (*total_size)), item,
10757 upper_layer = proto;
10759 if (verbose_level & 0x1)
10760 printf("total data size is %zu\n", (*total_size));
10761 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
10762 memmove(data, (data_tail - (*total_size)), *total_size);
10767 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
10770 /** Populate help strings for current token (cmdline API). */
10772 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
10775 struct context *ctx = &cmd_flow_context;
10776 const struct token *token = &token_list[ctx->prev];
10781 /* Set token type and update global help with details. */
10782 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
10784 cmd_set_raw.help_str = token->help;
10786 cmd_set_raw.help_str = token->name;
10790 /** Token definition template (cmdline API). */
10791 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
10792 .ops = &(struct cmdline_token_ops){
10793 .parse = cmd_flow_parse,
10794 .complete_get_nb = cmd_flow_complete_get_nb,
10795 .complete_get_elt = cmd_flow_complete_get_elt,
10796 .get_help = cmd_set_raw_get_help,
10801 /** Populate the next dynamic token. */
10803 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
10804 cmdline_parse_token_hdr_t **hdr_inst)
10806 struct context *ctx = &cmd_flow_context;
10808 /* Always reinitialize context before requesting the first token. */
10809 if (!(hdr_inst - cmd_set_raw.tokens)) {
10810 cmd_flow_context_init(ctx);
10811 ctx->curr = START_SET;
10813 /* Return NULL when no more tokens are expected. */
10814 if (!ctx->next_num && (ctx->curr != START_SET)) {
10818 /* Determine if command should end here. */
10819 if (ctx->eol && ctx->last && ctx->next_num) {
10820 const enum index *list = ctx->next[ctx->next_num - 1];
10823 for (i = 0; list[i]; ++i) {
10824 if (list[i] != END)
10830 *hdr = &cmd_set_raw_token_hdr;
10833 /** Token generator and output processing callback (cmdline API). */
10835 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
10838 cmd_set_raw_tok(arg0, arg2);
10840 cmd_set_raw_parsed(arg0);
10843 /** Global parser instance (cmdline API). */
10844 cmdline_parse_inst_t cmd_set_raw = {
10845 .f = cmd_set_raw_cb,
10846 .data = NULL, /**< Unused. */
10847 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
10850 }, /**< Tokens are returned by cmd_flow_tok(). */
10853 /* *** display raw_encap/raw_decap buf */
10854 struct cmd_show_set_raw_result {
10855 cmdline_fixed_string_t cmd_show;
10856 cmdline_fixed_string_t cmd_what;
10857 cmdline_fixed_string_t cmd_all;
10858 uint16_t cmd_index;
10862 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
10864 struct cmd_show_set_raw_result *res = parsed_result;
10865 uint16_t index = res->cmd_index;
10867 uint8_t *raw_data = NULL;
10868 size_t raw_size = 0;
10869 char title[16] = {0};
10872 RTE_SET_USED(data);
10873 if (!strcmp(res->cmd_all, "all")) {
10876 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
10877 fprintf(stderr, "index should be 0-%u\n",
10878 RAW_ENCAP_CONFS_MAX_NUM - 1);
10882 if (!strcmp(res->cmd_what, "raw_encap")) {
10883 raw_data = (uint8_t *)&raw_encap_confs[index].data;
10884 raw_size = raw_encap_confs[index].size;
10885 snprintf(title, 16, "\nindex: %u", index);
10886 rte_hexdump(stdout, title, raw_data, raw_size);
10888 raw_data = (uint8_t *)&raw_decap_confs[index].data;
10889 raw_size = raw_decap_confs[index].size;
10890 snprintf(title, 16, "\nindex: %u", index);
10891 rte_hexdump(stdout, title, raw_data, raw_size);
10893 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
10896 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
10897 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
10899 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
10900 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
10901 cmd_what, "raw_encap#raw_decap");
10902 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
10903 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
10904 cmd_index, RTE_UINT16);
10905 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
10906 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
10908 cmdline_parse_inst_t cmd_show_set_raw = {
10909 .f = cmd_show_set_raw_parsed,
10911 .help_str = "show <raw_encap|raw_decap> <index>",
10913 (void *)&cmd_show_set_raw_cmd_show,
10914 (void *)&cmd_show_set_raw_cmd_what,
10915 (void *)&cmd_show_set_raw_cmd_index,
10919 cmdline_parse_inst_t cmd_show_set_raw_all = {
10920 .f = cmd_show_set_raw_parsed,
10922 .help_str = "show <raw_encap|raw_decap> all",
10924 (void *)&cmd_show_set_raw_cmd_show,
10925 (void *)&cmd_show_set_raw_cmd_what,
10926 (void *)&cmd_show_set_raw_cmd_all,