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. */
103 /* Pattern template arguments. */
104 PATTERN_TEMPLATE_CREATE,
105 PATTERN_TEMPLATE_DESTROY,
106 PATTERN_TEMPLATE_CREATE_ID,
107 PATTERN_TEMPLATE_DESTROY_ID,
108 PATTERN_TEMPLATE_RELAXED_MATCHING,
109 PATTERN_TEMPLATE_INGRESS,
110 PATTERN_TEMPLATE_EGRESS,
111 PATTERN_TEMPLATE_TRANSFER,
112 PATTERN_TEMPLATE_SPEC,
114 /* Actions template arguments. */
115 ACTIONS_TEMPLATE_CREATE,
116 ACTIONS_TEMPLATE_DESTROY,
117 ACTIONS_TEMPLATE_CREATE_ID,
118 ACTIONS_TEMPLATE_DESTROY_ID,
119 ACTIONS_TEMPLATE_INGRESS,
120 ACTIONS_TEMPLATE_EGRESS,
121 ACTIONS_TEMPLATE_TRANSFER,
122 ACTIONS_TEMPLATE_SPEC,
123 ACTIONS_TEMPLATE_MASK,
125 /* Queue arguments. */
129 /* Queue create arguments. */
131 QUEUE_CREATE_POSTPONE,
132 QUEUE_TEMPLATE_TABLE,
133 QUEUE_PATTERN_TEMPLATE,
134 QUEUE_ACTIONS_TEMPLATE,
137 /* Queue destroy arguments. */
139 QUEUE_DESTROY_POSTPONE,
141 /* Table arguments. */
152 TABLE_PATTERN_TEMPLATE,
153 TABLE_ACTIONS_TEMPLATE,
155 /* Tunnel arguments. */
162 /* Destroy arguments. */
165 /* Query arguments. */
168 /* List arguments. */
171 /* Destroy aged flow arguments. */
174 /* Validate/create arguments. */
187 /* Configure arguments */
188 CONFIG_QUEUES_NUMBER,
190 CONFIG_COUNTERS_NUMBER,
191 CONFIG_AGING_OBJECTS_NUMBER,
192 CONFIG_METERS_NUMBER,
194 /* Indirect action arguments */
195 INDIRECT_ACTION_CREATE,
196 INDIRECT_ACTION_UPDATE,
197 INDIRECT_ACTION_DESTROY,
198 INDIRECT_ACTION_QUERY,
200 /* Indirect action create arguments */
201 INDIRECT_ACTION_CREATE_ID,
202 INDIRECT_ACTION_INGRESS,
203 INDIRECT_ACTION_EGRESS,
204 INDIRECT_ACTION_TRANSFER,
205 INDIRECT_ACTION_SPEC,
207 /* Indirect action destroy arguments */
208 INDIRECT_ACTION_DESTROY_ID,
210 /* Validate/create pattern. */
238 ITEM_RAW_PATTERN_HEX,
249 ITEM_VLAN_INNER_TYPE,
250 ITEM_VLAN_HAS_MORE_VLAN,
255 ITEM_IPV4_FRAGMENT_OFFSET,
267 ITEM_IPV6_HAS_FRAG_EXT,
287 ITEM_VXLAN_LAST_RSVD,
289 ITEM_E_TAG_GRP_ECID_B,
298 ITEM_GRE_C_RSVD0_VER,
317 ITEM_ARP_ETH_IPV4_SHA,
318 ITEM_ARP_ETH_IPV4_SPA,
319 ITEM_ARP_ETH_IPV4_THA,
320 ITEM_ARP_ETH_IPV4_TPA,
322 ITEM_IPV6_EXT_NEXT_HDR,
324 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
325 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
326 ITEM_IPV6_FRAG_EXT_ID,
331 ITEM_ICMP6_ND_NS_TARGET_ADDR,
333 ITEM_ICMP6_ND_NA_TARGET_ADDR,
335 ITEM_ICMP6_ND_OPT_TYPE,
336 ITEM_ICMP6_ND_OPT_SLA_ETH,
337 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
338 ITEM_ICMP6_ND_OPT_TLA_ETH,
339 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
345 ITEM_GRE_OPTION_CHECKSUM,
347 ITEM_GRE_OPTION_SEQUENCE,
356 ITEM_HIGIG2_CLASSIFICATION,
362 ITEM_L2TPV3OIP_SESSION_ID,
372 ITEM_ECPRI_COMMON_TYPE,
373 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
374 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
375 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
376 ITEM_ECPRI_MSG_IQ_DATA_PCID,
377 ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
378 ITEM_ECPRI_MSG_DLY_MSR_MSRID,
380 ITEM_GENEVE_OPT_CLASS,
381 ITEM_GENEVE_OPT_TYPE,
382 ITEM_GENEVE_OPT_LENGTH,
383 ITEM_GENEVE_OPT_DATA,
385 ITEM_INTEGRITY_LEVEL,
386 ITEM_INTEGRITY_VALUE,
391 ITEM_PORT_REPRESENTOR,
392 ITEM_PORT_REPRESENTOR_PORT_ID,
393 ITEM_REPRESENTED_PORT,
394 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
396 ITEM_FLEX_ITEM_HANDLE,
397 ITEM_FLEX_PATTERN_HANDLE,
400 ITEM_L2TPV2_TYPE_DATA,
401 ITEM_L2TPV2_TYPE_DATA_L,
402 ITEM_L2TPV2_TYPE_DATA_S,
403 ITEM_L2TPV2_TYPE_DATA_O,
404 ITEM_L2TPV2_TYPE_DATA_L_S,
405 ITEM_L2TPV2_TYPE_CTRL,
406 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
407 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
408 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
409 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
410 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
411 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
412 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
413 ITEM_L2TPV2_MSG_DATA_S_NS,
414 ITEM_L2TPV2_MSG_DATA_S_NR,
415 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
416 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
417 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
418 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
419 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
420 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
421 ITEM_L2TPV2_MSG_DATA_L_S_NS,
422 ITEM_L2TPV2_MSG_DATA_L_S_NR,
423 ITEM_L2TPV2_MSG_CTRL_LENGTH,
424 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
425 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
426 ITEM_L2TPV2_MSG_CTRL_NS,
427 ITEM_L2TPV2_MSG_CTRL_NR,
433 /* Validate/create actions. */
452 ACTION_RSS_FUNC_DEFAULT,
453 ACTION_RSS_FUNC_TOEPLITZ,
454 ACTION_RSS_FUNC_SIMPLE_XOR,
455 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
467 ACTION_PHY_PORT_ORIGINAL,
468 ACTION_PHY_PORT_INDEX,
470 ACTION_PORT_ID_ORIGINAL,
474 ACTION_METER_COLOR_TYPE,
475 ACTION_METER_COLOR_GREEN,
476 ACTION_METER_COLOR_YELLOW,
477 ACTION_METER_COLOR_RED,
479 ACTION_OF_SET_MPLS_TTL,
480 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
481 ACTION_OF_DEC_MPLS_TTL,
482 ACTION_OF_SET_NW_TTL,
483 ACTION_OF_SET_NW_TTL_NW_TTL,
484 ACTION_OF_DEC_NW_TTL,
485 ACTION_OF_COPY_TTL_OUT,
486 ACTION_OF_COPY_TTL_IN,
489 ACTION_OF_PUSH_VLAN_ETHERTYPE,
490 ACTION_OF_SET_VLAN_VID,
491 ACTION_OF_SET_VLAN_VID_VLAN_VID,
492 ACTION_OF_SET_VLAN_PCP,
493 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
495 ACTION_OF_POP_MPLS_ETHERTYPE,
497 ACTION_OF_PUSH_MPLS_ETHERTYPE,
504 ACTION_MPLSOGRE_ENCAP,
505 ACTION_MPLSOGRE_DECAP,
506 ACTION_MPLSOUDP_ENCAP,
507 ACTION_MPLSOUDP_DECAP,
509 ACTION_SET_IPV4_SRC_IPV4_SRC,
511 ACTION_SET_IPV4_DST_IPV4_DST,
513 ACTION_SET_IPV6_SRC_IPV6_SRC,
515 ACTION_SET_IPV6_DST_IPV6_DST,
517 ACTION_SET_TP_SRC_TP_SRC,
519 ACTION_SET_TP_DST_TP_DST,
525 ACTION_SET_MAC_SRC_MAC_SRC,
527 ACTION_SET_MAC_DST_MAC_DST,
529 ACTION_INC_TCP_SEQ_VALUE,
531 ACTION_DEC_TCP_SEQ_VALUE,
533 ACTION_INC_TCP_ACK_VALUE,
535 ACTION_DEC_TCP_ACK_VALUE,
538 ACTION_RAW_ENCAP_INDEX,
539 ACTION_RAW_ENCAP_INDEX_VALUE,
540 ACTION_RAW_DECAP_INDEX,
541 ACTION_RAW_DECAP_INDEX_VALUE,
544 ACTION_SET_TAG_INDEX,
547 ACTION_SET_META_DATA,
548 ACTION_SET_META_MASK,
549 ACTION_SET_IPV4_DSCP,
550 ACTION_SET_IPV4_DSCP_VALUE,
551 ACTION_SET_IPV6_DSCP,
552 ACTION_SET_IPV6_DSCP_VALUE,
558 ACTION_SAMPLE_INDEX_VALUE,
560 INDIRECT_ACTION_ID2PTR,
562 ACTION_MODIFY_FIELD_OP,
563 ACTION_MODIFY_FIELD_OP_VALUE,
564 ACTION_MODIFY_FIELD_DST_TYPE,
565 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
566 ACTION_MODIFY_FIELD_DST_LEVEL,
567 ACTION_MODIFY_FIELD_DST_OFFSET,
568 ACTION_MODIFY_FIELD_SRC_TYPE,
569 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
570 ACTION_MODIFY_FIELD_SRC_LEVEL,
571 ACTION_MODIFY_FIELD_SRC_OFFSET,
572 ACTION_MODIFY_FIELD_SRC_VALUE,
573 ACTION_MODIFY_FIELD_SRC_POINTER,
574 ACTION_MODIFY_FIELD_WIDTH,
576 ACTION_CONNTRACK_UPDATE,
577 ACTION_CONNTRACK_UPDATE_DIR,
578 ACTION_CONNTRACK_UPDATE_CTX,
582 ACTION_PORT_REPRESENTOR,
583 ACTION_PORT_REPRESENTOR_PORT_ID,
584 ACTION_REPRESENTED_PORT,
585 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
588 /** Maximum size for pattern in struct rte_flow_item_raw. */
589 #define ITEM_RAW_PATTERN_SIZE 512
591 /** Maximum size for GENEVE option data pattern in bytes. */
592 #define ITEM_GENEVE_OPT_DATA_SIZE 124
594 /** Storage size for struct rte_flow_item_raw including pattern. */
595 #define ITEM_RAW_SIZE \
596 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
598 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
599 #define ACTION_MODIFY_PATTERN_SIZE 32
601 /** Storage size for struct rte_flow_action_modify_field including pattern. */
602 #define ACTION_MODIFY_SIZE \
603 (sizeof(struct rte_flow_action_modify_field) + \
604 ACTION_MODIFY_PATTERN_SIZE)
606 /** Maximum number of queue indices in struct rte_flow_action_rss. */
607 #define ACTION_RSS_QUEUE_NUM 128
609 /** Storage for struct rte_flow_action_rss including external data. */
610 struct action_rss_data {
611 struct rte_flow_action_rss conf;
612 uint8_t key[RSS_HASH_KEY_LENGTH];
613 uint16_t queue[ACTION_RSS_QUEUE_NUM];
616 /** Maximum data size in struct rte_flow_action_raw_encap. */
617 #define ACTION_RAW_ENCAP_MAX_DATA 512
618 #define RAW_ENCAP_CONFS_MAX_NUM 8
620 /** Storage for struct rte_flow_action_raw_encap. */
621 struct raw_encap_conf {
622 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
623 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
627 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
629 /** Storage for struct rte_flow_action_raw_encap including external data. */
630 struct action_raw_encap_data {
631 struct rte_flow_action_raw_encap conf;
632 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
633 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
637 /** Storage for struct rte_flow_action_raw_decap. */
638 struct raw_decap_conf {
639 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
643 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
645 /** Storage for struct rte_flow_action_raw_decap including external data. */
646 struct action_raw_decap_data {
647 struct rte_flow_action_raw_decap conf;
648 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
652 struct vxlan_encap_conf vxlan_encap_conf = {
656 .vni = "\x00\x00\x00",
658 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
659 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
660 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
661 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
662 "\x00\x00\x00\x00\x00\x00\x00\x01",
663 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
664 "\x00\x00\x00\x00\x00\x00\x11\x11",
668 .eth_src = "\x00\x00\x00\x00\x00\x00",
669 .eth_dst = "\xff\xff\xff\xff\xff\xff",
672 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
673 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
675 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
676 struct action_vxlan_encap_data {
677 struct rte_flow_action_vxlan_encap conf;
678 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
679 struct rte_flow_item_eth item_eth;
680 struct rte_flow_item_vlan item_vlan;
682 struct rte_flow_item_ipv4 item_ipv4;
683 struct rte_flow_item_ipv6 item_ipv6;
685 struct rte_flow_item_udp item_udp;
686 struct rte_flow_item_vxlan item_vxlan;
689 struct nvgre_encap_conf nvgre_encap_conf = {
692 .tni = "\x00\x00\x00",
693 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
694 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
695 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
696 "\x00\x00\x00\x00\x00\x00\x00\x01",
697 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
698 "\x00\x00\x00\x00\x00\x00\x11\x11",
700 .eth_src = "\x00\x00\x00\x00\x00\x00",
701 .eth_dst = "\xff\xff\xff\xff\xff\xff",
704 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
705 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
707 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
708 struct action_nvgre_encap_data {
709 struct rte_flow_action_nvgre_encap conf;
710 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
711 struct rte_flow_item_eth item_eth;
712 struct rte_flow_item_vlan item_vlan;
714 struct rte_flow_item_ipv4 item_ipv4;
715 struct rte_flow_item_ipv6 item_ipv6;
717 struct rte_flow_item_nvgre item_nvgre;
720 struct l2_encap_conf l2_encap_conf;
722 struct l2_decap_conf l2_decap_conf;
724 struct mplsogre_encap_conf mplsogre_encap_conf;
726 struct mplsogre_decap_conf mplsogre_decap_conf;
728 struct mplsoudp_encap_conf mplsoudp_encap_conf;
730 struct mplsoudp_decap_conf mplsoudp_decap_conf;
732 struct rte_flow_action_conntrack conntrack_context;
734 #define ACTION_SAMPLE_ACTIONS_NUM 10
735 #define RAW_SAMPLE_CONFS_MAX_NUM 8
736 /** Storage for struct rte_flow_action_sample including external data. */
737 struct action_sample_data {
738 struct rte_flow_action_sample conf;
741 /** Storage for struct rte_flow_action_sample. */
742 struct raw_sample_conf {
743 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
745 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
746 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
747 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
748 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
749 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
750 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
751 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
752 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
753 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
754 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
756 static const char *const modify_field_ops[] = {
757 "set", "add", "sub", NULL
760 static const char *const modify_field_ids[] = {
761 "start", "mac_dst", "mac_src",
762 "vlan_type", "vlan_id", "mac_type",
763 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
764 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
765 "tcp_port_src", "tcp_port_dst",
766 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
767 "udp_port_src", "udp_port_dst",
768 "vxlan_vni", "geneve_vni", "gtp_teid",
769 "tag", "mark", "meta", "pointer", "value", NULL
772 /** Maximum number of subsequent tokens and arguments on the stack. */
773 #define CTX_STACK_SIZE 16
775 /** Parser context. */
777 /** Stack of subsequent token lists to process. */
778 const enum index *next[CTX_STACK_SIZE];
779 /** Arguments for stacked tokens. */
780 const void *args[CTX_STACK_SIZE];
781 enum index curr; /**< Current token index. */
782 enum index prev; /**< Index of the last token seen. */
783 int next_num; /**< Number of entries in next[]. */
784 int args_num; /**< Number of entries in args[]. */
785 uint32_t eol:1; /**< EOL has been detected. */
786 uint32_t last:1; /**< No more arguments. */
787 portid_t port; /**< Current port ID (for completions). */
788 uint32_t objdata; /**< Object-specific data. */
789 void *object; /**< Address of current object for relative offsets. */
790 void *objmask; /**< Object a full mask must be written to. */
793 /** Token argument. */
795 uint32_t hton:1; /**< Use network byte ordering. */
796 uint32_t sign:1; /**< Value is signed. */
797 uint32_t bounded:1; /**< Value is bounded. */
798 uintmax_t min; /**< Minimum value if bounded. */
799 uintmax_t max; /**< Maximum value if bounded. */
800 uint32_t offset; /**< Relative offset from ctx->object. */
801 uint32_t size; /**< Field size. */
802 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
805 /** Parser token definition. */
807 /** Type displayed during completion (defaults to "TOKEN"). */
809 /** Help displayed during completion (defaults to token name). */
811 /** Private data used by parser functions. */
814 * Lists of subsequent tokens to push on the stack. Each call to the
815 * parser consumes the last entry of that stack.
817 const enum index *const *next;
818 /** Arguments stack for subsequent tokens that need them. */
819 const struct arg *const *args;
821 * Token-processing callback, returns -1 in case of error, the
822 * length of the matched string otherwise. If NULL, attempts to
823 * match the token name.
825 * If buf is not NULL, the result should be stored in it according
826 * to context. An error is returned if not large enough.
828 int (*call)(struct context *ctx, const struct token *token,
829 const char *str, unsigned int len,
830 void *buf, unsigned int size);
832 * Callback that provides possible values for this token, used for
833 * completion. Returns -1 in case of error, the number of possible
834 * values otherwise. If NULL, the token name is used.
836 * If buf is not NULL, entry index ent is written to buf and the
837 * full length of the entry is returned (same behavior as
840 int (*comp)(struct context *ctx, const struct token *token,
841 unsigned int ent, char *buf, unsigned int size);
842 /** Mandatory token name, no default value. */
846 /** Static initializer for the next field. */
847 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
849 /** Static initializer for a NEXT() entry. */
850 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
852 /** Static initializer for the args field. */
853 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
855 /** Static initializer for ARGS() to target a field. */
856 #define ARGS_ENTRY(s, f) \
857 (&(const struct arg){ \
858 .offset = offsetof(s, f), \
859 .size = sizeof(((s *)0)->f), \
862 /** Static initializer for ARGS() to target a bit-field. */
863 #define ARGS_ENTRY_BF(s, f, b) \
864 (&(const struct arg){ \
866 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
869 /** Static initializer for ARGS() to target a field with limits. */
870 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
871 (&(const struct arg){ \
875 .offset = offsetof(s, f), \
876 .size = sizeof(((s *)0)->f), \
879 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
880 #define ARGS_ENTRY_MASK(s, f, m) \
881 (&(const struct arg){ \
882 .offset = offsetof(s, f), \
883 .size = sizeof(((s *)0)->f), \
884 .mask = (const void *)(m), \
887 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
888 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
889 (&(const struct arg){ \
891 .offset = offsetof(s, f), \
892 .size = sizeof(((s *)0)->f), \
893 .mask = (const void *)(m), \
896 /** Static initializer for ARGS() to target a pointer. */
897 #define ARGS_ENTRY_PTR(s, f) \
898 (&(const struct arg){ \
899 .size = sizeof(*((s *)0)->f), \
902 /** Static initializer for ARGS() with arbitrary offset and size. */
903 #define ARGS_ENTRY_ARB(o, s) \
904 (&(const struct arg){ \
909 /** Same as ARGS_ENTRY_ARB() with bounded values. */
910 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
911 (&(const struct arg){ \
919 /** Same as ARGS_ENTRY() using network byte ordering. */
920 #define ARGS_ENTRY_HTON(s, f) \
921 (&(const struct arg){ \
923 .offset = offsetof(s, f), \
924 .size = sizeof(((s *)0)->f), \
927 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
928 #define ARG_ENTRY_HTON(s) \
929 (&(const struct arg){ \
935 /** Parser output buffer layout expected by cmd_flow_parsed(). */
937 enum index command; /**< Flow command. */
938 portid_t port; /**< Affected port ID. */
939 queueid_t queue; /** Async queue ID. */
940 bool postpone; /** Postpone async operation */
943 struct rte_flow_port_attr port_attr;
945 struct rte_flow_queue_attr queue_attr;
946 } configure; /**< Configuration arguments. */
948 uint32_t *template_id;
949 uint32_t template_id_n;
950 } templ_destroy; /**< Template destroy arguments. */
953 struct rte_flow_template_table_attr attr;
954 uint32_t *pat_templ_id;
955 uint32_t pat_templ_id_n;
956 uint32_t *act_templ_id;
957 uint32_t act_templ_id_n;
958 } table; /**< Table arguments. */
962 } table_destroy; /**< Template destroy arguments. */
965 uint32_t action_id_n;
966 } ia_destroy; /**< Indirect action destroy arguments. */
969 } ia; /* Indirect action query arguments */
972 uint32_t pat_templ_id;
973 uint32_t act_templ_id;
974 struct rte_flow_attr attr;
975 struct tunnel_ops tunnel_ops;
976 struct rte_flow_item *pattern;
977 struct rte_flow_action *actions;
978 struct rte_flow_action *masks;
982 } vc; /**< Validate/create arguments. */
986 } destroy; /**< Destroy arguments. */
991 } dump; /**< Dump arguments. */
994 struct rte_flow_action action;
995 } query; /**< Query arguments. */
999 } list; /**< List arguments. */
1002 } isolate; /**< Isolated mode arguments. */
1005 } aged; /**< Aged arguments. */
1008 } policy;/**< Policy arguments. */
1013 } flex; /**< Flex arguments*/
1014 } args; /**< Command arguments. */
1017 /** Private data for pattern items. */
1018 struct parse_item_priv {
1019 enum rte_flow_item_type type; /**< Item type. */
1020 uint32_t size; /**< Size of item specification structure. */
1023 #define PRIV_ITEM(t, s) \
1024 (&(const struct parse_item_priv){ \
1025 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
1029 /** Private data for actions. */
1030 struct parse_action_priv {
1031 enum rte_flow_action_type type; /**< Action type. */
1032 uint32_t size; /**< Size of action configuration structure. */
1035 #define PRIV_ACTION(t, s) \
1036 (&(const struct parse_action_priv){ \
1037 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
1041 static const enum index next_flex_item[] = {
1048 static const enum index next_config_attr[] = {
1049 CONFIG_QUEUES_NUMBER,
1051 CONFIG_COUNTERS_NUMBER,
1052 CONFIG_AGING_OBJECTS_NUMBER,
1053 CONFIG_METERS_NUMBER,
1058 static const enum index next_pt_subcmd[] = {
1059 PATTERN_TEMPLATE_CREATE,
1060 PATTERN_TEMPLATE_DESTROY,
1064 static const enum index next_pt_attr[] = {
1065 PATTERN_TEMPLATE_CREATE_ID,
1066 PATTERN_TEMPLATE_RELAXED_MATCHING,
1067 PATTERN_TEMPLATE_INGRESS,
1068 PATTERN_TEMPLATE_EGRESS,
1069 PATTERN_TEMPLATE_TRANSFER,
1070 PATTERN_TEMPLATE_SPEC,
1074 static const enum index next_pt_destroy_attr[] = {
1075 PATTERN_TEMPLATE_DESTROY_ID,
1080 static const enum index next_at_subcmd[] = {
1081 ACTIONS_TEMPLATE_CREATE,
1082 ACTIONS_TEMPLATE_DESTROY,
1086 static const enum index next_at_attr[] = {
1087 ACTIONS_TEMPLATE_CREATE_ID,
1088 ACTIONS_TEMPLATE_INGRESS,
1089 ACTIONS_TEMPLATE_EGRESS,
1090 ACTIONS_TEMPLATE_TRANSFER,
1091 ACTIONS_TEMPLATE_SPEC,
1095 static const enum index next_at_destroy_attr[] = {
1096 ACTIONS_TEMPLATE_DESTROY_ID,
1101 static const enum index next_table_subcmd[] = {
1107 static const enum index next_table_attr[] = {
1115 TABLE_PATTERN_TEMPLATE,
1116 TABLE_ACTIONS_TEMPLATE,
1121 static const enum index next_table_destroy_attr[] = {
1127 static const enum index next_queue_subcmd[] = {
1133 static const enum index next_queue_destroy_attr[] = {
1139 static const enum index next_ia_create_attr[] = {
1140 INDIRECT_ACTION_CREATE_ID,
1141 INDIRECT_ACTION_INGRESS,
1142 INDIRECT_ACTION_EGRESS,
1143 INDIRECT_ACTION_TRANSFER,
1144 INDIRECT_ACTION_SPEC,
1148 static const enum index next_dump_subcmd[] = {
1154 static const enum index next_ia_subcmd[] = {
1155 INDIRECT_ACTION_CREATE,
1156 INDIRECT_ACTION_UPDATE,
1157 INDIRECT_ACTION_DESTROY,
1158 INDIRECT_ACTION_QUERY,
1162 static const enum index next_vc_attr[] = {
1174 static const enum index next_destroy_attr[] = {
1180 static const enum index next_dump_attr[] = {
1186 static const enum index next_list_attr[] = {
1192 static const enum index next_aged_attr[] = {
1198 static const enum index next_ia_destroy_attr[] = {
1199 INDIRECT_ACTION_DESTROY_ID,
1204 static const enum index item_param[] = {
1213 static const enum index next_item[] = {
1250 ITEM_ICMP6_ND_OPT_SLA_ETH,
1251 ITEM_ICMP6_ND_OPT_TLA_ETH,
1258 ITEM_PPPOE_PROTO_ID,
1269 ITEM_PORT_REPRESENTOR,
1270 ITEM_REPRESENTED_PORT,
1278 static const enum index item_fuzzy[] = {
1284 static const enum index item_any[] = {
1290 static const enum index item_vf[] = {
1296 static const enum index item_phy_port[] = {
1297 ITEM_PHY_PORT_INDEX,
1302 static const enum index item_port_id[] = {
1308 static const enum index item_mark[] = {
1314 static const enum index item_raw[] = {
1320 ITEM_RAW_PATTERN_HEX,
1325 static const enum index item_eth[] = {
1334 static const enum index item_vlan[] = {
1339 ITEM_VLAN_INNER_TYPE,
1340 ITEM_VLAN_HAS_MORE_VLAN,
1345 static const enum index item_ipv4[] = {
1349 ITEM_IPV4_FRAGMENT_OFFSET,
1358 static const enum index item_ipv6[] = {
1365 ITEM_IPV6_HAS_FRAG_EXT,
1370 static const enum index item_icmp[] = {
1379 static const enum index item_udp[] = {
1386 static const enum index item_tcp[] = {
1394 static const enum index item_sctp[] = {
1403 static const enum index item_vxlan[] = {
1405 ITEM_VXLAN_LAST_RSVD,
1410 static const enum index item_e_tag[] = {
1411 ITEM_E_TAG_GRP_ECID_B,
1416 static const enum index item_nvgre[] = {
1422 static const enum index item_mpls[] = {
1430 static const enum index item_gre[] = {
1432 ITEM_GRE_C_RSVD0_VER,
1440 static const enum index item_gre_key[] = {
1446 static const enum index item_gre_option[] = {
1447 ITEM_GRE_OPTION_CHECKSUM,
1448 ITEM_GRE_OPTION_KEY,
1449 ITEM_GRE_OPTION_SEQUENCE,
1454 static const enum index item_gtp[] = {
1462 static const enum index item_geneve[] = {
1470 static const enum index item_vxlan_gpe[] = {
1476 static const enum index item_arp_eth_ipv4[] = {
1477 ITEM_ARP_ETH_IPV4_SHA,
1478 ITEM_ARP_ETH_IPV4_SPA,
1479 ITEM_ARP_ETH_IPV4_THA,
1480 ITEM_ARP_ETH_IPV4_TPA,
1485 static const enum index item_ipv6_ext[] = {
1486 ITEM_IPV6_EXT_NEXT_HDR,
1491 static const enum index item_ipv6_frag_ext[] = {
1492 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1493 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1494 ITEM_IPV6_FRAG_EXT_ID,
1499 static const enum index item_icmp6[] = {
1506 static const enum index item_icmp6_nd_ns[] = {
1507 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1512 static const enum index item_icmp6_nd_na[] = {
1513 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1518 static const enum index item_icmp6_nd_opt[] = {
1519 ITEM_ICMP6_ND_OPT_TYPE,
1524 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1525 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1530 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1531 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1536 static const enum index item_meta[] = {
1542 static const enum index item_gtp_psc[] = {
1549 static const enum index item_pppoed[] = {
1555 static const enum index item_pppoes[] = {
1561 static const enum index item_pppoe_proto_id[] = {
1566 static const enum index item_higig2[] = {
1567 ITEM_HIGIG2_CLASSIFICATION,
1573 static const enum index item_esp[] = {
1579 static const enum index item_ah[] = {
1585 static const enum index item_pfcp[] = {
1592 static const enum index next_set_raw[] = {
1598 static const enum index item_tag[] = {
1605 static const enum index item_l2tpv3oip[] = {
1606 ITEM_L2TPV3OIP_SESSION_ID,
1611 static const enum index item_ecpri[] = {
1617 static const enum index item_ecpri_common[] = {
1618 ITEM_ECPRI_COMMON_TYPE,
1622 static const enum index item_ecpri_common_type[] = {
1623 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1624 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1625 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1629 static const enum index item_geneve_opt[] = {
1630 ITEM_GENEVE_OPT_CLASS,
1631 ITEM_GENEVE_OPT_TYPE,
1632 ITEM_GENEVE_OPT_LENGTH,
1633 ITEM_GENEVE_OPT_DATA,
1638 static const enum index item_integrity[] = {
1639 ITEM_INTEGRITY_LEVEL,
1640 ITEM_INTEGRITY_VALUE,
1644 static const enum index item_integrity_lv[] = {
1645 ITEM_INTEGRITY_LEVEL,
1646 ITEM_INTEGRITY_VALUE,
1651 static const enum index item_port_representor[] = {
1652 ITEM_PORT_REPRESENTOR_PORT_ID,
1657 static const enum index item_represented_port[] = {
1658 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1663 static const enum index item_flex[] = {
1664 ITEM_FLEX_PATTERN_HANDLE,
1665 ITEM_FLEX_ITEM_HANDLE,
1670 static const enum index item_l2tpv2[] = {
1676 static const enum index item_l2tpv2_type[] = {
1677 ITEM_L2TPV2_TYPE_DATA,
1678 ITEM_L2TPV2_TYPE_DATA_L,
1679 ITEM_L2TPV2_TYPE_DATA_S,
1680 ITEM_L2TPV2_TYPE_DATA_O,
1681 ITEM_L2TPV2_TYPE_DATA_L_S,
1682 ITEM_L2TPV2_TYPE_CTRL,
1686 static const enum index item_l2tpv2_type_data[] = {
1687 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1688 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1693 static const enum index item_l2tpv2_type_data_l[] = {
1694 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1695 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1696 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1701 static const enum index item_l2tpv2_type_data_s[] = {
1702 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1703 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1704 ITEM_L2TPV2_MSG_DATA_S_NS,
1705 ITEM_L2TPV2_MSG_DATA_S_NR,
1710 static const enum index item_l2tpv2_type_data_o[] = {
1711 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1712 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1713 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1718 static const enum index item_l2tpv2_type_data_l_s[] = {
1719 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1720 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1721 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1722 ITEM_L2TPV2_MSG_DATA_L_S_NS,
1723 ITEM_L2TPV2_MSG_DATA_L_S_NR,
1728 static const enum index item_l2tpv2_type_ctrl[] = {
1729 ITEM_L2TPV2_MSG_CTRL_LENGTH,
1730 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1731 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1732 ITEM_L2TPV2_MSG_CTRL_NS,
1733 ITEM_L2TPV2_MSG_CTRL_NR,
1738 static const enum index item_ppp[] = {
1746 static const enum index next_action[] = {
1763 ACTION_OF_SET_MPLS_TTL,
1764 ACTION_OF_DEC_MPLS_TTL,
1765 ACTION_OF_SET_NW_TTL,
1766 ACTION_OF_DEC_NW_TTL,
1767 ACTION_OF_COPY_TTL_OUT,
1768 ACTION_OF_COPY_TTL_IN,
1770 ACTION_OF_PUSH_VLAN,
1771 ACTION_OF_SET_VLAN_VID,
1772 ACTION_OF_SET_VLAN_PCP,
1774 ACTION_OF_PUSH_MPLS,
1781 ACTION_MPLSOGRE_ENCAP,
1782 ACTION_MPLSOGRE_DECAP,
1783 ACTION_MPLSOUDP_ENCAP,
1784 ACTION_MPLSOUDP_DECAP,
1785 ACTION_SET_IPV4_SRC,
1786 ACTION_SET_IPV4_DST,
1787 ACTION_SET_IPV6_SRC,
1788 ACTION_SET_IPV6_DST,
1804 ACTION_SET_IPV4_DSCP,
1805 ACTION_SET_IPV6_DSCP,
1809 ACTION_MODIFY_FIELD,
1811 ACTION_CONNTRACK_UPDATE,
1812 ACTION_PORT_REPRESENTOR,
1813 ACTION_REPRESENTED_PORT,
1817 static const enum index action_mark[] = {
1823 static const enum index action_queue[] = {
1829 static const enum index action_count[] = {
1835 static const enum index action_rss[] = {
1846 static const enum index action_vf[] = {
1853 static const enum index action_phy_port[] = {
1854 ACTION_PHY_PORT_ORIGINAL,
1855 ACTION_PHY_PORT_INDEX,
1860 static const enum index action_port_id[] = {
1861 ACTION_PORT_ID_ORIGINAL,
1867 static const enum index action_meter[] = {
1873 static const enum index action_meter_color[] = {
1874 ACTION_METER_COLOR_TYPE,
1879 static const enum index action_of_set_mpls_ttl[] = {
1880 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1885 static const enum index action_of_set_nw_ttl[] = {
1886 ACTION_OF_SET_NW_TTL_NW_TTL,
1891 static const enum index action_of_push_vlan[] = {
1892 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1897 static const enum index action_of_set_vlan_vid[] = {
1898 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1903 static const enum index action_of_set_vlan_pcp[] = {
1904 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1909 static const enum index action_of_pop_mpls[] = {
1910 ACTION_OF_POP_MPLS_ETHERTYPE,
1915 static const enum index action_of_push_mpls[] = {
1916 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1921 static const enum index action_set_ipv4_src[] = {
1922 ACTION_SET_IPV4_SRC_IPV4_SRC,
1927 static const enum index action_set_mac_src[] = {
1928 ACTION_SET_MAC_SRC_MAC_SRC,
1933 static const enum index action_set_ipv4_dst[] = {
1934 ACTION_SET_IPV4_DST_IPV4_DST,
1939 static const enum index action_set_ipv6_src[] = {
1940 ACTION_SET_IPV6_SRC_IPV6_SRC,
1945 static const enum index action_set_ipv6_dst[] = {
1946 ACTION_SET_IPV6_DST_IPV6_DST,
1951 static const enum index action_set_tp_src[] = {
1952 ACTION_SET_TP_SRC_TP_SRC,
1957 static const enum index action_set_tp_dst[] = {
1958 ACTION_SET_TP_DST_TP_DST,
1963 static const enum index action_set_ttl[] = {
1969 static const enum index action_jump[] = {
1975 static const enum index action_set_mac_dst[] = {
1976 ACTION_SET_MAC_DST_MAC_DST,
1981 static const enum index action_inc_tcp_seq[] = {
1982 ACTION_INC_TCP_SEQ_VALUE,
1987 static const enum index action_dec_tcp_seq[] = {
1988 ACTION_DEC_TCP_SEQ_VALUE,
1993 static const enum index action_inc_tcp_ack[] = {
1994 ACTION_INC_TCP_ACK_VALUE,
1999 static const enum index action_dec_tcp_ack[] = {
2000 ACTION_DEC_TCP_ACK_VALUE,
2005 static const enum index action_raw_encap[] = {
2006 ACTION_RAW_ENCAP_INDEX,
2011 static const enum index action_raw_decap[] = {
2012 ACTION_RAW_DECAP_INDEX,
2017 static const enum index action_set_tag[] = {
2018 ACTION_SET_TAG_DATA,
2019 ACTION_SET_TAG_INDEX,
2020 ACTION_SET_TAG_MASK,
2025 static const enum index action_set_meta[] = {
2026 ACTION_SET_META_DATA,
2027 ACTION_SET_META_MASK,
2032 static const enum index action_set_ipv4_dscp[] = {
2033 ACTION_SET_IPV4_DSCP_VALUE,
2038 static const enum index action_set_ipv6_dscp[] = {
2039 ACTION_SET_IPV6_DSCP_VALUE,
2044 static const enum index action_age[] = {
2051 static const enum index action_sample[] = {
2053 ACTION_SAMPLE_RATIO,
2054 ACTION_SAMPLE_INDEX,
2059 static const enum index next_action_sample[] = {
2072 static const enum index action_modify_field_dst[] = {
2073 ACTION_MODIFY_FIELD_DST_LEVEL,
2074 ACTION_MODIFY_FIELD_DST_OFFSET,
2075 ACTION_MODIFY_FIELD_SRC_TYPE,
2079 static const enum index action_modify_field_src[] = {
2080 ACTION_MODIFY_FIELD_SRC_LEVEL,
2081 ACTION_MODIFY_FIELD_SRC_OFFSET,
2082 ACTION_MODIFY_FIELD_SRC_VALUE,
2083 ACTION_MODIFY_FIELD_SRC_POINTER,
2084 ACTION_MODIFY_FIELD_WIDTH,
2088 static const enum index action_update_conntrack[] = {
2089 ACTION_CONNTRACK_UPDATE_DIR,
2090 ACTION_CONNTRACK_UPDATE_CTX,
2095 static const enum index action_port_representor[] = {
2096 ACTION_PORT_REPRESENTOR_PORT_ID,
2101 static const enum index action_represented_port[] = {
2102 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2107 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2108 const char *, unsigned int,
2109 void *, unsigned int);
2110 static int parse_set_sample_action(struct context *, const struct token *,
2111 const char *, unsigned int,
2112 void *, unsigned int);
2113 static int parse_set_init(struct context *, const struct token *,
2114 const char *, unsigned int,
2115 void *, unsigned int);
2117 parse_flex_handle(struct context *, const struct token *,
2118 const char *, unsigned int, void *, unsigned int);
2119 static int parse_init(struct context *, const struct token *,
2120 const char *, unsigned int,
2121 void *, unsigned int);
2122 static int parse_vc(struct context *, const struct token *,
2123 const char *, unsigned int,
2124 void *, unsigned int);
2125 static int parse_vc_spec(struct context *, const struct token *,
2126 const char *, unsigned int, void *, unsigned int);
2127 static int parse_vc_conf(struct context *, const struct token *,
2128 const char *, unsigned int, void *, unsigned int);
2129 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2130 const char *, unsigned int,
2131 void *, unsigned int);
2132 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2133 const char *, unsigned int,
2134 void *, unsigned int);
2135 static int parse_vc_action_meter_color_type(struct context *,
2136 const struct token *,
2137 const char *, unsigned int, void *,
2139 static int parse_vc_action_rss(struct context *, const struct token *,
2140 const char *, unsigned int, void *,
2142 static int parse_vc_action_rss_func(struct context *, const struct token *,
2143 const char *, unsigned int, void *,
2145 static int parse_vc_action_rss_type(struct context *, const struct token *,
2146 const char *, unsigned int, void *,
2148 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2149 const char *, unsigned int, void *,
2151 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2152 const char *, unsigned int, void *,
2154 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2155 const char *, unsigned int, void *,
2157 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2158 const char *, unsigned int, void *,
2160 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2161 const char *, unsigned int, void *,
2163 static int parse_vc_action_mplsogre_encap(struct context *,
2164 const struct token *, const char *,
2165 unsigned int, void *, unsigned int);
2166 static int parse_vc_action_mplsogre_decap(struct context *,
2167 const struct token *, const char *,
2168 unsigned int, void *, unsigned int);
2169 static int parse_vc_action_mplsoudp_encap(struct context *,
2170 const struct token *, const char *,
2171 unsigned int, void *, unsigned int);
2172 static int parse_vc_action_mplsoudp_decap(struct context *,
2173 const struct token *, const char *,
2174 unsigned int, void *, unsigned int);
2175 static int parse_vc_action_raw_encap(struct context *,
2176 const struct token *, const char *,
2177 unsigned int, void *, unsigned int);
2178 static int parse_vc_action_raw_decap(struct context *,
2179 const struct token *, const char *,
2180 unsigned int, void *, unsigned int);
2181 static int parse_vc_action_raw_encap_index(struct context *,
2182 const struct token *, const char *,
2183 unsigned int, void *, unsigned int);
2184 static int parse_vc_action_raw_decap_index(struct context *,
2185 const struct token *, const char *,
2186 unsigned int, void *, unsigned int);
2187 static int parse_vc_action_set_meta(struct context *ctx,
2188 const struct token *token, const char *str,
2189 unsigned int len, void *buf,
2191 static int parse_vc_action_sample(struct context *ctx,
2192 const struct token *token, const char *str,
2193 unsigned int len, void *buf,
2196 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2197 const char *str, unsigned int len, void *buf,
2200 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2201 const char *str, unsigned int len, void *buf,
2204 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2205 const char *str, unsigned int len, void *buf,
2208 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2209 const char *str, unsigned int len, void *buf,
2211 static int parse_destroy(struct context *, const struct token *,
2212 const char *, unsigned int,
2213 void *, unsigned int);
2214 static int parse_flush(struct context *, const struct token *,
2215 const char *, unsigned int,
2216 void *, unsigned int);
2217 static int parse_dump(struct context *, const struct token *,
2218 const char *, unsigned int,
2219 void *, unsigned int);
2220 static int parse_query(struct context *, const struct token *,
2221 const char *, unsigned int,
2222 void *, unsigned int);
2223 static int parse_action(struct context *, const struct token *,
2224 const char *, unsigned int,
2225 void *, unsigned int);
2226 static int parse_list(struct context *, const struct token *,
2227 const char *, unsigned int,
2228 void *, unsigned int);
2229 static int parse_aged(struct context *, const struct token *,
2230 const char *, unsigned int,
2231 void *, unsigned int);
2232 static int parse_isolate(struct context *, const struct token *,
2233 const char *, unsigned int,
2234 void *, unsigned int);
2235 static int parse_configure(struct context *, const struct token *,
2236 const char *, unsigned int,
2237 void *, unsigned int);
2238 static int parse_template(struct context *, const struct token *,
2239 const char *, unsigned int,
2240 void *, unsigned int);
2241 static int parse_template_destroy(struct context *, const struct token *,
2242 const char *, unsigned int,
2243 void *, unsigned int);
2244 static int parse_table(struct context *, const struct token *,
2245 const char *, unsigned int, void *, unsigned int);
2246 static int parse_table_destroy(struct context *, const struct token *,
2247 const char *, unsigned int,
2248 void *, unsigned int);
2249 static int parse_qo(struct context *, const struct token *,
2250 const char *, unsigned int,
2251 void *, unsigned int);
2252 static int parse_qo_destroy(struct context *, const struct token *,
2253 const char *, unsigned int,
2254 void *, unsigned int);
2255 static int parse_tunnel(struct context *, const struct token *,
2256 const char *, unsigned int,
2257 void *, unsigned int);
2258 static int parse_flex(struct context *, const struct token *,
2259 const char *, unsigned int, void *, unsigned int);
2260 static int parse_int(struct context *, const struct token *,
2261 const char *, unsigned int,
2262 void *, unsigned int);
2263 static int parse_prefix(struct context *, const struct token *,
2264 const char *, unsigned int,
2265 void *, unsigned int);
2266 static int parse_boolean(struct context *, const struct token *,
2267 const char *, unsigned int,
2268 void *, unsigned int);
2269 static int parse_string(struct context *, const struct token *,
2270 const char *, unsigned int,
2271 void *, unsigned int);
2272 static int parse_hex(struct context *ctx, const struct token *token,
2273 const char *str, unsigned int len,
2274 void *buf, unsigned int size);
2275 static int parse_string0(struct context *, const struct token *,
2276 const char *, unsigned int,
2277 void *, unsigned int);
2278 static int parse_mac_addr(struct context *, const struct token *,
2279 const char *, unsigned int,
2280 void *, unsigned int);
2281 static int parse_ipv4_addr(struct context *, const struct token *,
2282 const char *, unsigned int,
2283 void *, unsigned int);
2284 static int parse_ipv6_addr(struct context *, const struct token *,
2285 const char *, unsigned int,
2286 void *, unsigned int);
2287 static int parse_port(struct context *, const struct token *,
2288 const char *, unsigned int,
2289 void *, unsigned int);
2290 static int parse_ia(struct context *, const struct token *,
2291 const char *, unsigned int,
2292 void *, unsigned int);
2293 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2294 const char *str, unsigned int len,
2295 void *buf, unsigned int size);
2296 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2297 const char *str, unsigned int len, void *buf,
2299 static int parse_mp(struct context *, const struct token *,
2300 const char *, unsigned int,
2301 void *, unsigned int);
2302 static int comp_none(struct context *, const struct token *,
2303 unsigned int, char *, unsigned int);
2304 static int comp_boolean(struct context *, const struct token *,
2305 unsigned int, char *, unsigned int);
2306 static int comp_action(struct context *, const struct token *,
2307 unsigned int, char *, unsigned int);
2308 static int comp_port(struct context *, const struct token *,
2309 unsigned int, char *, unsigned int);
2310 static int comp_rule_id(struct context *, const struct token *,
2311 unsigned int, char *, unsigned int);
2312 static int comp_vc_action_rss_type(struct context *, const struct token *,
2313 unsigned int, char *, unsigned int);
2314 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2315 unsigned int, char *, unsigned int);
2316 static int comp_set_raw_index(struct context *, const struct token *,
2317 unsigned int, char *, unsigned int);
2318 static int comp_set_sample_index(struct context *, const struct token *,
2319 unsigned int, char *, unsigned int);
2320 static int comp_set_modify_field_op(struct context *, const struct token *,
2321 unsigned int, char *, unsigned int);
2322 static int comp_set_modify_field_id(struct context *, const struct token *,
2323 unsigned int, char *, unsigned int);
2324 static int comp_pattern_template_id(struct context *, const struct token *,
2325 unsigned int, char *, unsigned int);
2326 static int comp_actions_template_id(struct context *, const struct token *,
2327 unsigned int, char *, unsigned int);
2328 static int comp_table_id(struct context *, const struct token *,
2329 unsigned int, char *, unsigned int);
2330 static int comp_queue_id(struct context *, const struct token *,
2331 unsigned int, char *, unsigned int);
2333 /** Token definitions. */
2334 static const struct token token_list[] = {
2335 /* Special tokens. */
2338 .help = "null entry, abused as the entry point",
2339 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2344 .help = "command may end here",
2347 .name = "START_SET",
2348 .help = "null entry, abused as the entry point for set",
2349 .next = NEXT(NEXT_ENTRY(SET)),
2354 .help = "set command may end here",
2356 /* Common tokens. */
2357 [COMMON_INTEGER] = {
2360 .help = "integer value",
2364 [COMMON_UNSIGNED] = {
2365 .name = "{unsigned}",
2367 .help = "unsigned integer value",
2374 .help = "prefix length for bit-mask",
2375 .call = parse_prefix,
2378 [COMMON_BOOLEAN] = {
2379 .name = "{boolean}",
2381 .help = "any boolean value",
2382 .call = parse_boolean,
2383 .comp = comp_boolean,
2388 .help = "fixed string",
2389 .call = parse_string,
2395 .help = "fixed string",
2398 [COMMON_FILE_PATH] = {
2399 .name = "{file path}",
2401 .help = "file path",
2402 .call = parse_string0,
2405 [COMMON_MAC_ADDR] = {
2406 .name = "{MAC address}",
2408 .help = "standard MAC address notation",
2409 .call = parse_mac_addr,
2412 [COMMON_IPV4_ADDR] = {
2413 .name = "{IPv4 address}",
2414 .type = "IPV4 ADDRESS",
2415 .help = "standard IPv4 address notation",
2416 .call = parse_ipv4_addr,
2419 [COMMON_IPV6_ADDR] = {
2420 .name = "{IPv6 address}",
2421 .type = "IPV6 ADDRESS",
2422 .help = "standard IPv6 address notation",
2423 .call = parse_ipv6_addr,
2426 [COMMON_RULE_ID] = {
2427 .name = "{rule id}",
2429 .help = "rule identifier",
2431 .comp = comp_rule_id,
2433 [COMMON_PORT_ID] = {
2434 .name = "{port_id}",
2436 .help = "port identifier",
2440 [COMMON_GROUP_ID] = {
2441 .name = "{group_id}",
2443 .help = "group identifier",
2447 [COMMON_PRIORITY_LEVEL] = {
2450 .help = "priority level",
2454 [COMMON_INDIRECT_ACTION_ID] = {
2455 .name = "{indirect_action_id}",
2456 .type = "INDIRECT_ACTION_ID",
2457 .help = "indirect action id",
2461 [COMMON_POLICY_ID] = {
2462 .name = "{policy_id}",
2463 .type = "POLICY_ID",
2464 .help = "policy id",
2468 [COMMON_FLEX_TOKEN] = {
2469 .name = "{flex token}",
2470 .type = "flex token",
2471 .help = "flex token",
2475 [COMMON_FLEX_HANDLE] = {
2476 .name = "{flex handle}",
2477 .type = "FLEX HANDLE",
2478 .help = "fill flex item data",
2479 .call = parse_flex_handle,
2482 [COMMON_PATTERN_TEMPLATE_ID] = {
2483 .name = "{pattern_template_id}",
2484 .type = "PATTERN_TEMPLATE_ID",
2485 .help = "pattern template id",
2487 .comp = comp_pattern_template_id,
2489 [COMMON_ACTIONS_TEMPLATE_ID] = {
2490 .name = "{actions_template_id}",
2491 .type = "ACTIONS_TEMPLATE_ID",
2492 .help = "actions template id",
2494 .comp = comp_actions_template_id,
2496 [COMMON_TABLE_ID] = {
2497 .name = "{table_id}",
2501 .comp = comp_table_id,
2503 [COMMON_QUEUE_ID] = {
2504 .name = "{queue_id}",
2508 .comp = comp_queue_id,
2510 /* Top-level command. */
2513 .type = "{command} {port_id} [{arg} [...]]",
2514 .help = "manage ingress/egress flow rules",
2515 .next = NEXT(NEXT_ENTRY
2536 /* Top-level command. */
2539 .help = "get information about flow engine",
2540 .next = NEXT(NEXT_ENTRY(END),
2541 NEXT_ENTRY(COMMON_PORT_ID)),
2542 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2543 .call = parse_configure,
2545 /* Top-level command. */
2547 .name = "configure",
2548 .help = "configure flow engine",
2549 .next = NEXT(next_config_attr,
2550 NEXT_ENTRY(COMMON_PORT_ID)),
2551 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2552 .call = parse_configure,
2554 /* Configure arguments. */
2555 [CONFIG_QUEUES_NUMBER] = {
2556 .name = "queues_number",
2557 .help = "number of queues",
2558 .next = NEXT(next_config_attr,
2559 NEXT_ENTRY(COMMON_UNSIGNED)),
2560 .args = ARGS(ARGS_ENTRY(struct buffer,
2561 args.configure.nb_queue)),
2563 [CONFIG_QUEUES_SIZE] = {
2564 .name = "queues_size",
2565 .help = "number of elements in queues",
2566 .next = NEXT(next_config_attr,
2567 NEXT_ENTRY(COMMON_UNSIGNED)),
2568 .args = ARGS(ARGS_ENTRY(struct buffer,
2569 args.configure.queue_attr.size)),
2571 [CONFIG_COUNTERS_NUMBER] = {
2572 .name = "counters_number",
2573 .help = "number of counters",
2574 .next = NEXT(next_config_attr,
2575 NEXT_ENTRY(COMMON_UNSIGNED)),
2576 .args = ARGS(ARGS_ENTRY(struct buffer,
2577 args.configure.port_attr.nb_counters)),
2579 [CONFIG_AGING_OBJECTS_NUMBER] = {
2580 .name = "aging_counters_number",
2581 .help = "number of aging objects",
2582 .next = NEXT(next_config_attr,
2583 NEXT_ENTRY(COMMON_UNSIGNED)),
2584 .args = ARGS(ARGS_ENTRY(struct buffer,
2585 args.configure.port_attr.nb_aging_objects)),
2587 [CONFIG_METERS_NUMBER] = {
2588 .name = "meters_number",
2589 .help = "number of meters",
2590 .next = NEXT(next_config_attr,
2591 NEXT_ENTRY(COMMON_UNSIGNED)),
2592 .args = ARGS(ARGS_ENTRY(struct buffer,
2593 args.configure.port_attr.nb_meters)),
2595 /* Top-level command. */
2596 [PATTERN_TEMPLATE] = {
2597 .name = "pattern_template",
2598 .type = "{command} {port_id} [{arg} [...]]",
2599 .help = "manage pattern templates",
2600 .next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2601 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2602 .call = parse_template,
2604 /* Sub-level commands. */
2605 [PATTERN_TEMPLATE_CREATE] = {
2607 .help = "create pattern template",
2608 .next = NEXT(next_pt_attr),
2609 .call = parse_template,
2611 [PATTERN_TEMPLATE_DESTROY] = {
2613 .help = "destroy pattern template",
2614 .next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
2615 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2616 .call = parse_template_destroy,
2618 /* Pattern template arguments. */
2619 [PATTERN_TEMPLATE_CREATE_ID] = {
2620 .name = "pattern_template_id",
2621 .help = "specify a pattern template id to create",
2622 .next = NEXT(next_pt_attr,
2623 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2624 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
2626 [PATTERN_TEMPLATE_DESTROY_ID] = {
2627 .name = "pattern_template",
2628 .help = "specify a pattern template id to destroy",
2629 .next = NEXT(next_pt_destroy_attr,
2630 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2631 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2632 args.templ_destroy.template_id)),
2633 .call = parse_template_destroy,
2635 [PATTERN_TEMPLATE_RELAXED_MATCHING] = {
2637 .help = "is matching relaxed",
2638 .next = NEXT(next_pt_attr,
2639 NEXT_ENTRY(COMMON_BOOLEAN)),
2640 .args = ARGS(ARGS_ENTRY_BF(struct buffer,
2641 args.vc.attr.reserved, 1)),
2643 [PATTERN_TEMPLATE_INGRESS] = {
2645 .help = "attribute pattern to ingress",
2646 .next = NEXT(next_pt_attr),
2647 .call = parse_template,
2649 [PATTERN_TEMPLATE_EGRESS] = {
2651 .help = "attribute pattern to egress",
2652 .next = NEXT(next_pt_attr),
2653 .call = parse_template,
2655 [PATTERN_TEMPLATE_TRANSFER] = {
2657 .help = "attribute pattern to transfer",
2658 .next = NEXT(next_pt_attr),
2659 .call = parse_template,
2661 [PATTERN_TEMPLATE_SPEC] = {
2663 .help = "specify item to create pattern template",
2664 .next = NEXT(next_item),
2666 /* Top-level command. */
2667 [ACTIONS_TEMPLATE] = {
2668 .name = "actions_template",
2669 .type = "{command} {port_id} [{arg} [...]]",
2670 .help = "manage actions templates",
2671 .next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2672 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2673 .call = parse_template,
2675 /* Sub-level commands. */
2676 [ACTIONS_TEMPLATE_CREATE] = {
2678 .help = "create actions template",
2679 .next = NEXT(next_at_attr),
2680 .call = parse_template,
2682 [ACTIONS_TEMPLATE_DESTROY] = {
2684 .help = "destroy actions template",
2685 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
2686 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2687 .call = parse_template_destroy,
2689 /* Actions template arguments. */
2690 [ACTIONS_TEMPLATE_CREATE_ID] = {
2691 .name = "actions_template_id",
2692 .help = "specify an actions template id to create",
2693 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
2694 NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
2695 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2696 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
2698 [ACTIONS_TEMPLATE_DESTROY_ID] = {
2699 .name = "actions_template",
2700 .help = "specify an actions template id to destroy",
2701 .next = NEXT(next_at_destroy_attr,
2702 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2703 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2704 args.templ_destroy.template_id)),
2705 .call = parse_template_destroy,
2707 [ACTIONS_TEMPLATE_INGRESS] = {
2709 .help = "attribute actions to ingress",
2710 .next = NEXT(next_at_attr),
2711 .call = parse_template,
2713 [ACTIONS_TEMPLATE_EGRESS] = {
2715 .help = "attribute actions to egress",
2716 .next = NEXT(next_at_attr),
2717 .call = parse_template,
2719 [ACTIONS_TEMPLATE_TRANSFER] = {
2721 .help = "attribute actions to transfer",
2722 .next = NEXT(next_at_attr),
2723 .call = parse_template,
2725 [ACTIONS_TEMPLATE_SPEC] = {
2727 .help = "specify action to create actions template",
2728 .next = NEXT(next_action),
2729 .call = parse_template,
2731 [ACTIONS_TEMPLATE_MASK] = {
2733 .help = "specify action mask to create actions template",
2734 .next = NEXT(next_action),
2735 .call = parse_template,
2737 /* Top-level command. */
2739 .name = "template_table",
2740 .type = "{command} {port_id} [{arg} [...]]",
2741 .help = "manage template tables",
2742 .next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2743 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2744 .call = parse_table,
2746 /* Sub-level commands. */
2749 .help = "create template table",
2750 .next = NEXT(next_table_attr),
2751 .call = parse_table,
2755 .help = "destroy template table",
2756 .next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
2757 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2758 .call = parse_table_destroy,
2760 /* Table arguments. */
2761 [TABLE_CREATE_ID] = {
2763 .help = "specify table id to create",
2764 .next = NEXT(next_table_attr,
2765 NEXT_ENTRY(COMMON_TABLE_ID)),
2766 .args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
2768 [TABLE_DESTROY_ID] = {
2770 .help = "specify table id to destroy",
2771 .next = NEXT(next_table_destroy_attr,
2772 NEXT_ENTRY(COMMON_TABLE_ID)),
2773 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2774 args.table_destroy.table_id)),
2775 .call = parse_table_destroy,
2779 .help = "specify a group",
2780 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2781 .args = ARGS(ARGS_ENTRY(struct buffer,
2782 args.table.attr.flow_attr.group)),
2784 [TABLE_PRIORITY] = {
2786 .help = "specify a priority level",
2787 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2788 .args = ARGS(ARGS_ENTRY(struct buffer,
2789 args.table.attr.flow_attr.priority)),
2793 .help = "affect rule to egress",
2794 .next = NEXT(next_table_attr),
2795 .call = parse_table,
2799 .help = "affect rule to ingress",
2800 .next = NEXT(next_table_attr),
2801 .call = parse_table,
2803 [TABLE_TRANSFER] = {
2805 .help = "affect rule to transfer",
2806 .next = NEXT(next_table_attr),
2807 .call = parse_table,
2809 [TABLE_RULES_NUMBER] = {
2810 .name = "rules_number",
2811 .help = "number of rules in table",
2812 .next = NEXT(next_table_attr,
2813 NEXT_ENTRY(COMMON_UNSIGNED)),
2814 .args = ARGS(ARGS_ENTRY(struct buffer,
2815 args.table.attr.nb_flows)),
2817 [TABLE_PATTERN_TEMPLATE] = {
2818 .name = "pattern_template",
2819 .help = "specify pattern template id",
2820 .next = NEXT(next_table_attr,
2821 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
2822 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2823 args.table.pat_templ_id)),
2824 .call = parse_table,
2826 [TABLE_ACTIONS_TEMPLATE] = {
2827 .name = "actions_template",
2828 .help = "specify actions template id",
2829 .next = NEXT(next_table_attr,
2830 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
2831 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2832 args.table.act_templ_id)),
2833 .call = parse_table,
2835 /* Top-level command. */
2838 .help = "queue a flow rule operation",
2839 .next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2840 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2843 /* Sub-level commands. */
2846 .help = "create a flow rule",
2847 .next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
2848 NEXT_ENTRY(COMMON_QUEUE_ID)),
2849 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2854 .help = "destroy a flow rule",
2855 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
2856 NEXT_ENTRY(COMMON_QUEUE_ID)),
2857 .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
2858 .call = parse_qo_destroy,
2860 /* Queue arguments. */
2861 [QUEUE_TEMPLATE_TABLE] = {
2862 .name = "template table",
2863 .help = "specify table id",
2864 .next = NEXT(NEXT_ENTRY(QUEUE_PATTERN_TEMPLATE),
2865 NEXT_ENTRY(COMMON_TABLE_ID)),
2866 .args = ARGS(ARGS_ENTRY(struct buffer,
2870 [QUEUE_PATTERN_TEMPLATE] = {
2871 .name = "pattern_template",
2872 .help = "specify pattern template index",
2873 .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
2874 NEXT_ENTRY(COMMON_UNSIGNED)),
2875 .args = ARGS(ARGS_ENTRY(struct buffer,
2876 args.vc.pat_templ_id)),
2879 [QUEUE_ACTIONS_TEMPLATE] = {
2880 .name = "actions_template",
2881 .help = "specify actions template index",
2882 .next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
2883 NEXT_ENTRY(COMMON_UNSIGNED)),
2884 .args = ARGS(ARGS_ENTRY(struct buffer,
2885 args.vc.act_templ_id)),
2888 [QUEUE_CREATE_POSTPONE] = {
2890 .help = "postpone create operation",
2891 .next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
2892 NEXT_ENTRY(COMMON_BOOLEAN)),
2893 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
2896 [QUEUE_DESTROY_POSTPONE] = {
2898 .help = "postpone destroy operation",
2899 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
2900 NEXT_ENTRY(COMMON_BOOLEAN)),
2901 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
2902 .call = parse_qo_destroy,
2904 [QUEUE_DESTROY_ID] = {
2906 .help = "specify rule id to destroy",
2907 .next = NEXT(next_queue_destroy_attr,
2908 NEXT_ENTRY(COMMON_UNSIGNED)),
2909 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
2910 args.destroy.rule)),
2911 .call = parse_qo_destroy,
2913 /* Top-level command. */
2914 [INDIRECT_ACTION] = {
2915 .name = "indirect_action",
2916 .type = "{command} {port_id} [{arg} [...]]",
2917 .help = "manage indirect actions",
2918 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2919 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2922 /* Sub-level commands. */
2923 [INDIRECT_ACTION_CREATE] = {
2925 .help = "create indirect action",
2926 .next = NEXT(next_ia_create_attr),
2929 [INDIRECT_ACTION_UPDATE] = {
2931 .help = "update indirect action",
2932 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2933 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2934 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2937 [INDIRECT_ACTION_DESTROY] = {
2939 .help = "destroy indirect action",
2940 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2941 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2942 .call = parse_ia_destroy,
2944 [INDIRECT_ACTION_QUERY] = {
2946 .help = "query indirect action",
2947 .next = NEXT(NEXT_ENTRY(END),
2948 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2949 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2954 .help = "check whether a flow rule can be created",
2955 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2956 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2961 .help = "create a flow rule",
2962 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2963 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2968 .help = "destroy specific flow rules",
2969 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2970 NEXT_ENTRY(COMMON_PORT_ID)),
2971 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2972 .call = parse_destroy,
2976 .help = "destroy all flow rules",
2977 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2978 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2979 .call = parse_flush,
2983 .help = "dump single/all flow rules to file",
2984 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2985 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2990 .help = "query an existing flow rule",
2991 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
2992 NEXT_ENTRY(COMMON_RULE_ID),
2993 NEXT_ENTRY(COMMON_PORT_ID)),
2994 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
2995 ARGS_ENTRY(struct buffer, args.query.rule),
2996 ARGS_ENTRY(struct buffer, port)),
2997 .call = parse_query,
3001 .help = "list existing flow rules",
3002 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3003 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3008 .help = "list and destroy aged flows",
3009 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3010 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3015 .help = "restrict ingress traffic to the defined flow rules",
3016 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
3017 NEXT_ENTRY(COMMON_PORT_ID)),
3018 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
3019 ARGS_ENTRY(struct buffer, port)),
3020 .call = parse_isolate,
3023 .name = "flex_item",
3024 .help = "flex item API",
3025 .next = NEXT(next_flex_item),
3028 [FLEX_ITEM_INIT] = {
3030 .help = "flex item init",
3031 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3032 ARGS_ENTRY(struct buffer, port)),
3033 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3034 NEXT_ENTRY(COMMON_PORT_ID)),
3037 [FLEX_ITEM_CREATE] = {
3039 .help = "flex item create",
3040 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
3041 ARGS_ENTRY(struct buffer, args.flex.token),
3042 ARGS_ENTRY(struct buffer, port)),
3043 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
3044 NEXT_ENTRY(COMMON_FLEX_TOKEN),
3045 NEXT_ENTRY(COMMON_PORT_ID)),
3048 [FLEX_ITEM_DESTROY] = {
3050 .help = "flex item destroy",
3051 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3052 ARGS_ENTRY(struct buffer, port)),
3053 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3054 NEXT_ENTRY(COMMON_PORT_ID)),
3059 .help = "new tunnel API",
3060 .next = NEXT(NEXT_ENTRY
3061 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
3062 .call = parse_tunnel,
3064 /* Tunnel arguments. */
3067 .help = "create new tunnel object",
3068 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
3069 NEXT_ENTRY(COMMON_PORT_ID)),
3070 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3071 .call = parse_tunnel,
3073 [TUNNEL_CREATE_TYPE] = {
3075 .help = "create new tunnel",
3076 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
3077 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
3078 .call = parse_tunnel,
3080 [TUNNEL_DESTROY] = {
3082 .help = "destroy tunnel",
3083 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
3084 NEXT_ENTRY(COMMON_PORT_ID)),
3085 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3086 .call = parse_tunnel,
3088 [TUNNEL_DESTROY_ID] = {
3090 .help = "tunnel identifier to destroy",
3091 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
3092 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3093 .call = parse_tunnel,
3097 .help = "list existing tunnels",
3098 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3099 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
3100 .call = parse_tunnel,
3102 /* Destroy arguments. */
3105 .help = "specify a rule identifier",
3106 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3107 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
3108 .call = parse_destroy,
3110 /* Dump arguments. */
3114 .next = NEXT(next_dump_attr),
3115 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
3120 .help = "dump one rule",
3121 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3122 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
3123 ARGS_ENTRY(struct buffer, args.dump.rule)),
3126 /* Query arguments. */
3130 .help = "action to query, must be part of the rule",
3131 .call = parse_action,
3132 .comp = comp_action,
3134 /* List arguments. */
3137 .help = "specify a group",
3138 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3139 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
3144 .help = "specify aged flows need be destroyed",
3148 /* Validate/create attributes. */
3151 .help = "specify a group",
3152 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3153 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
3158 .help = "specify a priority level",
3159 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3160 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
3165 .help = "affect rule to ingress",
3166 .next = NEXT(next_vc_attr),
3171 .help = "affect rule to egress",
3172 .next = NEXT(next_vc_attr),
3177 .help = "apply rule directly to endpoints found in pattern",
3178 .next = NEXT(next_vc_attr),
3182 .name = "tunnel_set",
3183 .help = "tunnel steer rule",
3184 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3185 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3188 [VC_TUNNEL_MATCH] = {
3189 .name = "tunnel_match",
3190 .help = "tunnel match rule",
3191 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3192 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3195 /* Validate/create pattern. */
3198 .help = "submit a list of pattern items",
3199 .next = NEXT(next_item),
3204 .help = "match value perfectly (with full bit-mask)",
3205 .call = parse_vc_spec,
3207 [ITEM_PARAM_SPEC] = {
3209 .help = "match value according to configured bit-mask",
3210 .call = parse_vc_spec,
3212 [ITEM_PARAM_LAST] = {
3214 .help = "specify upper bound to establish a range",
3215 .call = parse_vc_spec,
3217 [ITEM_PARAM_MASK] = {
3219 .help = "specify bit-mask with relevant bits set to one",
3220 .call = parse_vc_spec,
3222 [ITEM_PARAM_PREFIX] = {
3224 .help = "generate bit-mask from a prefix length",
3225 .call = parse_vc_spec,
3229 .help = "specify next pattern item",
3230 .next = NEXT(next_item),
3234 .help = "end list of pattern items",
3235 .priv = PRIV_ITEM(END, 0),
3236 .next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3241 .help = "no-op pattern item",
3242 .priv = PRIV_ITEM(VOID, 0),
3243 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3248 .help = "perform actions when pattern does not match",
3249 .priv = PRIV_ITEM(INVERT, 0),
3250 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3255 .help = "match any protocol for the current layer",
3256 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
3257 .next = NEXT(item_any),
3262 .help = "number of layers covered",
3263 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3264 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
3268 .help = "match traffic from/to the physical function",
3269 .priv = PRIV_ITEM(PF, 0),
3270 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3275 .help = "match traffic from/to a virtual function ID",
3276 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
3277 .next = NEXT(item_vf),
3283 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3284 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
3288 .help = "match traffic from/to a specific physical port",
3289 .priv = PRIV_ITEM(PHY_PORT,
3290 sizeof(struct rte_flow_item_phy_port)),
3291 .next = NEXT(item_phy_port),
3294 [ITEM_PHY_PORT_INDEX] = {
3296 .help = "physical port index",
3297 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
3299 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
3303 .help = "match traffic from/to a given DPDK port ID",
3304 .priv = PRIV_ITEM(PORT_ID,
3305 sizeof(struct rte_flow_item_port_id)),
3306 .next = NEXT(item_port_id),
3309 [ITEM_PORT_ID_ID] = {
3311 .help = "DPDK port ID",
3312 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
3314 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
3318 .help = "match traffic against value set in previously matched rule",
3319 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
3320 .next = NEXT(item_mark),
3325 .help = "Integer value to match against",
3326 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
3328 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
3332 .help = "match an arbitrary byte string",
3333 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
3334 .next = NEXT(item_raw),
3337 [ITEM_RAW_RELATIVE] = {
3339 .help = "look for pattern after the previous item",
3340 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3341 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3344 [ITEM_RAW_SEARCH] = {
3346 .help = "search pattern from offset (see also limit)",
3347 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3348 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3351 [ITEM_RAW_OFFSET] = {
3353 .help = "absolute or relative offset for pattern",
3354 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
3355 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
3357 [ITEM_RAW_LIMIT] = {
3359 .help = "search area limit for start of pattern",
3360 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3361 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
3363 [ITEM_RAW_PATTERN] = {
3365 .help = "byte string to look for",
3366 .next = NEXT(item_raw,
3367 NEXT_ENTRY(COMMON_STRING),
3368 NEXT_ENTRY(ITEM_PARAM_IS,
3371 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3372 ARGS_ENTRY(struct rte_flow_item_raw, length),
3373 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3374 ITEM_RAW_PATTERN_SIZE)),
3376 [ITEM_RAW_PATTERN_HEX] = {
3377 .name = "pattern_hex",
3378 .help = "hex string to look for",
3379 .next = NEXT(item_raw,
3380 NEXT_ENTRY(COMMON_HEX),
3381 NEXT_ENTRY(ITEM_PARAM_IS,
3384 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3385 ARGS_ENTRY(struct rte_flow_item_raw, length),
3386 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3387 ITEM_RAW_PATTERN_SIZE)),
3391 .help = "match Ethernet header",
3392 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
3393 .next = NEXT(item_eth),
3398 .help = "destination MAC",
3399 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3400 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
3404 .help = "source MAC",
3405 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3406 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
3410 .help = "EtherType",
3411 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3412 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
3414 [ITEM_ETH_HAS_VLAN] = {
3416 .help = "packet header contains VLAN",
3417 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3418 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
3423 .help = "match 802.1Q/ad VLAN tag",
3424 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
3425 .next = NEXT(item_vlan),
3430 .help = "tag control information",
3431 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3433 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
3437 .help = "priority code point",
3438 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3440 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3445 .help = "drop eligible indicator",
3446 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3448 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3453 .help = "VLAN identifier",
3454 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3456 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
3459 [ITEM_VLAN_INNER_TYPE] = {
3460 .name = "inner_type",
3461 .help = "inner EtherType",
3462 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3464 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
3467 [ITEM_VLAN_HAS_MORE_VLAN] = {
3468 .name = "has_more_vlan",
3469 .help = "packet header contains another VLAN",
3470 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
3472 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
3477 .help = "match IPv4 header",
3478 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
3479 .next = NEXT(item_ipv4),
3482 [ITEM_IPV4_VER_IHL] = {
3483 .name = "version_ihl",
3484 .help = "match header length",
3485 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3487 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
3492 .help = "type of service",
3493 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3495 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3496 hdr.type_of_service)),
3499 .name = "packet_id",
3500 .help = "fragment packet id",
3501 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3503 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3506 [ITEM_IPV4_FRAGMENT_OFFSET] = {
3507 .name = "fragment_offset",
3508 .help = "fragmentation flags and fragment offset",
3509 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3511 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3512 hdr.fragment_offset)),
3516 .help = "time to live",
3517 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3519 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3522 [ITEM_IPV4_PROTO] = {
3524 .help = "next protocol ID",
3525 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
3527 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3528 hdr.next_proto_id)),
3532 .help = "source address",
3533 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3535 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3540 .help = "destination address",
3541 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3543 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3548 .help = "match IPv6 header",
3549 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
3550 .next = NEXT(item_ipv6),
3555 .help = "traffic class",
3556 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3558 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3560 "\x0f\xf0\x00\x00")),
3562 [ITEM_IPV6_FLOW] = {
3564 .help = "flow label",
3565 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3567 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3569 "\x00\x0f\xff\xff")),
3571 [ITEM_IPV6_PROTO] = {
3573 .help = "protocol (next header)",
3574 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3576 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3581 .help = "hop limit",
3582 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3584 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3589 .help = "source address",
3590 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3592 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3597 .help = "destination address",
3598 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3600 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3603 [ITEM_IPV6_HAS_FRAG_EXT] = {
3604 .name = "has_frag_ext",
3605 .help = "fragment packet attribute",
3606 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3608 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
3613 .help = "match ICMP header",
3614 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
3615 .next = NEXT(item_icmp),
3618 [ITEM_ICMP_TYPE] = {
3620 .help = "ICMP packet type",
3621 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3623 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3626 [ITEM_ICMP_CODE] = {
3628 .help = "ICMP packet code",
3629 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3631 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3634 [ITEM_ICMP_IDENT] = {
3636 .help = "ICMP packet identifier",
3637 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3639 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3644 .help = "ICMP packet sequence number",
3645 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3647 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3652 .help = "match UDP header",
3653 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
3654 .next = NEXT(item_udp),
3659 .help = "UDP source port",
3660 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
3662 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3667 .help = "UDP destination port",
3668 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3669 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3674 .help = "match TCP header",
3675 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
3676 .next = NEXT(item_tcp),
3681 .help = "TCP source port",
3682 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3683 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3688 .help = "TCP destination port",
3689 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3690 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3693 [ITEM_TCP_FLAGS] = {
3695 .help = "TCP flags",
3696 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3697 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3702 .help = "match SCTP header",
3703 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
3704 .next = NEXT(item_sctp),
3709 .help = "SCTP source port",
3710 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3712 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3717 .help = "SCTP destination port",
3718 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3720 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3725 .help = "validation tag",
3726 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3728 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3731 [ITEM_SCTP_CKSUM] = {
3734 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3736 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3741 .help = "match VXLAN header",
3742 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
3743 .next = NEXT(item_vxlan),
3746 [ITEM_VXLAN_VNI] = {
3748 .help = "VXLAN identifier",
3749 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3751 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
3753 [ITEM_VXLAN_LAST_RSVD] = {
3754 .name = "last_rsvd",
3755 .help = "VXLAN last reserved bits",
3756 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3758 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
3763 .help = "match E-Tag header",
3764 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
3765 .next = NEXT(item_e_tag),
3768 [ITEM_E_TAG_GRP_ECID_B] = {
3769 .name = "grp_ecid_b",
3770 .help = "GRP and E-CID base",
3771 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3773 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
3779 .help = "match NVGRE header",
3780 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
3781 .next = NEXT(item_nvgre),
3784 [ITEM_NVGRE_TNI] = {
3786 .help = "virtual subnet ID",
3787 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
3789 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
3793 .help = "match MPLS header",
3794 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
3795 .next = NEXT(item_mpls),
3798 [ITEM_MPLS_LABEL] = {
3800 .help = "MPLS label",
3801 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3803 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3809 .help = "MPLS Traffic Class",
3810 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3812 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3818 .help = "MPLS Bottom-of-Stack",
3819 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3821 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3827 .help = "match GRE header",
3828 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
3829 .next = NEXT(item_gre),
3832 [ITEM_GRE_PROTO] = {
3834 .help = "GRE protocol type",
3835 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3837 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3840 [ITEM_GRE_C_RSVD0_VER] = {
3841 .name = "c_rsvd0_ver",
3843 "checksum (1b), undefined (1b), key bit (1b),"
3844 " sequence number (1b), reserved 0 (9b),"
3846 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3848 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3851 [ITEM_GRE_C_BIT] = {
3853 .help = "checksum bit (C)",
3854 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
3856 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3858 "\x80\x00\x00\x00")),
3860 [ITEM_GRE_S_BIT] = {
3862 .help = "sequence number bit (S)",
3863 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3864 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3866 "\x10\x00\x00\x00")),
3868 [ITEM_GRE_K_BIT] = {
3870 .help = "key bit (K)",
3871 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3872 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3874 "\x20\x00\x00\x00")),
3878 .help = "fuzzy pattern match, expect faster than default",
3879 .priv = PRIV_ITEM(FUZZY,
3880 sizeof(struct rte_flow_item_fuzzy)),
3881 .next = NEXT(item_fuzzy),
3884 [ITEM_FUZZY_THRESH] = {
3886 .help = "match accuracy threshold",
3887 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
3889 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
3894 .help = "match GTP header",
3895 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
3896 .next = NEXT(item_gtp),
3899 [ITEM_GTP_FLAGS] = {
3900 .name = "v_pt_rsv_flags",
3901 .help = "GTP flags",
3902 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3903 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3906 [ITEM_GTP_MSG_TYPE] = {
3908 .help = "GTP message type",
3909 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3910 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3914 .help = "tunnel endpoint identifier",
3915 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3916 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3920 .help = "match GTP header",
3921 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3922 .next = NEXT(item_gtp),
3927 .help = "match GTP header",
3928 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3929 .next = NEXT(item_gtp),
3934 .help = "match GENEVE header",
3935 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3936 .next = NEXT(item_geneve),
3939 [ITEM_GENEVE_VNI] = {
3941 .help = "virtual network identifier",
3942 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3944 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3946 [ITEM_GENEVE_PROTO] = {
3948 .help = "GENEVE protocol type",
3949 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3951 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3954 [ITEM_GENEVE_OPTLEN] = {
3956 .help = "GENEVE options length in dwords",
3957 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3959 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3960 ver_opt_len_o_c_rsvd0,
3963 [ITEM_VXLAN_GPE] = {
3964 .name = "vxlan-gpe",
3965 .help = "match VXLAN-GPE header",
3966 .priv = PRIV_ITEM(VXLAN_GPE,
3967 sizeof(struct rte_flow_item_vxlan_gpe)),
3968 .next = NEXT(item_vxlan_gpe),
3971 [ITEM_VXLAN_GPE_VNI] = {
3973 .help = "VXLAN-GPE identifier",
3974 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3976 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
3979 [ITEM_ARP_ETH_IPV4] = {
3980 .name = "arp_eth_ipv4",
3981 .help = "match ARP header for Ethernet/IPv4",
3982 .priv = PRIV_ITEM(ARP_ETH_IPV4,
3983 sizeof(struct rte_flow_item_arp_eth_ipv4)),
3984 .next = NEXT(item_arp_eth_ipv4),
3987 [ITEM_ARP_ETH_IPV4_SHA] = {
3989 .help = "sender hardware address",
3990 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3992 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3995 [ITEM_ARP_ETH_IPV4_SPA] = {
3997 .help = "sender IPv4 address",
3998 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4000 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4003 [ITEM_ARP_ETH_IPV4_THA] = {
4005 .help = "target hardware address",
4006 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4008 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4011 [ITEM_ARP_ETH_IPV4_TPA] = {
4013 .help = "target IPv4 address",
4014 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4016 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4021 .help = "match presence of any IPv6 extension header",
4022 .priv = PRIV_ITEM(IPV6_EXT,
4023 sizeof(struct rte_flow_item_ipv6_ext)),
4024 .next = NEXT(item_ipv6_ext),
4027 [ITEM_IPV6_EXT_NEXT_HDR] = {
4029 .help = "next header",
4030 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4032 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
4035 [ITEM_IPV6_FRAG_EXT] = {
4036 .name = "ipv6_frag_ext",
4037 .help = "match presence of IPv6 fragment extension header",
4038 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
4039 sizeof(struct rte_flow_item_ipv6_frag_ext)),
4040 .next = NEXT(item_ipv6_frag_ext),
4043 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
4045 .help = "next header",
4046 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4048 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
4051 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
4052 .name = "frag_data",
4053 .help = "fragment flags and offset",
4054 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4056 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4059 [ITEM_IPV6_FRAG_EXT_ID] = {
4060 .name = "packet_id",
4061 .help = "fragment packet id",
4062 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4064 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4069 .help = "match any ICMPv6 header",
4070 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
4071 .next = NEXT(item_icmp6),
4074 [ITEM_ICMP6_TYPE] = {
4076 .help = "ICMPv6 type",
4077 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4079 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4082 [ITEM_ICMP6_CODE] = {
4084 .help = "ICMPv6 code",
4085 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4087 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4090 [ITEM_ICMP6_ND_NS] = {
4091 .name = "icmp6_nd_ns",
4092 .help = "match ICMPv6 neighbor discovery solicitation",
4093 .priv = PRIV_ITEM(ICMP6_ND_NS,
4094 sizeof(struct rte_flow_item_icmp6_nd_ns)),
4095 .next = NEXT(item_icmp6_nd_ns),
4098 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
4099 .name = "target_addr",
4100 .help = "target address",
4101 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
4103 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
4106 [ITEM_ICMP6_ND_NA] = {
4107 .name = "icmp6_nd_na",
4108 .help = "match ICMPv6 neighbor discovery advertisement",
4109 .priv = PRIV_ITEM(ICMP6_ND_NA,
4110 sizeof(struct rte_flow_item_icmp6_nd_na)),
4111 .next = NEXT(item_icmp6_nd_na),
4114 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
4115 .name = "target_addr",
4116 .help = "target address",
4117 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
4119 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
4122 [ITEM_ICMP6_ND_OPT] = {
4123 .name = "icmp6_nd_opt",
4124 .help = "match presence of any ICMPv6 neighbor discovery"
4126 .priv = PRIV_ITEM(ICMP6_ND_OPT,
4127 sizeof(struct rte_flow_item_icmp6_nd_opt)),
4128 .next = NEXT(item_icmp6_nd_opt),
4131 [ITEM_ICMP6_ND_OPT_TYPE] = {
4133 .help = "ND option type",
4134 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4136 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
4139 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
4140 .name = "icmp6_nd_opt_sla_eth",
4141 .help = "match ICMPv6 neighbor discovery source Ethernet"
4142 " link-layer address option",
4144 (ICMP6_ND_OPT_SLA_ETH,
4145 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
4146 .next = NEXT(item_icmp6_nd_opt_sla_eth),
4149 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
4151 .help = "source Ethernet LLA",
4152 .next = NEXT(item_icmp6_nd_opt_sla_eth,
4153 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4154 .args = ARGS(ARGS_ENTRY_HTON
4155 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
4157 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
4158 .name = "icmp6_nd_opt_tla_eth",
4159 .help = "match ICMPv6 neighbor discovery target Ethernet"
4160 " link-layer address option",
4162 (ICMP6_ND_OPT_TLA_ETH,
4163 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
4164 .next = NEXT(item_icmp6_nd_opt_tla_eth),
4167 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
4169 .help = "target Ethernet LLA",
4170 .next = NEXT(item_icmp6_nd_opt_tla_eth,
4171 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4172 .args = ARGS(ARGS_ENTRY_HTON
4173 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
4177 .help = "match metadata header",
4178 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
4179 .next = NEXT(item_meta),
4182 [ITEM_META_DATA] = {
4184 .help = "metadata value",
4185 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
4187 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
4188 data, "\xff\xff\xff\xff")),
4192 .help = "match GRE key",
4193 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
4194 .next = NEXT(item_gre_key),
4197 [ITEM_GRE_KEY_VALUE] = {
4199 .help = "key value",
4200 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
4202 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4204 [ITEM_GRE_OPTION] = {
4205 .name = "gre_option",
4206 .help = "match GRE optional fields",
4207 .priv = PRIV_ITEM(GRE_OPTION,
4208 sizeof(struct rte_flow_item_gre_opt)),
4209 .next = NEXT(item_gre_option),
4212 [ITEM_GRE_OPTION_CHECKSUM] = {
4214 .help = "match GRE checksum",
4215 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4217 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4218 checksum_rsvd.checksum)),
4220 [ITEM_GRE_OPTION_KEY] = {
4222 .help = "match GRE key",
4223 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4225 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4228 [ITEM_GRE_OPTION_SEQUENCE] = {
4230 .help = "match GRE sequence",
4231 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4233 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4234 sequence.sequence)),
4238 .help = "match GTP extension header with type 0x85",
4239 .priv = PRIV_ITEM(GTP_PSC,
4240 sizeof(struct rte_flow_item_gtp_psc)),
4241 .next = NEXT(item_gtp_psc),
4244 [ITEM_GTP_PSC_QFI] = {
4246 .help = "QoS flow identifier",
4247 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4249 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4252 [ITEM_GTP_PSC_PDU_T] = {
4255 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4257 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4262 .help = "match PPPoE session header",
4263 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
4264 .next = NEXT(item_pppoes),
4269 .help = "match PPPoE discovery header",
4270 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
4271 .next = NEXT(item_pppoed),
4274 [ITEM_PPPOE_SEID] = {
4276 .help = "session identifier",
4277 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
4279 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
4282 [ITEM_PPPOE_PROTO_ID] = {
4283 .name = "pppoe_proto_id",
4284 .help = "match PPPoE session protocol identifier",
4285 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
4286 sizeof(struct rte_flow_item_pppoe_proto_id)),
4287 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
4289 .args = ARGS(ARGS_ENTRY_HTON
4290 (struct rte_flow_item_pppoe_proto_id, proto_id)),
4295 .help = "matches higig2 header",
4296 .priv = PRIV_ITEM(HIGIG2,
4297 sizeof(struct rte_flow_item_higig2_hdr)),
4298 .next = NEXT(item_higig2),
4301 [ITEM_HIGIG2_CLASSIFICATION] = {
4302 .name = "classification",
4303 .help = "matches classification of higig2 header",
4304 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4306 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4307 hdr.ppt1.classification)),
4309 [ITEM_HIGIG2_VID] = {
4311 .help = "matches vid of higig2 header",
4312 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4314 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4319 .help = "match tag value",
4320 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
4321 .next = NEXT(item_tag),
4326 .help = "tag value to match",
4327 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4328 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
4330 [ITEM_TAG_INDEX] = {
4332 .help = "index of tag array to match",
4333 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4334 NEXT_ENTRY(ITEM_PARAM_IS)),
4335 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
4337 [ITEM_L2TPV3OIP] = {
4338 .name = "l2tpv3oip",
4339 .help = "match L2TPv3 over IP header",
4340 .priv = PRIV_ITEM(L2TPV3OIP,
4341 sizeof(struct rte_flow_item_l2tpv3oip)),
4342 .next = NEXT(item_l2tpv3oip),
4345 [ITEM_L2TPV3OIP_SESSION_ID] = {
4346 .name = "session_id",
4347 .help = "session identifier",
4348 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
4350 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
4355 .help = "match ESP header",
4356 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
4357 .next = NEXT(item_esp),
4362 .help = "security policy index",
4363 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4364 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
4369 .help = "match AH header",
4370 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
4371 .next = NEXT(item_ah),
4376 .help = "security parameters index",
4377 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4378 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
4382 .help = "match pfcp header",
4383 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
4384 .next = NEXT(item_pfcp),
4387 [ITEM_PFCP_S_FIELD] = {
4390 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
4392 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
4395 [ITEM_PFCP_SEID] = {
4397 .help = "session endpoint identifier",
4398 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
4400 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
4404 .help = "match eCPRI header",
4405 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
4406 .next = NEXT(item_ecpri),
4409 [ITEM_ECPRI_COMMON] = {
4411 .help = "eCPRI common header",
4412 .next = NEXT(item_ecpri_common),
4414 [ITEM_ECPRI_COMMON_TYPE] = {
4416 .help = "type of common header",
4417 .next = NEXT(item_ecpri_common_type),
4418 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
4420 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
4422 .help = "Type #0: IQ Data",
4423 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
4425 .call = parse_vc_item_ecpri_type,
4427 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
4429 .help = "Physical Channel ID",
4430 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
4431 ITEM_ECPRI_COMMON, ITEM_NEXT),
4432 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4433 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4436 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
4438 .help = "Type #2: Real-Time Control Data",
4439 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
4441 .call = parse_vc_item_ecpri_type,
4443 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
4445 .help = "Real-Time Control Data ID",
4446 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
4447 ITEM_ECPRI_COMMON, ITEM_NEXT),
4448 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4449 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4452 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
4453 .name = "delay_measure",
4454 .help = "Type #5: One-Way Delay Measurement",
4455 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
4457 .call = parse_vc_item_ecpri_type,
4459 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
4461 .help = "Measurement ID",
4462 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
4463 ITEM_ECPRI_COMMON, ITEM_NEXT),
4464 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4465 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
4468 [ITEM_GENEVE_OPT] = {
4469 .name = "geneve-opt",
4470 .help = "GENEVE header option",
4471 .priv = PRIV_ITEM(GENEVE_OPT,
4472 sizeof(struct rte_flow_item_geneve_opt) +
4473 ITEM_GENEVE_OPT_DATA_SIZE),
4474 .next = NEXT(item_geneve_opt),
4477 [ITEM_GENEVE_OPT_CLASS] = {
4479 .help = "GENEVE option class",
4480 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4482 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
4485 [ITEM_GENEVE_OPT_TYPE] = {
4487 .help = "GENEVE option type",
4488 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4490 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
4493 [ITEM_GENEVE_OPT_LENGTH] = {
4495 .help = "GENEVE option data length (in 32b words)",
4496 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4498 .args = ARGS(ARGS_ENTRY_BOUNDED(
4499 struct rte_flow_item_geneve_opt, option_len,
4502 [ITEM_GENEVE_OPT_DATA] = {
4504 .help = "GENEVE option data pattern",
4505 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
4507 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
4508 ARGS_ENTRY_ARB(0, 0),
4510 (sizeof(struct rte_flow_item_geneve_opt),
4511 ITEM_GENEVE_OPT_DATA_SIZE)),
4513 [ITEM_INTEGRITY] = {
4514 .name = "integrity",
4515 .help = "match packet integrity",
4516 .priv = PRIV_ITEM(INTEGRITY,
4517 sizeof(struct rte_flow_item_integrity)),
4518 .next = NEXT(item_integrity),
4521 [ITEM_INTEGRITY_LEVEL] = {
4523 .help = "integrity level",
4524 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
4526 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
4528 [ITEM_INTEGRITY_VALUE] = {
4530 .help = "integrity value",
4531 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
4533 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
4535 [ITEM_CONNTRACK] = {
4536 .name = "conntrack",
4537 .help = "conntrack state",
4538 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
4540 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
4542 [ITEM_PORT_REPRESENTOR] = {
4543 .name = "port_representor",
4544 .help = "match traffic entering the embedded switch from the given ethdev",
4545 .priv = PRIV_ITEM(PORT_REPRESENTOR,
4546 sizeof(struct rte_flow_item_ethdev)),
4547 .next = NEXT(item_port_representor),
4550 [ITEM_PORT_REPRESENTOR_PORT_ID] = {
4552 .help = "ethdev port ID",
4553 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
4555 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4557 [ITEM_REPRESENTED_PORT] = {
4558 .name = "represented_port",
4559 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
4560 .priv = PRIV_ITEM(REPRESENTED_PORT,
4561 sizeof(struct rte_flow_item_ethdev)),
4562 .next = NEXT(item_represented_port),
4565 [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
4566 .name = "ethdev_port_id",
4567 .help = "ethdev port ID",
4568 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
4570 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4574 .help = "match flex header",
4575 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
4576 .next = NEXT(item_flex),
4579 [ITEM_FLEX_ITEM_HANDLE] = {
4581 .help = "flex item handle",
4582 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4583 NEXT_ENTRY(ITEM_PARAM_IS)),
4584 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
4586 [ITEM_FLEX_PATTERN_HANDLE] = {
4588 .help = "flex pattern handle",
4589 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4590 NEXT_ENTRY(ITEM_PARAM_IS)),
4591 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
4595 .help = "match L2TPv2 header",
4596 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
4597 .next = NEXT(item_l2tpv2),
4600 [ITEM_L2TPV2_TYPE] = {
4602 .help = "type of l2tpv2",
4603 .next = NEXT(item_l2tpv2_type),
4604 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
4606 [ITEM_L2TPV2_TYPE_DATA] = {
4608 .help = "Type #7: data message without any options",
4609 .next = NEXT(item_l2tpv2_type_data),
4610 .call = parse_vc_item_l2tpv2_type,
4612 [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
4613 .name = "tunnel_id",
4614 .help = "tunnel identifier",
4615 .next = NEXT(item_l2tpv2_type_data,
4616 NEXT_ENTRY(COMMON_UNSIGNED),
4618 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4619 hdr.type7.tunnel_id)),
4621 [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
4622 .name = "session_id",
4623 .help = "session identifier",
4624 .next = NEXT(item_l2tpv2_type_data,
4625 NEXT_ENTRY(COMMON_UNSIGNED),
4627 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4628 hdr.type7.session_id)),
4630 [ITEM_L2TPV2_TYPE_DATA_L] = {
4632 .help = "Type #6: data message with length option",
4633 .next = NEXT(item_l2tpv2_type_data_l),
4634 .call = parse_vc_item_l2tpv2_type,
4636 [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
4638 .help = "message length",
4639 .next = NEXT(item_l2tpv2_type_data_l,
4640 NEXT_ENTRY(COMMON_UNSIGNED),
4642 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4645 [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
4646 .name = "tunnel_id",
4647 .help = "tunnel identifier",
4648 .next = NEXT(item_l2tpv2_type_data_l,
4649 NEXT_ENTRY(COMMON_UNSIGNED),
4651 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4652 hdr.type6.tunnel_id)),
4654 [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
4655 .name = "session_id",
4656 .help = "session identifier",
4657 .next = NEXT(item_l2tpv2_type_data_l,
4658 NEXT_ENTRY(COMMON_UNSIGNED),
4660 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4661 hdr.type6.session_id)),
4663 [ITEM_L2TPV2_TYPE_DATA_S] = {
4665 .help = "Type #5: data message with ns, nr option",
4666 .next = NEXT(item_l2tpv2_type_data_s),
4667 .call = parse_vc_item_l2tpv2_type,
4669 [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
4670 .name = "tunnel_id",
4671 .help = "tunnel identifier",
4672 .next = NEXT(item_l2tpv2_type_data_s,
4673 NEXT_ENTRY(COMMON_UNSIGNED),
4675 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4676 hdr.type5.tunnel_id)),
4678 [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
4679 .name = "session_id",
4680 .help = "session identifier",
4681 .next = NEXT(item_l2tpv2_type_data_s,
4682 NEXT_ENTRY(COMMON_UNSIGNED),
4684 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4685 hdr.type5.session_id)),
4687 [ITEM_L2TPV2_MSG_DATA_S_NS] = {
4689 .help = "sequence number for message",
4690 .next = NEXT(item_l2tpv2_type_data_s,
4691 NEXT_ENTRY(COMMON_UNSIGNED),
4693 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4696 [ITEM_L2TPV2_MSG_DATA_S_NR] = {
4698 .help = "sequence number for next receive message",
4699 .next = NEXT(item_l2tpv2_type_data_s,
4700 NEXT_ENTRY(COMMON_UNSIGNED),
4702 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4705 [ITEM_L2TPV2_TYPE_DATA_O] = {
4707 .help = "Type #4: data message with offset option",
4708 .next = NEXT(item_l2tpv2_type_data_o),
4709 .call = parse_vc_item_l2tpv2_type,
4711 [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
4712 .name = "tunnel_id",
4713 .help = "tunnel identifier",
4714 .next = NEXT(item_l2tpv2_type_data_o,
4715 NEXT_ENTRY(COMMON_UNSIGNED),
4717 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4718 hdr.type4.tunnel_id)),
4720 [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
4721 .name = "session_id",
4722 .help = "session identifier",
4723 .next = NEXT(item_l2tpv2_type_data_o,
4724 NEXT_ENTRY(COMMON_UNSIGNED),
4726 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4727 hdr.type5.session_id)),
4729 [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
4730 .name = "offset_size",
4731 .help = "the size of offset padding",
4732 .next = NEXT(item_l2tpv2_type_data_o,
4733 NEXT_ENTRY(COMMON_UNSIGNED),
4735 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4736 hdr.type4.offset_size)),
4738 [ITEM_L2TPV2_TYPE_DATA_L_S] = {
4740 .help = "Type #3: data message contains length, ns, nr "
4742 .next = NEXT(item_l2tpv2_type_data_l_s),
4743 .call = parse_vc_item_l2tpv2_type,
4745 [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
4747 .help = "message length",
4748 .next = NEXT(item_l2tpv2_type_data_l_s,
4749 NEXT_ENTRY(COMMON_UNSIGNED),
4751 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4754 [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
4755 .name = "tunnel_id",
4756 .help = "tunnel identifier",
4757 .next = NEXT(item_l2tpv2_type_data_l_s,
4758 NEXT_ENTRY(COMMON_UNSIGNED),
4760 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4761 hdr.type3.tunnel_id)),
4763 [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
4764 .name = "session_id",
4765 .help = "session identifier",
4766 .next = NEXT(item_l2tpv2_type_data_l_s,
4767 NEXT_ENTRY(COMMON_UNSIGNED),
4769 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4770 hdr.type3.session_id)),
4772 [ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
4774 .help = "sequence number for message",
4775 .next = NEXT(item_l2tpv2_type_data_l_s,
4776 NEXT_ENTRY(COMMON_UNSIGNED),
4778 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4781 [ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
4783 .help = "sequence number for next receive message",
4784 .next = NEXT(item_l2tpv2_type_data_l_s,
4785 NEXT_ENTRY(COMMON_UNSIGNED),
4787 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4790 [ITEM_L2TPV2_TYPE_CTRL] = {
4792 .help = "Type #3: conrtol message contains length, ns, nr "
4794 .next = NEXT(item_l2tpv2_type_ctrl),
4795 .call = parse_vc_item_l2tpv2_type,
4797 [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
4799 .help = "message length",
4800 .next = NEXT(item_l2tpv2_type_ctrl,
4801 NEXT_ENTRY(COMMON_UNSIGNED),
4803 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4806 [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
4807 .name = "tunnel_id",
4808 .help = "tunnel identifier",
4809 .next = NEXT(item_l2tpv2_type_ctrl,
4810 NEXT_ENTRY(COMMON_UNSIGNED),
4812 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4813 hdr.type3.tunnel_id)),
4815 [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
4816 .name = "session_id",
4817 .help = "session identifier",
4818 .next = NEXT(item_l2tpv2_type_ctrl,
4819 NEXT_ENTRY(COMMON_UNSIGNED),
4821 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4822 hdr.type3.session_id)),
4824 [ITEM_L2TPV2_MSG_CTRL_NS] = {
4826 .help = "sequence number for message",
4827 .next = NEXT(item_l2tpv2_type_ctrl,
4828 NEXT_ENTRY(COMMON_UNSIGNED),
4830 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4833 [ITEM_L2TPV2_MSG_CTRL_NR] = {
4835 .help = "sequence number for next receive message",
4836 .next = NEXT(item_l2tpv2_type_ctrl,
4837 NEXT_ENTRY(COMMON_UNSIGNED),
4839 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4844 .help = "match PPP header",
4845 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
4846 .next = NEXT(item_ppp),
4851 .help = "PPP address",
4852 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4854 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
4858 .help = "PPP control",
4859 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4861 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
4863 [ITEM_PPP_PROTO_ID] = {
4865 .help = "PPP protocol identifier",
4866 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4868 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
4871 /* Validate/create actions. */
4874 .help = "submit a list of associated actions",
4875 .next = NEXT(next_action),
4880 .help = "specify next action",
4881 .next = NEXT(next_action),
4885 .help = "end list of actions",
4886 .priv = PRIV_ACTION(END, 0),
4891 .help = "no-op action",
4892 .priv = PRIV_ACTION(VOID, 0),
4893 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4896 [ACTION_PASSTHRU] = {
4898 .help = "let subsequent rule process matched packets",
4899 .priv = PRIV_ACTION(PASSTHRU, 0),
4900 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4905 .help = "redirect traffic to a given group",
4906 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
4907 .next = NEXT(action_jump),
4910 [ACTION_JUMP_GROUP] = {
4912 .help = "group to redirect traffic to",
4913 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
4914 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
4915 .call = parse_vc_conf,
4919 .help = "attach 32 bit value to packets",
4920 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
4921 .next = NEXT(action_mark),
4924 [ACTION_MARK_ID] = {
4926 .help = "32 bit value to return with packets",
4927 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
4928 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
4929 .call = parse_vc_conf,
4933 .help = "flag packets",
4934 .priv = PRIV_ACTION(FLAG, 0),
4935 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4940 .help = "assign packets to a given queue index",
4941 .priv = PRIV_ACTION(QUEUE,
4942 sizeof(struct rte_flow_action_queue)),
4943 .next = NEXT(action_queue),
4946 [ACTION_QUEUE_INDEX] = {
4948 .help = "queue index to use",
4949 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
4950 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
4951 .call = parse_vc_conf,
4955 .help = "drop packets (note: passthru has priority)",
4956 .priv = PRIV_ACTION(DROP, 0),
4957 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4962 .help = "enable counters for this rule",
4963 .priv = PRIV_ACTION(COUNT,
4964 sizeof(struct rte_flow_action_count)),
4965 .next = NEXT(action_count),
4968 [ACTION_COUNT_ID] = {
4969 .name = "identifier",
4970 .help = "counter identifier to use",
4971 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
4972 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
4973 .call = parse_vc_conf,
4977 .help = "spread packets among several queues",
4978 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
4979 .next = NEXT(action_rss),
4980 .call = parse_vc_action_rss,
4982 [ACTION_RSS_FUNC] = {
4984 .help = "RSS hash function to apply",
4985 .next = NEXT(action_rss,
4986 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
4987 ACTION_RSS_FUNC_TOEPLITZ,
4988 ACTION_RSS_FUNC_SIMPLE_XOR,
4989 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
4991 [ACTION_RSS_FUNC_DEFAULT] = {
4993 .help = "default hash function",
4994 .call = parse_vc_action_rss_func,
4996 [ACTION_RSS_FUNC_TOEPLITZ] = {
4998 .help = "Toeplitz hash function",
4999 .call = parse_vc_action_rss_func,
5001 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
5002 .name = "simple_xor",
5003 .help = "simple XOR hash function",
5004 .call = parse_vc_action_rss_func,
5006 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
5007 .name = "symmetric_toeplitz",
5008 .help = "Symmetric Toeplitz hash function",
5009 .call = parse_vc_action_rss_func,
5011 [ACTION_RSS_LEVEL] = {
5013 .help = "encapsulation level for \"types\"",
5014 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5015 .args = ARGS(ARGS_ENTRY_ARB
5016 (offsetof(struct action_rss_data, conf) +
5017 offsetof(struct rte_flow_action_rss, level),
5018 sizeof(((struct rte_flow_action_rss *)0)->
5021 [ACTION_RSS_TYPES] = {
5023 .help = "specific RSS hash types",
5024 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
5026 [ACTION_RSS_TYPE] = {
5028 .help = "RSS hash type",
5029 .call = parse_vc_action_rss_type,
5030 .comp = comp_vc_action_rss_type,
5032 [ACTION_RSS_KEY] = {
5034 .help = "RSS hash key",
5035 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
5036 .args = ARGS(ARGS_ENTRY_ARB
5037 (offsetof(struct action_rss_data, conf) +
5038 offsetof(struct rte_flow_action_rss, key),
5039 sizeof(((struct rte_flow_action_rss *)0)->key)),
5041 (offsetof(struct action_rss_data, conf) +
5042 offsetof(struct rte_flow_action_rss, key_len),
5043 sizeof(((struct rte_flow_action_rss *)0)->
5045 ARGS_ENTRY(struct action_rss_data, key)),
5047 [ACTION_RSS_KEY_LEN] = {
5049 .help = "RSS hash key length in bytes",
5050 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5051 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5052 (offsetof(struct action_rss_data, conf) +
5053 offsetof(struct rte_flow_action_rss, key_len),
5054 sizeof(((struct rte_flow_action_rss *)0)->
5057 RSS_HASH_KEY_LENGTH)),
5059 [ACTION_RSS_QUEUES] = {
5061 .help = "queue indices to use",
5062 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
5063 .call = parse_vc_conf,
5065 [ACTION_RSS_QUEUE] = {
5067 .help = "queue index",
5068 .call = parse_vc_action_rss_queue,
5069 .comp = comp_vc_action_rss_queue,
5073 .help = "direct traffic to physical function",
5074 .priv = PRIV_ACTION(PF, 0),
5075 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5080 .help = "direct traffic to a virtual function ID",
5081 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
5082 .next = NEXT(action_vf),
5085 [ACTION_VF_ORIGINAL] = {
5087 .help = "use original VF ID if possible",
5088 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
5089 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
5091 .call = parse_vc_conf,
5096 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
5097 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
5098 .call = parse_vc_conf,
5100 [ACTION_PHY_PORT] = {
5102 .help = "direct packets to physical port index",
5103 .priv = PRIV_ACTION(PHY_PORT,
5104 sizeof(struct rte_flow_action_phy_port)),
5105 .next = NEXT(action_phy_port),
5108 [ACTION_PHY_PORT_ORIGINAL] = {
5110 .help = "use original port index if possible",
5111 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
5112 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
5114 .call = parse_vc_conf,
5116 [ACTION_PHY_PORT_INDEX] = {
5118 .help = "physical port index",
5119 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
5120 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
5122 .call = parse_vc_conf,
5124 [ACTION_PORT_ID] = {
5126 .help = "direct matching traffic to a given DPDK port ID",
5127 .priv = PRIV_ACTION(PORT_ID,
5128 sizeof(struct rte_flow_action_port_id)),
5129 .next = NEXT(action_port_id),
5132 [ACTION_PORT_ID_ORIGINAL] = {
5134 .help = "use original DPDK port ID if possible",
5135 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
5136 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
5138 .call = parse_vc_conf,
5140 [ACTION_PORT_ID_ID] = {
5142 .help = "DPDK port ID",
5143 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
5144 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
5145 .call = parse_vc_conf,
5149 .help = "meter the directed packets at given id",
5150 .priv = PRIV_ACTION(METER,
5151 sizeof(struct rte_flow_action_meter)),
5152 .next = NEXT(action_meter),
5155 [ACTION_METER_COLOR] = {
5157 .help = "meter color for the packets",
5158 .priv = PRIV_ACTION(METER_COLOR,
5159 sizeof(struct rte_flow_action_meter_color)),
5160 .next = NEXT(action_meter_color),
5163 [ACTION_METER_COLOR_TYPE] = {
5165 .help = "specific meter color",
5166 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5167 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
5168 ACTION_METER_COLOR_YELLOW,
5169 ACTION_METER_COLOR_RED)),
5171 [ACTION_METER_COLOR_GREEN] = {
5173 .help = "meter color green",
5174 .call = parse_vc_action_meter_color_type,
5176 [ACTION_METER_COLOR_YELLOW] = {
5178 .help = "meter color yellow",
5179 .call = parse_vc_action_meter_color_type,
5181 [ACTION_METER_COLOR_RED] = {
5183 .help = "meter color red",
5184 .call = parse_vc_action_meter_color_type,
5186 [ACTION_METER_ID] = {
5188 .help = "meter id to use",
5189 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
5190 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
5191 .call = parse_vc_conf,
5193 [ACTION_OF_SET_MPLS_TTL] = {
5194 .name = "of_set_mpls_ttl",
5195 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
5198 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
5199 .next = NEXT(action_of_set_mpls_ttl),
5202 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
5205 .next = NEXT(action_of_set_mpls_ttl,
5206 NEXT_ENTRY(COMMON_UNSIGNED)),
5207 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
5209 .call = parse_vc_conf,
5211 [ACTION_OF_DEC_MPLS_TTL] = {
5212 .name = "of_dec_mpls_ttl",
5213 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
5214 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
5215 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5218 [ACTION_OF_SET_NW_TTL] = {
5219 .name = "of_set_nw_ttl",
5220 .help = "OpenFlow's OFPAT_SET_NW_TTL",
5223 sizeof(struct rte_flow_action_of_set_nw_ttl)),
5224 .next = NEXT(action_of_set_nw_ttl),
5227 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
5230 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5231 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
5233 .call = parse_vc_conf,
5235 [ACTION_OF_DEC_NW_TTL] = {
5236 .name = "of_dec_nw_ttl",
5237 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
5238 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
5239 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5242 [ACTION_OF_COPY_TTL_OUT] = {
5243 .name = "of_copy_ttl_out",
5244 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
5245 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
5246 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5249 [ACTION_OF_COPY_TTL_IN] = {
5250 .name = "of_copy_ttl_in",
5251 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
5252 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
5253 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5256 [ACTION_OF_POP_VLAN] = {
5257 .name = "of_pop_vlan",
5258 .help = "OpenFlow's OFPAT_POP_VLAN",
5259 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
5260 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5263 [ACTION_OF_PUSH_VLAN] = {
5264 .name = "of_push_vlan",
5265 .help = "OpenFlow's OFPAT_PUSH_VLAN",
5268 sizeof(struct rte_flow_action_of_push_vlan)),
5269 .next = NEXT(action_of_push_vlan),
5272 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
5273 .name = "ethertype",
5274 .help = "EtherType",
5275 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
5276 .args = ARGS(ARGS_ENTRY_HTON
5277 (struct rte_flow_action_of_push_vlan,
5279 .call = parse_vc_conf,
5281 [ACTION_OF_SET_VLAN_VID] = {
5282 .name = "of_set_vlan_vid",
5283 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
5286 sizeof(struct rte_flow_action_of_set_vlan_vid)),
5287 .next = NEXT(action_of_set_vlan_vid),
5290 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
5293 .next = NEXT(action_of_set_vlan_vid,
5294 NEXT_ENTRY(COMMON_UNSIGNED)),
5295 .args = ARGS(ARGS_ENTRY_HTON
5296 (struct rte_flow_action_of_set_vlan_vid,
5298 .call = parse_vc_conf,
5300 [ACTION_OF_SET_VLAN_PCP] = {
5301 .name = "of_set_vlan_pcp",
5302 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
5305 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
5306 .next = NEXT(action_of_set_vlan_pcp),
5309 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
5311 .help = "VLAN priority",
5312 .next = NEXT(action_of_set_vlan_pcp,
5313 NEXT_ENTRY(COMMON_UNSIGNED)),
5314 .args = ARGS(ARGS_ENTRY_HTON
5315 (struct rte_flow_action_of_set_vlan_pcp,
5317 .call = parse_vc_conf,
5319 [ACTION_OF_POP_MPLS] = {
5320 .name = "of_pop_mpls",
5321 .help = "OpenFlow's OFPAT_POP_MPLS",
5322 .priv = PRIV_ACTION(OF_POP_MPLS,
5323 sizeof(struct rte_flow_action_of_pop_mpls)),
5324 .next = NEXT(action_of_pop_mpls),
5327 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
5328 .name = "ethertype",
5329 .help = "EtherType",
5330 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5331 .args = ARGS(ARGS_ENTRY_HTON
5332 (struct rte_flow_action_of_pop_mpls,
5334 .call = parse_vc_conf,
5336 [ACTION_OF_PUSH_MPLS] = {
5337 .name = "of_push_mpls",
5338 .help = "OpenFlow's OFPAT_PUSH_MPLS",
5341 sizeof(struct rte_flow_action_of_push_mpls)),
5342 .next = NEXT(action_of_push_mpls),
5345 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
5346 .name = "ethertype",
5347 .help = "EtherType",
5348 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
5349 .args = ARGS(ARGS_ENTRY_HTON
5350 (struct rte_flow_action_of_push_mpls,
5352 .call = parse_vc_conf,
5354 [ACTION_VXLAN_ENCAP] = {
5355 .name = "vxlan_encap",
5356 .help = "VXLAN encapsulation, uses configuration set by \"set"
5358 .priv = PRIV_ACTION(VXLAN_ENCAP,
5359 sizeof(struct action_vxlan_encap_data)),
5360 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5361 .call = parse_vc_action_vxlan_encap,
5363 [ACTION_VXLAN_DECAP] = {
5364 .name = "vxlan_decap",
5365 .help = "Performs a decapsulation action by stripping all"
5366 " headers of the VXLAN tunnel network overlay from the"
5368 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
5369 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5372 [ACTION_NVGRE_ENCAP] = {
5373 .name = "nvgre_encap",
5374 .help = "NVGRE encapsulation, uses configuration set by \"set"
5376 .priv = PRIV_ACTION(NVGRE_ENCAP,
5377 sizeof(struct action_nvgre_encap_data)),
5378 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5379 .call = parse_vc_action_nvgre_encap,
5381 [ACTION_NVGRE_DECAP] = {
5382 .name = "nvgre_decap",
5383 .help = "Performs a decapsulation action by stripping all"
5384 " headers of the NVGRE tunnel network overlay from the"
5386 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
5387 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5390 [ACTION_L2_ENCAP] = {
5392 .help = "l2 encap, uses configuration set by"
5393 " \"set l2_encap\"",
5394 .priv = PRIV_ACTION(RAW_ENCAP,
5395 sizeof(struct action_raw_encap_data)),
5396 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5397 .call = parse_vc_action_l2_encap,
5399 [ACTION_L2_DECAP] = {
5401 .help = "l2 decap, uses configuration set by"
5402 " \"set l2_decap\"",
5403 .priv = PRIV_ACTION(RAW_DECAP,
5404 sizeof(struct action_raw_decap_data)),
5405 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5406 .call = parse_vc_action_l2_decap,
5408 [ACTION_MPLSOGRE_ENCAP] = {
5409 .name = "mplsogre_encap",
5410 .help = "mplsogre encapsulation, uses configuration set by"
5411 " \"set mplsogre_encap\"",
5412 .priv = PRIV_ACTION(RAW_ENCAP,
5413 sizeof(struct action_raw_encap_data)),
5414 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5415 .call = parse_vc_action_mplsogre_encap,
5417 [ACTION_MPLSOGRE_DECAP] = {
5418 .name = "mplsogre_decap",
5419 .help = "mplsogre decapsulation, uses configuration set by"
5420 " \"set mplsogre_decap\"",
5421 .priv = PRIV_ACTION(RAW_DECAP,
5422 sizeof(struct action_raw_decap_data)),
5423 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5424 .call = parse_vc_action_mplsogre_decap,
5426 [ACTION_MPLSOUDP_ENCAP] = {
5427 .name = "mplsoudp_encap",
5428 .help = "mplsoudp encapsulation, uses configuration set by"
5429 " \"set mplsoudp_encap\"",
5430 .priv = PRIV_ACTION(RAW_ENCAP,
5431 sizeof(struct action_raw_encap_data)),
5432 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5433 .call = parse_vc_action_mplsoudp_encap,
5435 [ACTION_MPLSOUDP_DECAP] = {
5436 .name = "mplsoudp_decap",
5437 .help = "mplsoudp decapsulation, uses configuration set by"
5438 " \"set mplsoudp_decap\"",
5439 .priv = PRIV_ACTION(RAW_DECAP,
5440 sizeof(struct action_raw_decap_data)),
5441 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5442 .call = parse_vc_action_mplsoudp_decap,
5444 [ACTION_SET_IPV4_SRC] = {
5445 .name = "set_ipv4_src",
5446 .help = "Set a new IPv4 source address in the outermost"
5448 .priv = PRIV_ACTION(SET_IPV4_SRC,
5449 sizeof(struct rte_flow_action_set_ipv4)),
5450 .next = NEXT(action_set_ipv4_src),
5453 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
5454 .name = "ipv4_addr",
5455 .help = "new IPv4 source address to set",
5456 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
5457 .args = ARGS(ARGS_ENTRY_HTON
5458 (struct rte_flow_action_set_ipv4, ipv4_addr)),
5459 .call = parse_vc_conf,
5461 [ACTION_SET_IPV4_DST] = {
5462 .name = "set_ipv4_dst",
5463 .help = "Set a new IPv4 destination address in the outermost"
5465 .priv = PRIV_ACTION(SET_IPV4_DST,
5466 sizeof(struct rte_flow_action_set_ipv4)),
5467 .next = NEXT(action_set_ipv4_dst),
5470 [ACTION_SET_IPV4_DST_IPV4_DST] = {
5471 .name = "ipv4_addr",
5472 .help = "new IPv4 destination address to set",
5473 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
5474 .args = ARGS(ARGS_ENTRY_HTON
5475 (struct rte_flow_action_set_ipv4, ipv4_addr)),
5476 .call = parse_vc_conf,
5478 [ACTION_SET_IPV6_SRC] = {
5479 .name = "set_ipv6_src",
5480 .help = "Set a new IPv6 source address in the outermost"
5482 .priv = PRIV_ACTION(SET_IPV6_SRC,
5483 sizeof(struct rte_flow_action_set_ipv6)),
5484 .next = NEXT(action_set_ipv6_src),
5487 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
5488 .name = "ipv6_addr",
5489 .help = "new IPv6 source address to set",
5490 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
5491 .args = ARGS(ARGS_ENTRY_HTON
5492 (struct rte_flow_action_set_ipv6, ipv6_addr)),
5493 .call = parse_vc_conf,
5495 [ACTION_SET_IPV6_DST] = {
5496 .name = "set_ipv6_dst",
5497 .help = "Set a new IPv6 destination address in the outermost"
5499 .priv = PRIV_ACTION(SET_IPV6_DST,
5500 sizeof(struct rte_flow_action_set_ipv6)),
5501 .next = NEXT(action_set_ipv6_dst),
5504 [ACTION_SET_IPV6_DST_IPV6_DST] = {
5505 .name = "ipv6_addr",
5506 .help = "new IPv6 destination address to set",
5507 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
5508 .args = ARGS(ARGS_ENTRY_HTON
5509 (struct rte_flow_action_set_ipv6, ipv6_addr)),
5510 .call = parse_vc_conf,
5512 [ACTION_SET_TP_SRC] = {
5513 .name = "set_tp_src",
5514 .help = "set a new source port number in the outermost"
5516 .priv = PRIV_ACTION(SET_TP_SRC,
5517 sizeof(struct rte_flow_action_set_tp)),
5518 .next = NEXT(action_set_tp_src),
5521 [ACTION_SET_TP_SRC_TP_SRC] = {
5523 .help = "new source port number to set",
5524 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
5525 .args = ARGS(ARGS_ENTRY_HTON
5526 (struct rte_flow_action_set_tp, port)),
5527 .call = parse_vc_conf,
5529 [ACTION_SET_TP_DST] = {
5530 .name = "set_tp_dst",
5531 .help = "set a new destination port number in the outermost"
5533 .priv = PRIV_ACTION(SET_TP_DST,
5534 sizeof(struct rte_flow_action_set_tp)),
5535 .next = NEXT(action_set_tp_dst),
5538 [ACTION_SET_TP_DST_TP_DST] = {
5540 .help = "new destination port number to set",
5541 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
5542 .args = ARGS(ARGS_ENTRY_HTON
5543 (struct rte_flow_action_set_tp, port)),
5544 .call = parse_vc_conf,
5546 [ACTION_MAC_SWAP] = {
5548 .help = "Swap the source and destination MAC addresses"
5549 " in the outermost Ethernet header",
5550 .priv = PRIV_ACTION(MAC_SWAP, 0),
5551 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5554 [ACTION_DEC_TTL] = {
5556 .help = "decrease network TTL if available",
5557 .priv = PRIV_ACTION(DEC_TTL, 0),
5558 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5561 [ACTION_SET_TTL] = {
5563 .help = "set ttl value",
5564 .priv = PRIV_ACTION(SET_TTL,
5565 sizeof(struct rte_flow_action_set_ttl)),
5566 .next = NEXT(action_set_ttl),
5569 [ACTION_SET_TTL_TTL] = {
5570 .name = "ttl_value",
5571 .help = "new ttl value to set",
5572 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5573 .args = ARGS(ARGS_ENTRY_HTON
5574 (struct rte_flow_action_set_ttl, ttl_value)),
5575 .call = parse_vc_conf,
5577 [ACTION_SET_MAC_SRC] = {
5578 .name = "set_mac_src",
5579 .help = "set source mac address",
5580 .priv = PRIV_ACTION(SET_MAC_SRC,
5581 sizeof(struct rte_flow_action_set_mac)),
5582 .next = NEXT(action_set_mac_src),
5585 [ACTION_SET_MAC_SRC_MAC_SRC] = {
5587 .help = "new source mac address",
5588 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
5589 .args = ARGS(ARGS_ENTRY_HTON
5590 (struct rte_flow_action_set_mac, mac_addr)),
5591 .call = parse_vc_conf,
5593 [ACTION_SET_MAC_DST] = {
5594 .name = "set_mac_dst",
5595 .help = "set destination mac address",
5596 .priv = PRIV_ACTION(SET_MAC_DST,
5597 sizeof(struct rte_flow_action_set_mac)),
5598 .next = NEXT(action_set_mac_dst),
5601 [ACTION_SET_MAC_DST_MAC_DST] = {
5603 .help = "new destination mac address to set",
5604 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
5605 .args = ARGS(ARGS_ENTRY_HTON
5606 (struct rte_flow_action_set_mac, mac_addr)),
5607 .call = parse_vc_conf,
5609 [ACTION_INC_TCP_SEQ] = {
5610 .name = "inc_tcp_seq",
5611 .help = "increase TCP sequence number",
5612 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
5613 .next = NEXT(action_inc_tcp_seq),
5616 [ACTION_INC_TCP_SEQ_VALUE] = {
5618 .help = "the value to increase TCP sequence number by",
5619 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5620 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5621 .call = parse_vc_conf,
5623 [ACTION_DEC_TCP_SEQ] = {
5624 .name = "dec_tcp_seq",
5625 .help = "decrease TCP sequence number",
5626 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
5627 .next = NEXT(action_dec_tcp_seq),
5630 [ACTION_DEC_TCP_SEQ_VALUE] = {
5632 .help = "the value to decrease TCP sequence number by",
5633 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5634 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5635 .call = parse_vc_conf,
5637 [ACTION_INC_TCP_ACK] = {
5638 .name = "inc_tcp_ack",
5639 .help = "increase TCP acknowledgment number",
5640 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
5641 .next = NEXT(action_inc_tcp_ack),
5644 [ACTION_INC_TCP_ACK_VALUE] = {
5646 .help = "the value to increase TCP acknowledgment number by",
5647 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5648 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5649 .call = parse_vc_conf,
5651 [ACTION_DEC_TCP_ACK] = {
5652 .name = "dec_tcp_ack",
5653 .help = "decrease TCP acknowledgment number",
5654 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
5655 .next = NEXT(action_dec_tcp_ack),
5658 [ACTION_DEC_TCP_ACK_VALUE] = {
5660 .help = "the value to decrease TCP acknowledgment number by",
5661 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5662 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5663 .call = parse_vc_conf,
5665 [ACTION_RAW_ENCAP] = {
5666 .name = "raw_encap",
5667 .help = "encapsulation data, defined by set raw_encap",
5668 .priv = PRIV_ACTION(RAW_ENCAP,
5669 sizeof(struct action_raw_encap_data)),
5670 .next = NEXT(action_raw_encap),
5671 .call = parse_vc_action_raw_encap,
5673 [ACTION_RAW_ENCAP_INDEX] = {
5675 .help = "the index of raw_encap_confs",
5676 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
5678 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
5681 .help = "unsigned integer value",
5682 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5683 .call = parse_vc_action_raw_encap_index,
5684 .comp = comp_set_raw_index,
5686 [ACTION_RAW_DECAP] = {
5687 .name = "raw_decap",
5688 .help = "decapsulation data, defined by set raw_encap",
5689 .priv = PRIV_ACTION(RAW_DECAP,
5690 sizeof(struct action_raw_decap_data)),
5691 .next = NEXT(action_raw_decap),
5692 .call = parse_vc_action_raw_decap,
5694 [ACTION_RAW_DECAP_INDEX] = {
5696 .help = "the index of raw_encap_confs",
5697 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
5699 [ACTION_RAW_DECAP_INDEX_VALUE] = {
5702 .help = "unsigned integer value",
5703 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5704 .call = parse_vc_action_raw_decap_index,
5705 .comp = comp_set_raw_index,
5707 [ACTION_MODIFY_FIELD] = {
5708 .name = "modify_field",
5709 .help = "modify destination field with data from source field",
5710 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
5711 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
5714 [ACTION_MODIFY_FIELD_OP] = {
5716 .help = "operation type",
5717 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
5718 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
5719 .call = parse_vc_conf,
5721 [ACTION_MODIFY_FIELD_OP_VALUE] = {
5722 .name = "{operation}",
5723 .help = "operation type value",
5724 .call = parse_vc_modify_field_op,
5725 .comp = comp_set_modify_field_op,
5727 [ACTION_MODIFY_FIELD_DST_TYPE] = {
5729 .help = "destination field type",
5730 .next = NEXT(action_modify_field_dst,
5731 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
5732 .call = parse_vc_conf,
5734 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
5735 .name = "{dst_type}",
5736 .help = "destination field type value",
5737 .call = parse_vc_modify_field_id,
5738 .comp = comp_set_modify_field_id,
5740 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
5741 .name = "dst_level",
5742 .help = "destination field level",
5743 .next = NEXT(action_modify_field_dst,
5744 NEXT_ENTRY(COMMON_UNSIGNED)),
5745 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5747 .call = parse_vc_conf,
5749 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
5750 .name = "dst_offset",
5751 .help = "destination field bit offset",
5752 .next = NEXT(action_modify_field_dst,
5753 NEXT_ENTRY(COMMON_UNSIGNED)),
5754 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5756 .call = parse_vc_conf,
5758 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
5760 .help = "source field type",
5761 .next = NEXT(action_modify_field_src,
5762 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
5763 .call = parse_vc_conf,
5765 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
5766 .name = "{src_type}",
5767 .help = "source field type value",
5768 .call = parse_vc_modify_field_id,
5769 .comp = comp_set_modify_field_id,
5771 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
5772 .name = "src_level",
5773 .help = "source field level",
5774 .next = NEXT(action_modify_field_src,
5775 NEXT_ENTRY(COMMON_UNSIGNED)),
5776 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5778 .call = parse_vc_conf,
5780 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
5781 .name = "src_offset",
5782 .help = "source field bit offset",
5783 .next = NEXT(action_modify_field_src,
5784 NEXT_ENTRY(COMMON_UNSIGNED)),
5785 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5787 .call = parse_vc_conf,
5789 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
5790 .name = "src_value",
5791 .help = "source immediate value",
5792 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5793 NEXT_ENTRY(COMMON_HEX)),
5794 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
5795 ARGS_ENTRY_ARB(0, 0),
5796 ARGS_ENTRY(struct rte_flow_action_modify_field,
5798 .call = parse_vc_conf,
5800 [ACTION_MODIFY_FIELD_SRC_POINTER] = {
5802 .help = "pointer to source immediate value",
5803 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5804 NEXT_ENTRY(COMMON_HEX)),
5805 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5807 ARGS_ENTRY_ARB(0, 0),
5809 (sizeof(struct rte_flow_action_modify_field),
5810 ACTION_MODIFY_PATTERN_SIZE)),
5811 .call = parse_vc_conf,
5813 [ACTION_MODIFY_FIELD_WIDTH] = {
5815 .help = "number of bits to copy",
5816 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5817 NEXT_ENTRY(COMMON_UNSIGNED)),
5818 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5820 .call = parse_vc_conf,
5822 /* Top level command. */
5825 .help = "set raw encap/decap/sample data",
5826 .type = "set raw_encap|raw_decap <index> <pattern>"
5827 " or set sample_actions <index> <action>",
5828 .next = NEXT(NEXT_ENTRY
5831 SET_SAMPLE_ACTIONS)),
5832 .call = parse_set_init,
5834 /* Sub-level commands. */
5836 .name = "raw_encap",
5837 .help = "set raw encap data",
5838 .next = NEXT(next_set_raw),
5839 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5840 (offsetof(struct buffer, port),
5841 sizeof(((struct buffer *)0)->port),
5842 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5843 .call = parse_set_raw_encap_decap,
5846 .name = "raw_decap",
5847 .help = "set raw decap data",
5848 .next = NEXT(next_set_raw),
5849 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5850 (offsetof(struct buffer, port),
5851 sizeof(((struct buffer *)0)->port),
5852 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5853 .call = parse_set_raw_encap_decap,
5857 .type = "COMMON_UNSIGNED",
5858 .help = "index of raw_encap/raw_decap data",
5859 .next = NEXT(next_item),
5862 [SET_SAMPLE_INDEX] = {
5865 .help = "index of sample actions",
5866 .next = NEXT(next_action_sample),
5869 [SET_SAMPLE_ACTIONS] = {
5870 .name = "sample_actions",
5871 .help = "set sample actions list",
5872 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
5873 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5874 (offsetof(struct buffer, port),
5875 sizeof(((struct buffer *)0)->port),
5876 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
5877 .call = parse_set_sample_action,
5879 [ACTION_SET_TAG] = {
5882 .priv = PRIV_ACTION(SET_TAG,
5883 sizeof(struct rte_flow_action_set_tag)),
5884 .next = NEXT(action_set_tag),
5887 [ACTION_SET_TAG_INDEX] = {
5889 .help = "index of tag array",
5890 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5891 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
5892 .call = parse_vc_conf,
5894 [ACTION_SET_TAG_DATA] = {
5896 .help = "tag value",
5897 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5898 .args = ARGS(ARGS_ENTRY
5899 (struct rte_flow_action_set_tag, data)),
5900 .call = parse_vc_conf,
5902 [ACTION_SET_TAG_MASK] = {
5904 .help = "mask for tag value",
5905 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5906 .args = ARGS(ARGS_ENTRY
5907 (struct rte_flow_action_set_tag, mask)),
5908 .call = parse_vc_conf,
5910 [ACTION_SET_META] = {
5912 .help = "set metadata",
5913 .priv = PRIV_ACTION(SET_META,
5914 sizeof(struct rte_flow_action_set_meta)),
5915 .next = NEXT(action_set_meta),
5916 .call = parse_vc_action_set_meta,
5918 [ACTION_SET_META_DATA] = {
5920 .help = "metadata value",
5921 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5922 .args = ARGS(ARGS_ENTRY
5923 (struct rte_flow_action_set_meta, data)),
5924 .call = parse_vc_conf,
5926 [ACTION_SET_META_MASK] = {
5928 .help = "mask for metadata value",
5929 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5930 .args = ARGS(ARGS_ENTRY
5931 (struct rte_flow_action_set_meta, mask)),
5932 .call = parse_vc_conf,
5934 [ACTION_SET_IPV4_DSCP] = {
5935 .name = "set_ipv4_dscp",
5936 .help = "set DSCP value",
5937 .priv = PRIV_ACTION(SET_IPV4_DSCP,
5938 sizeof(struct rte_flow_action_set_dscp)),
5939 .next = NEXT(action_set_ipv4_dscp),
5942 [ACTION_SET_IPV4_DSCP_VALUE] = {
5943 .name = "dscp_value",
5944 .help = "new IPv4 DSCP value to set",
5945 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5946 .args = ARGS(ARGS_ENTRY
5947 (struct rte_flow_action_set_dscp, dscp)),
5948 .call = parse_vc_conf,
5950 [ACTION_SET_IPV6_DSCP] = {
5951 .name = "set_ipv6_dscp",
5952 .help = "set DSCP value",
5953 .priv = PRIV_ACTION(SET_IPV6_DSCP,
5954 sizeof(struct rte_flow_action_set_dscp)),
5955 .next = NEXT(action_set_ipv6_dscp),
5958 [ACTION_SET_IPV6_DSCP_VALUE] = {
5959 .name = "dscp_value",
5960 .help = "new IPv6 DSCP value to set",
5961 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5962 .args = ARGS(ARGS_ENTRY
5963 (struct rte_flow_action_set_dscp, dscp)),
5964 .call = parse_vc_conf,
5968 .help = "set a specific metadata header",
5969 .next = NEXT(action_age),
5970 .priv = PRIV_ACTION(AGE,
5971 sizeof(struct rte_flow_action_age)),
5974 [ACTION_AGE_TIMEOUT] = {
5976 .help = "flow age timeout value",
5977 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
5979 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
5980 .call = parse_vc_conf,
5984 .help = "set a sample action",
5985 .next = NEXT(action_sample),
5986 .priv = PRIV_ACTION(SAMPLE,
5987 sizeof(struct action_sample_data)),
5988 .call = parse_vc_action_sample,
5990 [ACTION_SAMPLE_RATIO] = {
5992 .help = "flow sample ratio value",
5993 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
5994 .args = ARGS(ARGS_ENTRY_ARB
5995 (offsetof(struct action_sample_data, conf) +
5996 offsetof(struct rte_flow_action_sample, ratio),
5997 sizeof(((struct rte_flow_action_sample *)0)->
6000 [ACTION_SAMPLE_INDEX] = {
6002 .help = "the index of sample actions list",
6003 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
6005 [ACTION_SAMPLE_INDEX_VALUE] = {
6007 .type = "COMMON_UNSIGNED",
6008 .help = "unsigned integer value",
6009 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6010 .call = parse_vc_action_sample_index,
6011 .comp = comp_set_sample_index,
6013 [ACTION_CONNTRACK] = {
6014 .name = "conntrack",
6015 .help = "create a conntrack object",
6016 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6017 .priv = PRIV_ACTION(CONNTRACK,
6018 sizeof(struct rte_flow_action_conntrack)),
6021 [ACTION_CONNTRACK_UPDATE] = {
6022 .name = "conntrack_update",
6023 .help = "update a conntrack object",
6024 .next = NEXT(action_update_conntrack),
6025 .priv = PRIV_ACTION(CONNTRACK,
6026 sizeof(struct rte_flow_modify_conntrack)),
6029 [ACTION_CONNTRACK_UPDATE_DIR] = {
6031 .help = "update a conntrack object direction",
6032 .next = NEXT(action_update_conntrack),
6033 .call = parse_vc_action_conntrack_update,
6035 [ACTION_CONNTRACK_UPDATE_CTX] = {
6037 .help = "update a conntrack object context",
6038 .next = NEXT(action_update_conntrack),
6039 .call = parse_vc_action_conntrack_update,
6041 [ACTION_PORT_REPRESENTOR] = {
6042 .name = "port_representor",
6043 .help = "at embedded switch level, send matching traffic to the given ethdev",
6044 .priv = PRIV_ACTION(PORT_REPRESENTOR,
6045 sizeof(struct rte_flow_action_ethdev)),
6046 .next = NEXT(action_port_representor),
6049 [ACTION_PORT_REPRESENTOR_PORT_ID] = {
6051 .help = "ethdev port ID",
6052 .next = NEXT(action_port_representor,
6053 NEXT_ENTRY(COMMON_UNSIGNED)),
6054 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6056 .call = parse_vc_conf,
6058 [ACTION_REPRESENTED_PORT] = {
6059 .name = "represented_port",
6060 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
6061 .priv = PRIV_ACTION(REPRESENTED_PORT,
6062 sizeof(struct rte_flow_action_ethdev)),
6063 .next = NEXT(action_represented_port),
6066 [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
6067 .name = "ethdev_port_id",
6068 .help = "ethdev port ID",
6069 .next = NEXT(action_represented_port,
6070 NEXT_ENTRY(COMMON_UNSIGNED)),
6071 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6073 .call = parse_vc_conf,
6075 /* Indirect action destroy arguments. */
6076 [INDIRECT_ACTION_DESTROY_ID] = {
6077 .name = "action_id",
6078 .help = "specify a indirect action id to destroy",
6079 .next = NEXT(next_ia_destroy_attr,
6080 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6081 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
6082 args.ia_destroy.action_id)),
6083 .call = parse_ia_destroy,
6085 /* Indirect action create arguments. */
6086 [INDIRECT_ACTION_CREATE_ID] = {
6087 .name = "action_id",
6088 .help = "specify a indirect action id to create",
6089 .next = NEXT(next_ia_create_attr,
6090 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6091 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
6093 [ACTION_INDIRECT] = {
6095 .help = "apply indirect action by id",
6096 .priv = PRIV_ACTION(INDIRECT, 0),
6097 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
6098 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6101 [INDIRECT_ACTION_ID2PTR] = {
6102 .name = "{action_id}",
6103 .type = "INDIRECT_ACTION_ID",
6104 .help = "indirect action id",
6105 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6106 .call = parse_ia_id2ptr,
6109 [INDIRECT_ACTION_INGRESS] = {
6111 .help = "affect rule to ingress",
6112 .next = NEXT(next_ia_create_attr),
6115 [INDIRECT_ACTION_EGRESS] = {
6117 .help = "affect rule to egress",
6118 .next = NEXT(next_ia_create_attr),
6121 [INDIRECT_ACTION_TRANSFER] = {
6123 .help = "affect rule to transfer",
6124 .next = NEXT(next_ia_create_attr),
6127 [INDIRECT_ACTION_SPEC] = {
6129 .help = "specify action to create indirect handle",
6130 .next = NEXT(next_action),
6133 .name = "g_actions",
6134 .help = "submit a list of associated actions for green",
6135 .next = NEXT(next_action),
6139 .name = "y_actions",
6140 .help = "submit a list of associated actions for yellow",
6141 .next = NEXT(next_action),
6144 .name = "r_actions",
6145 .help = "submit a list of associated actions for red",
6146 .next = NEXT(next_action),
6149 /* Top-level command. */
6152 .type = "port meter policy {port_id} {arg}",
6153 .help = "add port meter policy",
6154 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
6157 /* Sub-level commands. */
6160 .help = "add port meter policy",
6161 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
6163 [ITEM_POL_METER] = {
6165 .help = "add port meter policy",
6166 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
6168 [ITEM_POL_POLICY] = {
6170 .help = "add port meter policy",
6171 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
6172 NEXT_ENTRY(ACTION_POL_Y),
6173 NEXT_ENTRY(ACTION_POL_G),
6174 NEXT_ENTRY(COMMON_POLICY_ID),
6175 NEXT_ENTRY(COMMON_PORT_ID)),
6176 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
6177 ARGS_ENTRY(struct buffer, port)),
6182 /** Remove and return last entry from argument stack. */
6183 static const struct arg *
6184 pop_args(struct context *ctx)
6186 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
6189 /** Add entry on top of the argument stack. */
6191 push_args(struct context *ctx, const struct arg *arg)
6193 if (ctx->args_num == CTX_STACK_SIZE)
6195 ctx->args[ctx->args_num++] = arg;
6199 /** Spread value into buffer according to bit-mask. */
6201 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
6203 uint32_t i = arg->size;
6211 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6220 unsigned int shift = 0;
6221 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
6223 for (shift = 0; arg->mask[i] >> shift; ++shift) {
6224 if (!(arg->mask[i] & (1 << shift)))
6229 *buf &= ~(1 << shift);
6230 *buf |= (val & 1) << shift;
6238 /** Compare a string with a partial one of a given length. */
6240 strcmp_partial(const char *full, const char *partial, size_t partial_len)
6242 int r = strncmp(full, partial, partial_len);
6246 if (strlen(full) <= partial_len)
6248 return full[partial_len];
6252 * Parse a prefix length and generate a bit-mask.
6254 * Last argument (ctx->args) is retrieved to determine mask size, storage
6255 * location and whether the result must use network byte ordering.
6258 parse_prefix(struct context *ctx, const struct token *token,
6259 const char *str, unsigned int len,
6260 void *buf, unsigned int size)
6262 const struct arg *arg = pop_args(ctx);
6263 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
6270 /* Argument is expected. */
6274 u = strtoumax(str, &end, 0);
6275 if (errno || (size_t)(end - str) != len)
6280 extra = arg_entry_bf_fill(NULL, 0, arg);
6289 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
6290 !arg_entry_bf_fill(ctx->objmask, -1, arg))
6297 if (bytes > size || bytes + !!extra > size)
6301 buf = (uint8_t *)ctx->object + arg->offset;
6302 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
6304 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
6305 memset(buf, 0x00, size - bytes);
6307 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
6311 memset(buf, 0xff, bytes);
6312 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
6314 ((uint8_t *)buf)[bytes] = conv[extra];
6317 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
6320 push_args(ctx, arg);
6324 /** Default parsing function for token name matching. */
6326 parse_default(struct context *ctx, const struct token *token,
6327 const char *str, unsigned int len,
6328 void *buf, unsigned int size)
6333 if (strcmp_partial(token->name, str, len))
6338 /** Parse flow command, initialize output buffer for subsequent tokens. */
6340 parse_init(struct context *ctx, const struct token *token,
6341 const char *str, unsigned int len,
6342 void *buf, unsigned int size)
6344 struct buffer *out = buf;
6346 /* Token name must match. */
6347 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6349 /* Nothing else to do if there is no buffer. */
6352 /* Make sure buffer is large enough. */
6353 if (size < sizeof(*out))
6355 /* Initialize buffer. */
6356 memset(out, 0x00, sizeof(*out));
6357 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
6360 ctx->objmask = NULL;
6364 /** Parse tokens for indirect action commands. */
6366 parse_ia(struct context *ctx, const struct token *token,
6367 const char *str, unsigned int len,
6368 void *buf, unsigned int size)
6370 struct buffer *out = buf;
6372 /* Token name must match. */
6373 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6375 /* Nothing else to do if there is no buffer. */
6378 if (!out->command) {
6379 if (ctx->curr != INDIRECT_ACTION)
6381 if (sizeof(*out) > size)
6383 out->command = ctx->curr;
6386 ctx->objmask = NULL;
6387 out->args.vc.data = (uint8_t *)out + size;
6390 switch (ctx->curr) {
6391 case INDIRECT_ACTION_CREATE:
6392 case INDIRECT_ACTION_UPDATE:
6393 out->args.vc.actions =
6394 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6396 out->args.vc.attr.group = UINT32_MAX;
6398 case INDIRECT_ACTION_QUERY:
6399 out->command = ctx->curr;
6402 ctx->objmask = NULL;
6404 case INDIRECT_ACTION_EGRESS:
6405 out->args.vc.attr.egress = 1;
6407 case INDIRECT_ACTION_INGRESS:
6408 out->args.vc.attr.ingress = 1;
6410 case INDIRECT_ACTION_TRANSFER:
6411 out->args.vc.attr.transfer = 1;
6419 /** Parse tokens for indirect action destroy command. */
6421 parse_ia_destroy(struct context *ctx, const struct token *token,
6422 const char *str, unsigned int len,
6423 void *buf, unsigned int size)
6425 struct buffer *out = buf;
6426 uint32_t *action_id;
6428 /* Token name must match. */
6429 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6431 /* Nothing else to do if there is no buffer. */
6434 if (!out->command || out->command == INDIRECT_ACTION) {
6435 if (ctx->curr != INDIRECT_ACTION_DESTROY)
6437 if (sizeof(*out) > size)
6439 out->command = ctx->curr;
6442 ctx->objmask = NULL;
6443 out->args.ia_destroy.action_id =
6444 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6448 action_id = out->args.ia_destroy.action_id
6449 + out->args.ia_destroy.action_id_n++;
6450 if ((uint8_t *)action_id > (uint8_t *)out + size)
6453 ctx->object = action_id;
6454 ctx->objmask = NULL;
6458 /** Parse tokens for meter policy action commands. */
6460 parse_mp(struct context *ctx, const struct token *token,
6461 const char *str, unsigned int len,
6462 void *buf, unsigned int size)
6464 struct buffer *out = buf;
6466 /* Token name must match. */
6467 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6469 /* Nothing else to do if there is no buffer. */
6472 if (!out->command) {
6473 if (ctx->curr != ITEM_POL_POLICY)
6475 if (sizeof(*out) > size)
6477 out->command = ctx->curr;
6480 ctx->objmask = NULL;
6481 out->args.vc.data = (uint8_t *)out + size;
6484 switch (ctx->curr) {
6486 out->args.vc.actions =
6487 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6489 out->command = ctx->curr;
6492 ctx->objmask = NULL;
6499 /** Parse tokens for validate/create commands. */
6501 parse_vc(struct context *ctx, const struct token *token,
6502 const char *str, unsigned int len,
6503 void *buf, unsigned int size)
6505 struct buffer *out = buf;
6509 /* Token name must match. */
6510 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6512 /* Nothing else to do if there is no buffer. */
6515 if (!out->command) {
6516 if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
6517 ctx->curr != PATTERN_TEMPLATE_CREATE &&
6518 ctx->curr != ACTIONS_TEMPLATE_CREATE)
6520 if (sizeof(*out) > size)
6522 out->command = ctx->curr;
6525 ctx->objmask = NULL;
6526 out->args.vc.data = (uint8_t *)out + size;
6530 switch (ctx->curr) {
6532 ctx->object = &out->args.vc.attr;
6535 case VC_TUNNEL_MATCH:
6536 ctx->object = &out->args.vc.tunnel_ops;
6539 ctx->objmask = NULL;
6540 switch (ctx->curr) {
6545 out->args.vc.tunnel_ops.enabled = 1;
6546 out->args.vc.tunnel_ops.actions = 1;
6548 case VC_TUNNEL_MATCH:
6549 out->args.vc.tunnel_ops.enabled = 1;
6550 out->args.vc.tunnel_ops.items = 1;
6553 out->args.vc.attr.ingress = 1;
6556 out->args.vc.attr.egress = 1;
6559 out->args.vc.attr.transfer = 1;
6562 out->args.vc.pattern =
6563 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6565 ctx->object = out->args.vc.pattern;
6566 ctx->objmask = NULL;
6569 out->args.vc.actions =
6570 (void *)RTE_ALIGN_CEIL((uintptr_t)
6571 (out->args.vc.pattern +
6572 out->args.vc.pattern_n),
6574 ctx->object = out->args.vc.actions;
6575 ctx->objmask = NULL;
6582 if (!out->args.vc.actions) {
6583 const struct parse_item_priv *priv = token->priv;
6584 struct rte_flow_item *item =
6585 out->args.vc.pattern + out->args.vc.pattern_n;
6587 data_size = priv->size * 3; /* spec, last, mask */
6588 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6589 (out->args.vc.data - data_size),
6591 if ((uint8_t *)item + sizeof(*item) > data)
6593 *item = (struct rte_flow_item){
6596 ++out->args.vc.pattern_n;
6598 ctx->objmask = NULL;
6600 const struct parse_action_priv *priv = token->priv;
6601 struct rte_flow_action *action =
6602 out->args.vc.actions + out->args.vc.actions_n;
6604 data_size = priv->size; /* configuration */
6605 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6606 (out->args.vc.data - data_size),
6608 if ((uint8_t *)action + sizeof(*action) > data)
6610 *action = (struct rte_flow_action){
6612 .conf = data_size ? data : NULL,
6614 ++out->args.vc.actions_n;
6615 ctx->object = action;
6616 ctx->objmask = NULL;
6618 memset(data, 0, data_size);
6619 out->args.vc.data = data;
6620 ctx->objdata = data_size;
6624 /** Parse pattern item parameter type. */
6626 parse_vc_spec(struct context *ctx, const struct token *token,
6627 const char *str, unsigned int len,
6628 void *buf, unsigned int size)
6630 struct buffer *out = buf;
6631 struct rte_flow_item *item;
6637 /* Token name must match. */
6638 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6640 /* Parse parameter types. */
6641 switch (ctx->curr) {
6642 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
6648 case ITEM_PARAM_SPEC:
6651 case ITEM_PARAM_LAST:
6654 case ITEM_PARAM_PREFIX:
6655 /* Modify next token to expect a prefix. */
6656 if (ctx->next_num < 2)
6658 ctx->next[ctx->next_num - 2] = prefix;
6660 case ITEM_PARAM_MASK:
6666 /* Nothing else to do if there is no buffer. */
6669 if (!out->args.vc.pattern_n)
6671 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6672 data_size = ctx->objdata / 3; /* spec, last, mask */
6673 /* Point to selected object. */
6674 ctx->object = out->args.vc.data + (data_size * index);
6676 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
6677 item->mask = ctx->objmask;
6679 ctx->objmask = NULL;
6680 /* Update relevant item pointer. */
6681 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
6686 /** Parse action configuration field. */
6688 parse_vc_conf(struct context *ctx, const struct token *token,
6689 const char *str, unsigned int len,
6690 void *buf, unsigned int size)
6692 struct buffer *out = buf;
6695 /* Token name must match. */
6696 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6698 /* Nothing else to do if there is no buffer. */
6701 /* Point to selected object. */
6702 ctx->object = out->args.vc.data;
6703 ctx->objmask = NULL;
6707 /** Parse eCPRI common header type field. */
6709 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
6710 const char *str, unsigned int len,
6711 void *buf, unsigned int size)
6713 struct rte_flow_item_ecpri *ecpri;
6714 struct rte_flow_item_ecpri *ecpri_mask;
6715 struct rte_flow_item *item;
6718 struct buffer *out = buf;
6719 const struct arg *arg;
6722 /* Token name must match. */
6723 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6725 switch (ctx->curr) {
6726 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
6727 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
6729 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
6730 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
6732 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
6733 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
6740 arg = pop_args(ctx);
6743 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
6744 ecpri->hdr.common.type = msg_type;
6745 data_size = ctx->objdata / 3; /* spec, last, mask */
6746 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
6748 ecpri_mask->hdr.common.type = 0xFF;
6750 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
6751 ecpri_mask->hdr.common.u32 =
6752 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
6754 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6756 item->mask = ecpri_mask;
6760 /** Parse L2TPv2 common header type field. */
6762 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
6763 const char *str, unsigned int len,
6764 void *buf, unsigned int size)
6766 struct rte_flow_item_l2tpv2 *l2tpv2;
6767 struct rte_flow_item_l2tpv2 *l2tpv2_mask;
6768 struct rte_flow_item *item;
6770 uint16_t msg_type = 0;
6771 struct buffer *out = buf;
6772 const struct arg *arg;
6775 /* Token name must match. */
6776 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6778 switch (ctx->curr) {
6779 case ITEM_L2TPV2_TYPE_DATA:
6780 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
6782 case ITEM_L2TPV2_TYPE_DATA_L:
6783 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
6785 case ITEM_L2TPV2_TYPE_DATA_S:
6786 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
6788 case ITEM_L2TPV2_TYPE_DATA_O:
6789 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
6791 case ITEM_L2TPV2_TYPE_DATA_L_S:
6792 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
6794 case ITEM_L2TPV2_TYPE_CTRL:
6795 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
6802 arg = pop_args(ctx);
6805 l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
6806 l2tpv2->hdr.common.flags_version |= msg_type;
6807 data_size = ctx->objdata / 3; /* spec, last, mask */
6808 l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
6810 l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
6812 l2tpv2->hdr.common.flags_version =
6813 rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
6814 l2tpv2_mask->hdr.common.flags_version =
6815 rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
6817 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6818 item->spec = l2tpv2;
6819 item->mask = l2tpv2_mask;
6823 /** Parse meter color action type. */
6825 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
6826 const char *str, unsigned int len,
6827 void *buf, unsigned int size)
6829 struct rte_flow_action *action_data;
6830 struct rte_flow_action_meter_color *conf;
6831 enum rte_color color;
6835 /* Token name must match. */
6836 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6838 switch (ctx->curr) {
6839 case ACTION_METER_COLOR_GREEN:
6840 color = RTE_COLOR_GREEN;
6842 case ACTION_METER_COLOR_YELLOW:
6843 color = RTE_COLOR_YELLOW;
6845 case ACTION_METER_COLOR_RED:
6846 color = RTE_COLOR_RED;
6854 action_data = ctx->object;
6855 conf = (struct rte_flow_action_meter_color *)
6856 (uintptr_t)(action_data->conf);
6857 conf->color = color;
6861 /** Parse RSS action. */
6863 parse_vc_action_rss(struct context *ctx, const struct token *token,
6864 const char *str, unsigned int len,
6865 void *buf, unsigned int size)
6867 struct buffer *out = buf;
6868 struct rte_flow_action *action;
6869 struct action_rss_data *action_rss_data;
6873 ret = parse_vc(ctx, token, str, len, buf, size);
6876 /* Nothing else to do if there is no buffer. */
6879 if (!out->args.vc.actions_n)
6881 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6882 /* Point to selected object. */
6883 ctx->object = out->args.vc.data;
6884 ctx->objmask = NULL;
6885 /* Set up default configuration. */
6886 action_rss_data = ctx->object;
6887 *action_rss_data = (struct action_rss_data){
6888 .conf = (struct rte_flow_action_rss){
6889 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
6893 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
6895 .queue = action_rss_data->queue,
6899 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
6900 action_rss_data->queue[i] = i;
6901 action->conf = &action_rss_data->conf;
6906 * Parse func field for RSS action.
6908 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
6909 * ACTION_RSS_FUNC_* index that called this function.
6912 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
6913 const char *str, unsigned int len,
6914 void *buf, unsigned int size)
6916 struct action_rss_data *action_rss_data;
6917 enum rte_eth_hash_function func;
6921 /* Token name must match. */
6922 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6924 switch (ctx->curr) {
6925 case ACTION_RSS_FUNC_DEFAULT:
6926 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
6928 case ACTION_RSS_FUNC_TOEPLITZ:
6929 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
6931 case ACTION_RSS_FUNC_SIMPLE_XOR:
6932 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
6934 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
6935 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
6942 action_rss_data = ctx->object;
6943 action_rss_data->conf.func = func;
6948 * Parse type field for RSS action.
6950 * Valid tokens are type field names and the "end" token.
6953 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
6954 const char *str, unsigned int len,
6955 void *buf, unsigned int size)
6957 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
6958 struct action_rss_data *action_rss_data;
6964 if (ctx->curr != ACTION_RSS_TYPE)
6966 if (!(ctx->objdata >> 16) && ctx->object) {
6967 action_rss_data = ctx->object;
6968 action_rss_data->conf.types = 0;
6970 if (!strcmp_partial("end", str, len)) {
6971 ctx->objdata &= 0xffff;
6974 for (i = 0; rss_type_table[i].str; ++i)
6975 if (!strcmp_partial(rss_type_table[i].str, str, len))
6977 if (!rss_type_table[i].str)
6979 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
6981 if (ctx->next_num == RTE_DIM(ctx->next))
6983 ctx->next[ctx->next_num++] = next;
6986 action_rss_data = ctx->object;
6987 action_rss_data->conf.types |= rss_type_table[i].rss_type;
6992 * Parse queue field for RSS action.
6994 * Valid tokens are queue indices and the "end" token.
6997 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
6998 const char *str, unsigned int len,
6999 void *buf, unsigned int size)
7001 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
7002 struct action_rss_data *action_rss_data;
7003 const struct arg *arg;
7010 if (ctx->curr != ACTION_RSS_QUEUE)
7012 i = ctx->objdata >> 16;
7013 if (!strcmp_partial("end", str, len)) {
7014 ctx->objdata &= 0xffff;
7017 if (i >= ACTION_RSS_QUEUE_NUM)
7019 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
7020 i * sizeof(action_rss_data->queue[i]),
7021 sizeof(action_rss_data->queue[i]));
7022 if (push_args(ctx, arg))
7024 ret = parse_int(ctx, token, str, len, NULL, 0);
7030 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
7032 if (ctx->next_num == RTE_DIM(ctx->next))
7034 ctx->next[ctx->next_num++] = next;
7038 action_rss_data = ctx->object;
7039 action_rss_data->conf.queue_num = i;
7040 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
7044 /** Setup VXLAN encap configuration. */
7046 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
7048 /* Set up default configuration. */
7049 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
7050 .conf = (struct rte_flow_action_vxlan_encap){
7051 .definition = action_vxlan_encap_data->items,
7055 .type = RTE_FLOW_ITEM_TYPE_ETH,
7056 .spec = &action_vxlan_encap_data->item_eth,
7057 .mask = &rte_flow_item_eth_mask,
7060 .type = RTE_FLOW_ITEM_TYPE_VLAN,
7061 .spec = &action_vxlan_encap_data->item_vlan,
7062 .mask = &rte_flow_item_vlan_mask,
7065 .type = RTE_FLOW_ITEM_TYPE_IPV4,
7066 .spec = &action_vxlan_encap_data->item_ipv4,
7067 .mask = &rte_flow_item_ipv4_mask,
7070 .type = RTE_FLOW_ITEM_TYPE_UDP,
7071 .spec = &action_vxlan_encap_data->item_udp,
7072 .mask = &rte_flow_item_udp_mask,
7075 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
7076 .spec = &action_vxlan_encap_data->item_vxlan,
7077 .mask = &rte_flow_item_vxlan_mask,
7080 .type = RTE_FLOW_ITEM_TYPE_END,
7085 .tci = vxlan_encap_conf.vlan_tci,
7089 .src_addr = vxlan_encap_conf.ipv4_src,
7090 .dst_addr = vxlan_encap_conf.ipv4_dst,
7093 .src_port = vxlan_encap_conf.udp_src,
7094 .dst_port = vxlan_encap_conf.udp_dst,
7096 .item_vxlan.flags = 0,
7098 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
7099 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7100 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
7101 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7102 if (!vxlan_encap_conf.select_ipv4) {
7103 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
7104 &vxlan_encap_conf.ipv6_src,
7105 sizeof(vxlan_encap_conf.ipv6_src));
7106 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
7107 &vxlan_encap_conf.ipv6_dst,
7108 sizeof(vxlan_encap_conf.ipv6_dst));
7109 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
7110 .type = RTE_FLOW_ITEM_TYPE_IPV6,
7111 .spec = &action_vxlan_encap_data->item_ipv6,
7112 .mask = &rte_flow_item_ipv6_mask,
7115 if (!vxlan_encap_conf.select_vlan)
7116 action_vxlan_encap_data->items[1].type =
7117 RTE_FLOW_ITEM_TYPE_VOID;
7118 if (vxlan_encap_conf.select_tos_ttl) {
7119 if (vxlan_encap_conf.select_ipv4) {
7120 static struct rte_flow_item_ipv4 ipv4_mask_tos;
7122 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
7123 sizeof(ipv4_mask_tos));
7124 ipv4_mask_tos.hdr.type_of_service = 0xff;
7125 ipv4_mask_tos.hdr.time_to_live = 0xff;
7126 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
7127 vxlan_encap_conf.ip_tos;
7128 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
7129 vxlan_encap_conf.ip_ttl;
7130 action_vxlan_encap_data->items[2].mask =
7133 static struct rte_flow_item_ipv6 ipv6_mask_tos;
7135 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
7136 sizeof(ipv6_mask_tos));
7137 ipv6_mask_tos.hdr.vtc_flow |=
7138 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
7139 ipv6_mask_tos.hdr.hop_limits = 0xff;
7140 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
7142 ((uint32_t)vxlan_encap_conf.ip_tos <<
7143 RTE_IPV6_HDR_TC_SHIFT);
7144 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
7145 vxlan_encap_conf.ip_ttl;
7146 action_vxlan_encap_data->items[2].mask =
7150 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
7151 RTE_DIM(vxlan_encap_conf.vni));
7155 /** Parse VXLAN encap action. */
7157 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
7158 const char *str, unsigned int len,
7159 void *buf, unsigned int size)
7161 struct buffer *out = buf;
7162 struct rte_flow_action *action;
7163 struct action_vxlan_encap_data *action_vxlan_encap_data;
7166 ret = parse_vc(ctx, token, str, len, buf, size);
7169 /* Nothing else to do if there is no buffer. */
7172 if (!out->args.vc.actions_n)
7174 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7175 /* Point to selected object. */
7176 ctx->object = out->args.vc.data;
7177 ctx->objmask = NULL;
7178 action_vxlan_encap_data = ctx->object;
7179 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
7180 action->conf = &action_vxlan_encap_data->conf;
7184 /** Setup NVGRE encap configuration. */
7186 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
7188 /* Set up default configuration. */
7189 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
7190 .conf = (struct rte_flow_action_nvgre_encap){
7191 .definition = action_nvgre_encap_data->items,
7195 .type = RTE_FLOW_ITEM_TYPE_ETH,
7196 .spec = &action_nvgre_encap_data->item_eth,
7197 .mask = &rte_flow_item_eth_mask,
7200 .type = RTE_FLOW_ITEM_TYPE_VLAN,
7201 .spec = &action_nvgre_encap_data->item_vlan,
7202 .mask = &rte_flow_item_vlan_mask,
7205 .type = RTE_FLOW_ITEM_TYPE_IPV4,
7206 .spec = &action_nvgre_encap_data->item_ipv4,
7207 .mask = &rte_flow_item_ipv4_mask,
7210 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
7211 .spec = &action_nvgre_encap_data->item_nvgre,
7212 .mask = &rte_flow_item_nvgre_mask,
7215 .type = RTE_FLOW_ITEM_TYPE_END,
7220 .tci = nvgre_encap_conf.vlan_tci,
7224 .src_addr = nvgre_encap_conf.ipv4_src,
7225 .dst_addr = nvgre_encap_conf.ipv4_dst,
7227 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
7228 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
7229 .item_nvgre.flow_id = 0,
7231 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
7232 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7233 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
7234 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7235 if (!nvgre_encap_conf.select_ipv4) {
7236 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
7237 &nvgre_encap_conf.ipv6_src,
7238 sizeof(nvgre_encap_conf.ipv6_src));
7239 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
7240 &nvgre_encap_conf.ipv6_dst,
7241 sizeof(nvgre_encap_conf.ipv6_dst));
7242 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
7243 .type = RTE_FLOW_ITEM_TYPE_IPV6,
7244 .spec = &action_nvgre_encap_data->item_ipv6,
7245 .mask = &rte_flow_item_ipv6_mask,
7248 if (!nvgre_encap_conf.select_vlan)
7249 action_nvgre_encap_data->items[1].type =
7250 RTE_FLOW_ITEM_TYPE_VOID;
7251 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
7252 RTE_DIM(nvgre_encap_conf.tni));
7256 /** Parse NVGRE encap action. */
7258 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
7259 const char *str, unsigned int len,
7260 void *buf, unsigned int size)
7262 struct buffer *out = buf;
7263 struct rte_flow_action *action;
7264 struct action_nvgre_encap_data *action_nvgre_encap_data;
7267 ret = parse_vc(ctx, token, str, len, buf, size);
7270 /* Nothing else to do if there is no buffer. */
7273 if (!out->args.vc.actions_n)
7275 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7276 /* Point to selected object. */
7277 ctx->object = out->args.vc.data;
7278 ctx->objmask = NULL;
7279 action_nvgre_encap_data = ctx->object;
7280 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
7281 action->conf = &action_nvgre_encap_data->conf;
7285 /** Parse l2 encap action. */
7287 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
7288 const char *str, unsigned int len,
7289 void *buf, unsigned int size)
7291 struct buffer *out = buf;
7292 struct rte_flow_action *action;
7293 struct action_raw_encap_data *action_encap_data;
7294 struct rte_flow_item_eth eth = { .type = 0, };
7295 struct rte_flow_item_vlan vlan = {
7296 .tci = mplsoudp_encap_conf.vlan_tci,
7302 ret = parse_vc(ctx, token, str, len, buf, size);
7305 /* Nothing else to do if there is no buffer. */
7308 if (!out->args.vc.actions_n)
7310 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7311 /* Point to selected object. */
7312 ctx->object = out->args.vc.data;
7313 ctx->objmask = NULL;
7314 /* Copy the headers to the buffer. */
7315 action_encap_data = ctx->object;
7316 *action_encap_data = (struct action_raw_encap_data) {
7317 .conf = (struct rte_flow_action_raw_encap){
7318 .data = action_encap_data->data,
7322 header = action_encap_data->data;
7323 if (l2_encap_conf.select_vlan)
7324 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7325 else if (l2_encap_conf.select_ipv4)
7326 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7328 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7329 memcpy(eth.dst.addr_bytes,
7330 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7331 memcpy(eth.src.addr_bytes,
7332 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7333 memcpy(header, ð, sizeof(eth));
7334 header += sizeof(eth);
7335 if (l2_encap_conf.select_vlan) {
7336 if (l2_encap_conf.select_ipv4)
7337 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7339 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7340 memcpy(header, &vlan, sizeof(vlan));
7341 header += sizeof(vlan);
7343 action_encap_data->conf.size = header -
7344 action_encap_data->data;
7345 action->conf = &action_encap_data->conf;
7349 /** Parse l2 decap action. */
7351 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
7352 const char *str, unsigned int len,
7353 void *buf, unsigned int size)
7355 struct buffer *out = buf;
7356 struct rte_flow_action *action;
7357 struct action_raw_decap_data *action_decap_data;
7358 struct rte_flow_item_eth eth = { .type = 0, };
7359 struct rte_flow_item_vlan vlan = {
7360 .tci = mplsoudp_encap_conf.vlan_tci,
7366 ret = parse_vc(ctx, token, str, len, buf, size);
7369 /* Nothing else to do if there is no buffer. */
7372 if (!out->args.vc.actions_n)
7374 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7375 /* Point to selected object. */
7376 ctx->object = out->args.vc.data;
7377 ctx->objmask = NULL;
7378 /* Copy the headers to the buffer. */
7379 action_decap_data = ctx->object;
7380 *action_decap_data = (struct action_raw_decap_data) {
7381 .conf = (struct rte_flow_action_raw_decap){
7382 .data = action_decap_data->data,
7386 header = action_decap_data->data;
7387 if (l2_decap_conf.select_vlan)
7388 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7389 memcpy(header, ð, sizeof(eth));
7390 header += sizeof(eth);
7391 if (l2_decap_conf.select_vlan) {
7392 memcpy(header, &vlan, sizeof(vlan));
7393 header += sizeof(vlan);
7395 action_decap_data->conf.size = header -
7396 action_decap_data->data;
7397 action->conf = &action_decap_data->conf;
7401 #define ETHER_TYPE_MPLS_UNICAST 0x8847
7403 /** Parse MPLSOGRE encap action. */
7405 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
7406 const char *str, unsigned int len,
7407 void *buf, unsigned int size)
7409 struct buffer *out = buf;
7410 struct rte_flow_action *action;
7411 struct action_raw_encap_data *action_encap_data;
7412 struct rte_flow_item_eth eth = { .type = 0, };
7413 struct rte_flow_item_vlan vlan = {
7414 .tci = mplsogre_encap_conf.vlan_tci,
7417 struct rte_flow_item_ipv4 ipv4 = {
7419 .src_addr = mplsogre_encap_conf.ipv4_src,
7420 .dst_addr = mplsogre_encap_conf.ipv4_dst,
7421 .next_proto_id = IPPROTO_GRE,
7422 .version_ihl = RTE_IPV4_VHL_DEF,
7423 .time_to_live = IPDEFTTL,
7426 struct rte_flow_item_ipv6 ipv6 = {
7428 .proto = IPPROTO_GRE,
7429 .hop_limits = IPDEFTTL,
7432 struct rte_flow_item_gre gre = {
7433 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
7435 struct rte_flow_item_mpls mpls = {
7441 ret = parse_vc(ctx, token, str, len, buf, size);
7444 /* Nothing else to do if there is no buffer. */
7447 if (!out->args.vc.actions_n)
7449 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7450 /* Point to selected object. */
7451 ctx->object = out->args.vc.data;
7452 ctx->objmask = NULL;
7453 /* Copy the headers to the buffer. */
7454 action_encap_data = ctx->object;
7455 *action_encap_data = (struct action_raw_encap_data) {
7456 .conf = (struct rte_flow_action_raw_encap){
7457 .data = action_encap_data->data,
7462 header = action_encap_data->data;
7463 if (mplsogre_encap_conf.select_vlan)
7464 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7465 else if (mplsogre_encap_conf.select_ipv4)
7466 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7468 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7469 memcpy(eth.dst.addr_bytes,
7470 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7471 memcpy(eth.src.addr_bytes,
7472 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7473 memcpy(header, ð, sizeof(eth));
7474 header += sizeof(eth);
7475 if (mplsogre_encap_conf.select_vlan) {
7476 if (mplsogre_encap_conf.select_ipv4)
7477 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7479 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7480 memcpy(header, &vlan, sizeof(vlan));
7481 header += sizeof(vlan);
7483 if (mplsogre_encap_conf.select_ipv4) {
7484 memcpy(header, &ipv4, sizeof(ipv4));
7485 header += sizeof(ipv4);
7487 memcpy(&ipv6.hdr.src_addr,
7488 &mplsogre_encap_conf.ipv6_src,
7489 sizeof(mplsogre_encap_conf.ipv6_src));
7490 memcpy(&ipv6.hdr.dst_addr,
7491 &mplsogre_encap_conf.ipv6_dst,
7492 sizeof(mplsogre_encap_conf.ipv6_dst));
7493 memcpy(header, &ipv6, sizeof(ipv6));
7494 header += sizeof(ipv6);
7496 memcpy(header, &gre, sizeof(gre));
7497 header += sizeof(gre);
7498 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
7499 RTE_DIM(mplsogre_encap_conf.label));
7500 mpls.label_tc_s[2] |= 0x1;
7501 memcpy(header, &mpls, sizeof(mpls));
7502 header += sizeof(mpls);
7503 action_encap_data->conf.size = header -
7504 action_encap_data->data;
7505 action->conf = &action_encap_data->conf;
7509 /** Parse MPLSOGRE decap action. */
7511 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
7512 const char *str, unsigned int len,
7513 void *buf, unsigned int size)
7515 struct buffer *out = buf;
7516 struct rte_flow_action *action;
7517 struct action_raw_decap_data *action_decap_data;
7518 struct rte_flow_item_eth eth = { .type = 0, };
7519 struct rte_flow_item_vlan vlan = {.tci = 0};
7520 struct rte_flow_item_ipv4 ipv4 = {
7522 .next_proto_id = IPPROTO_GRE,
7525 struct rte_flow_item_ipv6 ipv6 = {
7527 .proto = IPPROTO_GRE,
7530 struct rte_flow_item_gre gre = {
7531 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
7533 struct rte_flow_item_mpls mpls;
7537 ret = parse_vc(ctx, token, str, len, buf, size);
7540 /* Nothing else to do if there is no buffer. */
7543 if (!out->args.vc.actions_n)
7545 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7546 /* Point to selected object. */
7547 ctx->object = out->args.vc.data;
7548 ctx->objmask = NULL;
7549 /* Copy the headers to the buffer. */
7550 action_decap_data = ctx->object;
7551 *action_decap_data = (struct action_raw_decap_data) {
7552 .conf = (struct rte_flow_action_raw_decap){
7553 .data = action_decap_data->data,
7557 header = action_decap_data->data;
7558 if (mplsogre_decap_conf.select_vlan)
7559 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7560 else if (mplsogre_encap_conf.select_ipv4)
7561 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7563 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7564 memcpy(eth.dst.addr_bytes,
7565 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7566 memcpy(eth.src.addr_bytes,
7567 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7568 memcpy(header, ð, sizeof(eth));
7569 header += sizeof(eth);
7570 if (mplsogre_encap_conf.select_vlan) {
7571 if (mplsogre_encap_conf.select_ipv4)
7572 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7574 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7575 memcpy(header, &vlan, sizeof(vlan));
7576 header += sizeof(vlan);
7578 if (mplsogre_encap_conf.select_ipv4) {
7579 memcpy(header, &ipv4, sizeof(ipv4));
7580 header += sizeof(ipv4);
7582 memcpy(header, &ipv6, sizeof(ipv6));
7583 header += sizeof(ipv6);
7585 memcpy(header, &gre, sizeof(gre));
7586 header += sizeof(gre);
7587 memset(&mpls, 0, sizeof(mpls));
7588 memcpy(header, &mpls, sizeof(mpls));
7589 header += sizeof(mpls);
7590 action_decap_data->conf.size = header -
7591 action_decap_data->data;
7592 action->conf = &action_decap_data->conf;
7596 /** Parse MPLSOUDP encap action. */
7598 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
7599 const char *str, unsigned int len,
7600 void *buf, unsigned int size)
7602 struct buffer *out = buf;
7603 struct rte_flow_action *action;
7604 struct action_raw_encap_data *action_encap_data;
7605 struct rte_flow_item_eth eth = { .type = 0, };
7606 struct rte_flow_item_vlan vlan = {
7607 .tci = mplsoudp_encap_conf.vlan_tci,
7610 struct rte_flow_item_ipv4 ipv4 = {
7612 .src_addr = mplsoudp_encap_conf.ipv4_src,
7613 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
7614 .next_proto_id = IPPROTO_UDP,
7615 .version_ihl = RTE_IPV4_VHL_DEF,
7616 .time_to_live = IPDEFTTL,
7619 struct rte_flow_item_ipv6 ipv6 = {
7621 .proto = IPPROTO_UDP,
7622 .hop_limits = IPDEFTTL,
7625 struct rte_flow_item_udp udp = {
7627 .src_port = mplsoudp_encap_conf.udp_src,
7628 .dst_port = mplsoudp_encap_conf.udp_dst,
7631 struct rte_flow_item_mpls mpls;
7635 ret = parse_vc(ctx, token, str, len, buf, size);
7638 /* Nothing else to do if there is no buffer. */
7641 if (!out->args.vc.actions_n)
7643 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7644 /* Point to selected object. */
7645 ctx->object = out->args.vc.data;
7646 ctx->objmask = NULL;
7647 /* Copy the headers to the buffer. */
7648 action_encap_data = ctx->object;
7649 *action_encap_data = (struct action_raw_encap_data) {
7650 .conf = (struct rte_flow_action_raw_encap){
7651 .data = action_encap_data->data,
7656 header = action_encap_data->data;
7657 if (mplsoudp_encap_conf.select_vlan)
7658 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7659 else if (mplsoudp_encap_conf.select_ipv4)
7660 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7662 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7663 memcpy(eth.dst.addr_bytes,
7664 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7665 memcpy(eth.src.addr_bytes,
7666 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7667 memcpy(header, ð, sizeof(eth));
7668 header += sizeof(eth);
7669 if (mplsoudp_encap_conf.select_vlan) {
7670 if (mplsoudp_encap_conf.select_ipv4)
7671 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7673 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7674 memcpy(header, &vlan, sizeof(vlan));
7675 header += sizeof(vlan);
7677 if (mplsoudp_encap_conf.select_ipv4) {
7678 memcpy(header, &ipv4, sizeof(ipv4));
7679 header += sizeof(ipv4);
7681 memcpy(&ipv6.hdr.src_addr,
7682 &mplsoudp_encap_conf.ipv6_src,
7683 sizeof(mplsoudp_encap_conf.ipv6_src));
7684 memcpy(&ipv6.hdr.dst_addr,
7685 &mplsoudp_encap_conf.ipv6_dst,
7686 sizeof(mplsoudp_encap_conf.ipv6_dst));
7687 memcpy(header, &ipv6, sizeof(ipv6));
7688 header += sizeof(ipv6);
7690 memcpy(header, &udp, sizeof(udp));
7691 header += sizeof(udp);
7692 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
7693 RTE_DIM(mplsoudp_encap_conf.label));
7694 mpls.label_tc_s[2] |= 0x1;
7695 memcpy(header, &mpls, sizeof(mpls));
7696 header += sizeof(mpls);
7697 action_encap_data->conf.size = header -
7698 action_encap_data->data;
7699 action->conf = &action_encap_data->conf;
7703 /** Parse MPLSOUDP decap action. */
7705 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
7706 const char *str, unsigned int len,
7707 void *buf, unsigned int size)
7709 struct buffer *out = buf;
7710 struct rte_flow_action *action;
7711 struct action_raw_decap_data *action_decap_data;
7712 struct rte_flow_item_eth eth = { .type = 0, };
7713 struct rte_flow_item_vlan vlan = {.tci = 0};
7714 struct rte_flow_item_ipv4 ipv4 = {
7716 .next_proto_id = IPPROTO_UDP,
7719 struct rte_flow_item_ipv6 ipv6 = {
7721 .proto = IPPROTO_UDP,
7724 struct rte_flow_item_udp udp = {
7726 .dst_port = rte_cpu_to_be_16(6635),
7729 struct rte_flow_item_mpls mpls;
7733 ret = parse_vc(ctx, token, str, len, buf, size);
7736 /* Nothing else to do if there is no buffer. */
7739 if (!out->args.vc.actions_n)
7741 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7742 /* Point to selected object. */
7743 ctx->object = out->args.vc.data;
7744 ctx->objmask = NULL;
7745 /* Copy the headers to the buffer. */
7746 action_decap_data = ctx->object;
7747 *action_decap_data = (struct action_raw_decap_data) {
7748 .conf = (struct rte_flow_action_raw_decap){
7749 .data = action_decap_data->data,
7753 header = action_decap_data->data;
7754 if (mplsoudp_decap_conf.select_vlan)
7755 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7756 else if (mplsoudp_encap_conf.select_ipv4)
7757 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7759 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7760 memcpy(eth.dst.addr_bytes,
7761 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7762 memcpy(eth.src.addr_bytes,
7763 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7764 memcpy(header, ð, sizeof(eth));
7765 header += sizeof(eth);
7766 if (mplsoudp_encap_conf.select_vlan) {
7767 if (mplsoudp_encap_conf.select_ipv4)
7768 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7770 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7771 memcpy(header, &vlan, sizeof(vlan));
7772 header += sizeof(vlan);
7774 if (mplsoudp_encap_conf.select_ipv4) {
7775 memcpy(header, &ipv4, sizeof(ipv4));
7776 header += sizeof(ipv4);
7778 memcpy(header, &ipv6, sizeof(ipv6));
7779 header += sizeof(ipv6);
7781 memcpy(header, &udp, sizeof(udp));
7782 header += sizeof(udp);
7783 memset(&mpls, 0, sizeof(mpls));
7784 memcpy(header, &mpls, sizeof(mpls));
7785 header += sizeof(mpls);
7786 action_decap_data->conf.size = header -
7787 action_decap_data->data;
7788 action->conf = &action_decap_data->conf;
7793 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
7794 const char *str, unsigned int len, void *buf,
7797 struct action_raw_decap_data *action_raw_decap_data;
7798 struct rte_flow_action *action;
7799 const struct arg *arg;
7800 struct buffer *out = buf;
7804 RTE_SET_USED(token);
7807 arg = ARGS_ENTRY_ARB_BOUNDED
7808 (offsetof(struct action_raw_decap_data, idx),
7809 sizeof(((struct action_raw_decap_data *)0)->idx),
7810 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7811 if (push_args(ctx, arg))
7813 ret = parse_int(ctx, token, str, len, NULL, 0);
7820 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7821 action_raw_decap_data = ctx->object;
7822 idx = action_raw_decap_data->idx;
7823 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
7824 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
7825 action->conf = &action_raw_decap_data->conf;
7831 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
7832 const char *str, unsigned int len, void *buf,
7835 struct action_raw_encap_data *action_raw_encap_data;
7836 struct rte_flow_action *action;
7837 const struct arg *arg;
7838 struct buffer *out = buf;
7842 RTE_SET_USED(token);
7845 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
7847 arg = ARGS_ENTRY_ARB_BOUNDED
7848 (offsetof(struct action_raw_encap_data, idx),
7849 sizeof(((struct action_raw_encap_data *)0)->idx),
7850 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7851 if (push_args(ctx, arg))
7853 ret = parse_int(ctx, token, str, len, NULL, 0);
7860 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7861 action_raw_encap_data = ctx->object;
7862 idx = action_raw_encap_data->idx;
7863 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
7864 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
7865 action_raw_encap_data->conf.preserve = NULL;
7866 action->conf = &action_raw_encap_data->conf;
7871 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
7872 const char *str, unsigned int len, void *buf,
7875 struct buffer *out = buf;
7876 struct rte_flow_action *action;
7877 struct action_raw_encap_data *action_raw_encap_data = NULL;
7880 ret = parse_vc(ctx, token, str, len, buf, size);
7883 /* Nothing else to do if there is no buffer. */
7886 if (!out->args.vc.actions_n)
7888 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7889 /* Point to selected object. */
7890 ctx->object = out->args.vc.data;
7891 ctx->objmask = NULL;
7892 /* Copy the headers to the buffer. */
7893 action_raw_encap_data = ctx->object;
7894 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
7895 action_raw_encap_data->conf.preserve = NULL;
7896 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
7897 action->conf = &action_raw_encap_data->conf;
7902 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
7903 const char *str, unsigned int len, void *buf,
7906 struct buffer *out = buf;
7907 struct rte_flow_action *action;
7908 struct action_raw_decap_data *action_raw_decap_data = NULL;
7911 ret = parse_vc(ctx, token, str, len, buf, size);
7914 /* Nothing else to do if there is no buffer. */
7917 if (!out->args.vc.actions_n)
7919 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7920 /* Point to selected object. */
7921 ctx->object = out->args.vc.data;
7922 ctx->objmask = NULL;
7923 /* Copy the headers to the buffer. */
7924 action_raw_decap_data = ctx->object;
7925 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
7926 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
7927 action->conf = &action_raw_decap_data->conf;
7932 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
7933 const char *str, unsigned int len, void *buf,
7938 ret = parse_vc(ctx, token, str, len, buf, size);
7941 ret = rte_flow_dynf_metadata_register();
7948 parse_vc_action_sample(struct context *ctx, const struct token *token,
7949 const char *str, unsigned int len, void *buf,
7952 struct buffer *out = buf;
7953 struct rte_flow_action *action;
7954 struct action_sample_data *action_sample_data = NULL;
7955 static struct rte_flow_action end_action = {
7956 RTE_FLOW_ACTION_TYPE_END, 0
7960 ret = parse_vc(ctx, token, str, len, buf, size);
7963 /* Nothing else to do if there is no buffer. */
7966 if (!out->args.vc.actions_n)
7968 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7969 /* Point to selected object. */
7970 ctx->object = out->args.vc.data;
7971 ctx->objmask = NULL;
7972 /* Copy the headers to the buffer. */
7973 action_sample_data = ctx->object;
7974 action_sample_data->conf.actions = &end_action;
7975 action->conf = &action_sample_data->conf;
7980 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
7981 const char *str, unsigned int len, void *buf,
7984 struct action_sample_data *action_sample_data;
7985 struct rte_flow_action *action;
7986 const struct arg *arg;
7987 struct buffer *out = buf;
7991 RTE_SET_USED(token);
7994 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
7996 arg = ARGS_ENTRY_ARB_BOUNDED
7997 (offsetof(struct action_sample_data, idx),
7998 sizeof(((struct action_sample_data *)0)->idx),
7999 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
8000 if (push_args(ctx, arg))
8002 ret = parse_int(ctx, token, str, len, NULL, 0);
8009 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8010 action_sample_data = ctx->object;
8011 idx = action_sample_data->idx;
8012 action_sample_data->conf.actions = raw_sample_confs[idx].data;
8013 action->conf = &action_sample_data->conf;
8017 /** Parse operation for modify_field command. */
8019 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
8020 const char *str, unsigned int len, void *buf,
8023 struct rte_flow_action_modify_field *action_modify_field;
8029 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
8031 for (i = 0; modify_field_ops[i]; ++i)
8032 if (!strcmp_partial(modify_field_ops[i], str, len))
8034 if (!modify_field_ops[i])
8038 action_modify_field = ctx->object;
8039 action_modify_field->operation = (enum rte_flow_modify_op)i;
8043 /** Parse id for modify_field command. */
8045 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
8046 const char *str, unsigned int len, void *buf,
8049 struct rte_flow_action_modify_field *action_modify_field;
8055 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
8056 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
8058 for (i = 0; modify_field_ids[i]; ++i)
8059 if (!strcmp_partial(modify_field_ids[i], str, len))
8061 if (!modify_field_ids[i])
8065 action_modify_field = ctx->object;
8066 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
8067 action_modify_field->dst.field = (enum rte_flow_field_id)i;
8069 action_modify_field->src.field = (enum rte_flow_field_id)i;
8073 /** Parse the conntrack update, not a rte_flow_action. */
8075 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
8076 const char *str, unsigned int len, void *buf,
8079 struct buffer *out = buf;
8080 struct rte_flow_modify_conntrack *ct_modify = NULL;
8083 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
8084 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
8086 /* Token name must match. */
8087 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8089 /* Nothing else to do if there is no buffer. */
8092 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
8093 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
8094 ct_modify->new_ct.is_original_dir =
8095 conntrack_context.is_original_dir;
8096 ct_modify->direction = 1;
8100 old_dir = ct_modify->new_ct.is_original_dir;
8101 memcpy(&ct_modify->new_ct, &conntrack_context,
8102 sizeof(conntrack_context));
8103 ct_modify->new_ct.is_original_dir = old_dir;
8104 ct_modify->state = 1;
8109 /** Parse tokens for destroy command. */
8111 parse_destroy(struct context *ctx, const struct token *token,
8112 const char *str, unsigned int len,
8113 void *buf, unsigned int size)
8115 struct buffer *out = buf;
8117 /* Token name must match. */
8118 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8120 /* Nothing else to do if there is no buffer. */
8123 if (!out->command) {
8124 if (ctx->curr != DESTROY)
8126 if (sizeof(*out) > size)
8128 out->command = ctx->curr;
8131 ctx->objmask = NULL;
8132 out->args.destroy.rule =
8133 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8137 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
8138 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
8141 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
8142 ctx->objmask = NULL;
8146 /** Parse tokens for flush command. */
8148 parse_flush(struct context *ctx, const struct token *token,
8149 const char *str, unsigned int len,
8150 void *buf, unsigned int size)
8152 struct buffer *out = buf;
8154 /* Token name must match. */
8155 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8157 /* Nothing else to do if there is no buffer. */
8160 if (!out->command) {
8161 if (ctx->curr != FLUSH)
8163 if (sizeof(*out) > size)
8165 out->command = ctx->curr;
8168 ctx->objmask = NULL;
8173 /** Parse tokens for dump command. */
8175 parse_dump(struct context *ctx, const struct token *token,
8176 const char *str, unsigned int len,
8177 void *buf, unsigned int size)
8179 struct buffer *out = buf;
8181 /* Token name must match. */
8182 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8184 /* Nothing else to do if there is no buffer. */
8187 if (!out->command) {
8188 if (ctx->curr != DUMP)
8190 if (sizeof(*out) > size)
8192 out->command = ctx->curr;
8195 ctx->objmask = NULL;
8198 switch (ctx->curr) {
8201 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
8202 out->command = ctx->curr;
8205 ctx->objmask = NULL;
8212 /** Parse tokens for query command. */
8214 parse_query(struct context *ctx, const struct token *token,
8215 const char *str, unsigned int len,
8216 void *buf, unsigned int size)
8218 struct buffer *out = buf;
8220 /* Token name must match. */
8221 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8223 /* Nothing else to do if there is no buffer. */
8226 if (!out->command) {
8227 if (ctx->curr != QUERY)
8229 if (sizeof(*out) > size)
8231 out->command = ctx->curr;
8234 ctx->objmask = NULL;
8239 /** Parse action names. */
8241 parse_action(struct context *ctx, const struct token *token,
8242 const char *str, unsigned int len,
8243 void *buf, unsigned int size)
8245 struct buffer *out = buf;
8246 const struct arg *arg = pop_args(ctx);
8250 /* Argument is expected. */
8253 /* Parse action name. */
8254 for (i = 0; next_action[i]; ++i) {
8255 const struct parse_action_priv *priv;
8257 token = &token_list[next_action[i]];
8258 if (strcmp_partial(token->name, str, len))
8264 memcpy((uint8_t *)ctx->object + arg->offset,
8270 push_args(ctx, arg);
8274 /** Parse tokens for list command. */
8276 parse_list(struct context *ctx, const struct token *token,
8277 const char *str, unsigned int len,
8278 void *buf, unsigned int size)
8280 struct buffer *out = buf;
8282 /* Token name must match. */
8283 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8285 /* Nothing else to do if there is no buffer. */
8288 if (!out->command) {
8289 if (ctx->curr != LIST)
8291 if (sizeof(*out) > size)
8293 out->command = ctx->curr;
8296 ctx->objmask = NULL;
8297 out->args.list.group =
8298 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8302 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
8303 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
8306 ctx->object = out->args.list.group + out->args.list.group_n++;
8307 ctx->objmask = NULL;
8311 /** Parse tokens for list all aged flows command. */
8313 parse_aged(struct context *ctx, const struct token *token,
8314 const char *str, unsigned int len,
8315 void *buf, unsigned int size)
8317 struct buffer *out = buf;
8319 /* Token name must match. */
8320 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8322 /* Nothing else to do if there is no buffer. */
8325 if (!out->command) {
8326 if (ctx->curr != AGED)
8328 if (sizeof(*out) > size)
8330 out->command = ctx->curr;
8333 ctx->objmask = NULL;
8335 if (ctx->curr == AGED_DESTROY)
8336 out->args.aged.destroy = 1;
8340 /** Parse tokens for isolate command. */
8342 parse_isolate(struct context *ctx, const struct token *token,
8343 const char *str, unsigned int len,
8344 void *buf, unsigned int size)
8346 struct buffer *out = buf;
8348 /* Token name must match. */
8349 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8351 /* Nothing else to do if there is no buffer. */
8354 if (!out->command) {
8355 if (ctx->curr != ISOLATE)
8357 if (sizeof(*out) > size)
8359 out->command = ctx->curr;
8362 ctx->objmask = NULL;
8367 /** Parse tokens for info/configure command. */
8369 parse_configure(struct context *ctx, const struct token *token,
8370 const char *str, unsigned int len,
8371 void *buf, unsigned int size)
8373 struct buffer *out = buf;
8375 /* Token name must match. */
8376 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8378 /* Nothing else to do if there is no buffer. */
8381 if (!out->command) {
8382 if (ctx->curr != INFO && ctx->curr != CONFIGURE)
8384 if (sizeof(*out) > size)
8386 out->command = ctx->curr;
8389 ctx->objmask = NULL;
8394 /** Parse tokens for template create command. */
8396 parse_template(struct context *ctx, const struct token *token,
8397 const char *str, unsigned int len,
8398 void *buf, unsigned int size)
8400 struct buffer *out = buf;
8402 /* Token name must match. */
8403 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8405 /* Nothing else to do if there is no buffer. */
8408 if (!out->command) {
8409 if (ctx->curr != PATTERN_TEMPLATE &&
8410 ctx->curr != ACTIONS_TEMPLATE)
8412 if (sizeof(*out) > size)
8414 out->command = ctx->curr;
8417 ctx->objmask = NULL;
8418 out->args.vc.data = (uint8_t *)out + size;
8421 switch (ctx->curr) {
8422 case PATTERN_TEMPLATE_CREATE:
8423 out->args.vc.pattern =
8424 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8426 out->args.vc.pat_templ_id = UINT32_MAX;
8427 out->command = ctx->curr;
8430 ctx->objmask = NULL;
8432 case PATTERN_TEMPLATE_EGRESS:
8433 out->args.vc.attr.egress = 1;
8435 case PATTERN_TEMPLATE_INGRESS:
8436 out->args.vc.attr.ingress = 1;
8438 case PATTERN_TEMPLATE_TRANSFER:
8439 out->args.vc.attr.transfer = 1;
8441 case ACTIONS_TEMPLATE_CREATE:
8442 out->args.vc.act_templ_id = UINT32_MAX;
8443 out->command = ctx->curr;
8446 ctx->objmask = NULL;
8448 case ACTIONS_TEMPLATE_SPEC:
8449 out->args.vc.actions =
8450 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8452 ctx->object = out->args.vc.actions;
8453 ctx->objmask = NULL;
8455 case ACTIONS_TEMPLATE_MASK:
8456 out->args.vc.masks =
8457 (void *)RTE_ALIGN_CEIL((uintptr_t)
8458 (out->args.vc.actions +
8459 out->args.vc.actions_n),
8461 ctx->object = out->args.vc.masks;
8462 ctx->objmask = NULL;
8464 case ACTIONS_TEMPLATE_EGRESS:
8465 out->args.vc.attr.egress = 1;
8467 case ACTIONS_TEMPLATE_INGRESS:
8468 out->args.vc.attr.ingress = 1;
8470 case ACTIONS_TEMPLATE_TRANSFER:
8471 out->args.vc.attr.transfer = 1;
8478 /** Parse tokens for template destroy command. */
8480 parse_template_destroy(struct context *ctx, const struct token *token,
8481 const char *str, unsigned int len,
8482 void *buf, unsigned int size)
8484 struct buffer *out = buf;
8485 uint32_t *template_id;
8487 /* Token name must match. */
8488 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8490 /* Nothing else to do if there is no buffer. */
8493 if (!out->command ||
8494 out->command == PATTERN_TEMPLATE ||
8495 out->command == ACTIONS_TEMPLATE) {
8496 if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
8497 ctx->curr != ACTIONS_TEMPLATE_DESTROY)
8499 if (sizeof(*out) > size)
8501 out->command = ctx->curr;
8504 ctx->objmask = NULL;
8505 out->args.templ_destroy.template_id =
8506 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8510 template_id = out->args.templ_destroy.template_id
8511 + out->args.templ_destroy.template_id_n++;
8512 if ((uint8_t *)template_id > (uint8_t *)out + size)
8515 ctx->object = template_id;
8516 ctx->objmask = NULL;
8520 /** Parse tokens for table create command. */
8522 parse_table(struct context *ctx, const struct token *token,
8523 const char *str, unsigned int len,
8524 void *buf, unsigned int size)
8526 struct buffer *out = buf;
8527 uint32_t *template_id;
8529 /* Token name must match. */
8530 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8532 /* Nothing else to do if there is no buffer. */
8535 if (!out->command) {
8536 if (ctx->curr != TABLE)
8538 if (sizeof(*out) > size)
8540 out->command = ctx->curr;
8543 ctx->objmask = NULL;
8546 switch (ctx->curr) {
8548 out->command = ctx->curr;
8551 ctx->objmask = NULL;
8552 out->args.table.id = UINT32_MAX;
8554 case TABLE_PATTERN_TEMPLATE:
8555 out->args.table.pat_templ_id =
8556 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8558 template_id = out->args.table.pat_templ_id
8559 + out->args.table.pat_templ_id_n++;
8560 if ((uint8_t *)template_id > (uint8_t *)out + size)
8563 ctx->object = template_id;
8564 ctx->objmask = NULL;
8566 case TABLE_ACTIONS_TEMPLATE:
8567 out->args.table.act_templ_id =
8568 (void *)RTE_ALIGN_CEIL((uintptr_t)
8569 (out->args.table.pat_templ_id +
8570 out->args.table.pat_templ_id_n),
8572 template_id = out->args.table.act_templ_id
8573 + out->args.table.act_templ_id_n++;
8574 if ((uint8_t *)template_id > (uint8_t *)out + size)
8577 ctx->object = template_id;
8578 ctx->objmask = NULL;
8581 out->args.table.attr.flow_attr.ingress = 1;
8584 out->args.table.attr.flow_attr.egress = 1;
8586 case TABLE_TRANSFER:
8587 out->args.table.attr.flow_attr.transfer = 1;
8594 /** Parse tokens for table destroy command. */
8596 parse_table_destroy(struct context *ctx, const struct token *token,
8597 const char *str, unsigned int len,
8598 void *buf, unsigned int size)
8600 struct buffer *out = buf;
8603 /* Token name must match. */
8604 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8606 /* Nothing else to do if there is no buffer. */
8609 if (!out->command || out->command == TABLE) {
8610 if (ctx->curr != TABLE_DESTROY)
8612 if (sizeof(*out) > size)
8614 out->command = ctx->curr;
8617 ctx->objmask = NULL;
8618 out->args.table_destroy.table_id =
8619 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8623 table_id = out->args.table_destroy.table_id
8624 + out->args.table_destroy.table_id_n++;
8625 if ((uint8_t *)table_id > (uint8_t *)out + size)
8628 ctx->object = table_id;
8629 ctx->objmask = NULL;
8633 /** Parse tokens for queue create commands. */
8635 parse_qo(struct context *ctx, const struct token *token,
8636 const char *str, unsigned int len,
8637 void *buf, unsigned int size)
8639 struct buffer *out = buf;
8641 /* Token name must match. */
8642 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8644 /* Nothing else to do if there is no buffer. */
8647 if (!out->command) {
8648 if (ctx->curr != QUEUE)
8650 if (sizeof(*out) > size)
8652 out->command = ctx->curr;
8655 ctx->objmask = NULL;
8656 out->args.vc.data = (uint8_t *)out + size;
8659 switch (ctx->curr) {
8661 out->command = ctx->curr;
8664 ctx->objmask = NULL;
8666 case QUEUE_TEMPLATE_TABLE:
8667 case QUEUE_PATTERN_TEMPLATE:
8668 case QUEUE_ACTIONS_TEMPLATE:
8669 case QUEUE_CREATE_POSTPONE:
8672 out->args.vc.pattern =
8673 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8675 ctx->object = out->args.vc.pattern;
8676 ctx->objmask = NULL;
8679 out->args.vc.actions =
8680 (void *)RTE_ALIGN_CEIL((uintptr_t)
8681 (out->args.vc.pattern +
8682 out->args.vc.pattern_n),
8684 ctx->object = out->args.vc.actions;
8685 ctx->objmask = NULL;
8692 /** Parse tokens for queue destroy command. */
8694 parse_qo_destroy(struct context *ctx, const struct token *token,
8695 const char *str, unsigned int len,
8696 void *buf, unsigned int size)
8698 struct buffer *out = buf;
8701 /* Token name must match. */
8702 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8704 /* Nothing else to do if there is no buffer. */
8707 if (!out->command || out->command == QUEUE) {
8708 if (ctx->curr != QUEUE_DESTROY)
8710 if (sizeof(*out) > size)
8712 out->command = ctx->curr;
8715 ctx->objmask = NULL;
8716 out->args.destroy.rule =
8717 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8721 switch (ctx->curr) {
8722 case QUEUE_DESTROY_ID:
8723 flow_id = out->args.destroy.rule
8724 + out->args.destroy.rule_n++;
8725 if ((uint8_t *)flow_id > (uint8_t *)out + size)
8728 ctx->object = flow_id;
8729 ctx->objmask = NULL;
8731 case QUEUE_DESTROY_POSTPONE:
8739 parse_flex(struct context *ctx, const struct token *token,
8740 const char *str, unsigned int len,
8741 void *buf, unsigned int size)
8743 struct buffer *out = buf;
8745 /* Token name must match. */
8746 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8748 /* Nothing else to do if there is no buffer. */
8751 if (out->command == ZERO) {
8752 if (ctx->curr != FLEX)
8754 if (sizeof(*out) > size)
8756 out->command = ctx->curr;
8759 ctx->objmask = NULL;
8761 switch (ctx->curr) {
8764 case FLEX_ITEM_INIT:
8765 case FLEX_ITEM_CREATE:
8766 case FLEX_ITEM_DESTROY:
8767 out->command = ctx->curr;
8776 parse_tunnel(struct context *ctx, const struct token *token,
8777 const char *str, unsigned int len,
8778 void *buf, unsigned int size)
8780 struct buffer *out = buf;
8782 /* Token name must match. */
8783 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8785 /* Nothing else to do if there is no buffer. */
8788 if (!out->command) {
8789 if (ctx->curr != TUNNEL)
8791 if (sizeof(*out) > size)
8793 out->command = ctx->curr;
8796 ctx->objmask = NULL;
8798 switch (ctx->curr) {
8802 case TUNNEL_DESTROY:
8804 out->command = ctx->curr;
8806 case TUNNEL_CREATE_TYPE:
8807 case TUNNEL_DESTROY_ID:
8808 ctx->object = &out->args.vc.tunnel_ops;
8817 * Parse signed/unsigned integers 8 to 64-bit long.
8819 * Last argument (ctx->args) is retrieved to determine integer type and
8823 parse_int(struct context *ctx, const struct token *token,
8824 const char *str, unsigned int len,
8825 void *buf, unsigned int size)
8827 const struct arg *arg = pop_args(ctx);
8832 /* Argument is expected. */
8837 (uintmax_t)strtoimax(str, &end, 0) :
8838 strtoumax(str, &end, 0);
8839 if (errno || (size_t)(end - str) != len)
8842 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
8843 (intmax_t)u > (intmax_t)arg->max)) ||
8844 (!arg->sign && (u < arg->min || u > arg->max))))
8849 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
8850 !arg_entry_bf_fill(ctx->objmask, -1, arg))
8854 buf = (uint8_t *)ctx->object + arg->offset;
8856 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
8860 case sizeof(uint8_t):
8861 *(uint8_t *)buf = u;
8863 case sizeof(uint16_t):
8864 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
8866 case sizeof(uint8_t [3]):
8867 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8869 ((uint8_t *)buf)[0] = u;
8870 ((uint8_t *)buf)[1] = u >> 8;
8871 ((uint8_t *)buf)[2] = u >> 16;
8875 ((uint8_t *)buf)[0] = u >> 16;
8876 ((uint8_t *)buf)[1] = u >> 8;
8877 ((uint8_t *)buf)[2] = u;
8879 case sizeof(uint32_t):
8880 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
8882 case sizeof(uint64_t):
8883 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
8888 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
8890 buf = (uint8_t *)ctx->objmask + arg->offset;
8895 push_args(ctx, arg);
8902 * Three arguments (ctx->args) are retrieved from the stack to store data,
8903 * its actual length and address (in that order).
8906 parse_string(struct context *ctx, const struct token *token,
8907 const char *str, unsigned int len,
8908 void *buf, unsigned int size)
8910 const struct arg *arg_data = pop_args(ctx);
8911 const struct arg *arg_len = pop_args(ctx);
8912 const struct arg *arg_addr = pop_args(ctx);
8913 char tmp[16]; /* Ought to be enough. */
8916 /* Arguments are expected. */
8920 push_args(ctx, arg_data);
8924 push_args(ctx, arg_len);
8925 push_args(ctx, arg_data);
8928 size = arg_data->size;
8929 /* Bit-mask fill is not supported. */
8930 if (arg_data->mask || size < len)
8934 /* Let parse_int() fill length information first. */
8935 ret = snprintf(tmp, sizeof(tmp), "%u", len);
8938 push_args(ctx, arg_len);
8939 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
8944 buf = (uint8_t *)ctx->object + arg_data->offset;
8945 /* Output buffer is not necessarily NUL-terminated. */
8946 memcpy(buf, str, len);
8947 memset((uint8_t *)buf + len, 0x00, size - len);
8949 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
8950 /* Save address if requested. */
8951 if (arg_addr->size) {
8952 memcpy((uint8_t *)ctx->object + arg_addr->offset,
8954 (uint8_t *)ctx->object + arg_data->offset
8958 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
8960 (uint8_t *)ctx->objmask + arg_data->offset
8966 push_args(ctx, arg_addr);
8967 push_args(ctx, arg_len);
8968 push_args(ctx, arg_data);
8973 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
8975 const uint8_t *head = dst;
8978 /* Check input parameters */
8979 if ((src == NULL) ||
8987 /* Convert chars to bytes */
8989 char tmp[3], *end = tmp;
8990 uint32_t read_lim = left & 1 ? 1 : 2;
8992 snprintf(tmp, read_lim + 1, "%s", src);
8993 *dst = strtoul(tmp, &end, 16);
8996 *size = (uint32_t)(dst - head);
9004 *size = (uint32_t)(dst - head);
9009 parse_hex(struct context *ctx, const struct token *token,
9010 const char *str, unsigned int len,
9011 void *buf, unsigned int size)
9013 const struct arg *arg_data = pop_args(ctx);
9014 const struct arg *arg_len = pop_args(ctx);
9015 const struct arg *arg_addr = pop_args(ctx);
9016 char tmp[16]; /* Ought to be enough. */
9018 unsigned int hexlen = len;
9019 unsigned int length = 256;
9020 uint8_t hex_tmp[length];
9022 /* Arguments are expected. */
9026 push_args(ctx, arg_data);
9030 push_args(ctx, arg_len);
9031 push_args(ctx, arg_data);
9034 size = arg_data->size;
9035 /* Bit-mask fill is not supported. */
9041 /* translate bytes string to array. */
9042 if (str[0] == '0' && ((str[1] == 'x') ||
9047 if (hexlen > length)
9049 ret = parse_hex_string(str, hex_tmp, &hexlen);
9052 /* Check the converted binary fits into data buffer. */
9055 /* Let parse_int() fill length information first. */
9056 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
9059 /* Save length if requested. */
9060 if (arg_len->size) {
9061 push_args(ctx, arg_len);
9062 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
9068 buf = (uint8_t *)ctx->object + arg_data->offset;
9069 /* Output buffer is not necessarily NUL-terminated. */
9070 memcpy(buf, hex_tmp, hexlen);
9071 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
9073 memset((uint8_t *)ctx->objmask + arg_data->offset,
9075 /* Save address if requested. */
9076 if (arg_addr->size) {
9077 memcpy((uint8_t *)ctx->object + arg_addr->offset,
9079 (uint8_t *)ctx->object + arg_data->offset
9083 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
9085 (uint8_t *)ctx->objmask + arg_data->offset
9091 push_args(ctx, arg_addr);
9092 push_args(ctx, arg_len);
9093 push_args(ctx, arg_data);
9099 * Parse a zero-ended string.
9102 parse_string0(struct context *ctx, const struct token *token __rte_unused,
9103 const char *str, unsigned int len,
9104 void *buf, unsigned int size)
9106 const struct arg *arg_data = pop_args(ctx);
9108 /* Arguments are expected. */
9111 size = arg_data->size;
9112 /* Bit-mask fill is not supported. */
9113 if (arg_data->mask || size < len + 1)
9117 buf = (uint8_t *)ctx->object + arg_data->offset;
9118 strncpy(buf, str, len);
9120 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
9123 push_args(ctx, arg_data);
9128 * Parse a MAC address.
9130 * Last argument (ctx->args) is retrieved to determine storage size and
9134 parse_mac_addr(struct context *ctx, const struct token *token,
9135 const char *str, unsigned int len,
9136 void *buf, unsigned int size)
9138 const struct arg *arg = pop_args(ctx);
9139 struct rte_ether_addr tmp;
9143 /* Argument is expected. */
9147 /* Bit-mask fill is not supported. */
9148 if (arg->mask || size != sizeof(tmp))
9150 /* Only network endian is supported. */
9153 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
9154 if (ret < 0 || (unsigned int)ret != len)
9158 buf = (uint8_t *)ctx->object + arg->offset;
9159 memcpy(buf, &tmp, size);
9161 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9164 push_args(ctx, arg);
9169 * Parse an IPv4 address.
9171 * Last argument (ctx->args) is retrieved to determine storage size and
9175 parse_ipv4_addr(struct context *ctx, const struct token *token,
9176 const char *str, unsigned int len,
9177 void *buf, unsigned int size)
9179 const struct arg *arg = pop_args(ctx);
9184 /* Argument is expected. */
9188 /* Bit-mask fill is not supported. */
9189 if (arg->mask || size != sizeof(tmp))
9191 /* Only network endian is supported. */
9194 memcpy(str2, str, len);
9196 ret = inet_pton(AF_INET, str2, &tmp);
9198 /* Attempt integer parsing. */
9199 push_args(ctx, arg);
9200 return parse_int(ctx, token, str, len, buf, size);
9204 buf = (uint8_t *)ctx->object + arg->offset;
9205 memcpy(buf, &tmp, size);
9207 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9210 push_args(ctx, arg);
9215 * Parse an IPv6 address.
9217 * Last argument (ctx->args) is retrieved to determine storage size and
9221 parse_ipv6_addr(struct context *ctx, const struct token *token,
9222 const char *str, unsigned int len,
9223 void *buf, unsigned int size)
9225 const struct arg *arg = pop_args(ctx);
9227 struct in6_addr tmp;
9231 /* Argument is expected. */
9235 /* Bit-mask fill is not supported. */
9236 if (arg->mask || size != sizeof(tmp))
9238 /* Only network endian is supported. */
9241 memcpy(str2, str, len);
9243 ret = inet_pton(AF_INET6, str2, &tmp);
9248 buf = (uint8_t *)ctx->object + arg->offset;
9249 memcpy(buf, &tmp, size);
9251 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
9254 push_args(ctx, arg);
9258 /** Boolean values (even indices stand for false). */
9259 static const char *const boolean_name[] = {
9269 * Parse a boolean value.
9271 * Last argument (ctx->args) is retrieved to determine storage size and
9275 parse_boolean(struct context *ctx, const struct token *token,
9276 const char *str, unsigned int len,
9277 void *buf, unsigned int size)
9279 const struct arg *arg = pop_args(ctx);
9283 /* Argument is expected. */
9286 for (i = 0; boolean_name[i]; ++i)
9287 if (!strcmp_partial(boolean_name[i], str, len))
9289 /* Process token as integer. */
9290 if (boolean_name[i])
9291 str = i & 1 ? "1" : "0";
9292 push_args(ctx, arg);
9293 ret = parse_int(ctx, token, str, strlen(str), buf, size);
9294 return ret > 0 ? (int)len : ret;
9297 /** Parse port and update context. */
9299 parse_port(struct context *ctx, const struct token *token,
9300 const char *str, unsigned int len,
9301 void *buf, unsigned int size)
9303 struct buffer *out = &(struct buffer){ .port = 0 };
9311 ctx->objmask = NULL;
9312 size = sizeof(*out);
9314 ret = parse_int(ctx, token, str, len, out, size);
9316 ctx->port = out->port;
9323 parse_ia_id2ptr(struct context *ctx, const struct token *token,
9324 const char *str, unsigned int len,
9325 void *buf, unsigned int size)
9327 struct rte_flow_action *action = ctx->object;
9335 ctx->objmask = NULL;
9336 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
9337 ctx->object = action;
9338 if (ret != (int)len)
9340 /* set indirect action */
9342 action->conf = port_action_handle_get_by_id(ctx->port, id);
9343 ret = (action->conf) ? ret : -1;
9348 /** Parse set command, initialize output buffer for subsequent tokens. */
9350 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
9351 const char *str, unsigned int len,
9352 void *buf, unsigned int size)
9354 struct buffer *out = buf;
9356 /* Token name must match. */
9357 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9359 /* Nothing else to do if there is no buffer. */
9362 /* Make sure buffer is large enough. */
9363 if (size < sizeof(*out))
9366 ctx->objmask = NULL;
9370 out->command = ctx->curr;
9371 /* For encap/decap we need is pattern */
9372 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9377 /** Parse set command, initialize output buffer for subsequent tokens. */
9379 parse_set_sample_action(struct context *ctx, const struct token *token,
9380 const char *str, unsigned int len,
9381 void *buf, unsigned int size)
9383 struct buffer *out = buf;
9385 /* Token name must match. */
9386 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9388 /* Nothing else to do if there is no buffer. */
9391 /* Make sure buffer is large enough. */
9392 if (size < sizeof(*out))
9395 ctx->objmask = NULL;
9399 out->command = ctx->curr;
9400 /* For sampler we need is actions */
9401 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9407 * Parse set raw_encap/raw_decap command,
9408 * initialize output buffer for subsequent tokens.
9411 parse_set_init(struct context *ctx, const struct token *token,
9412 const char *str, unsigned int len,
9413 void *buf, unsigned int size)
9415 struct buffer *out = buf;
9417 /* Token name must match. */
9418 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9420 /* Nothing else to do if there is no buffer. */
9423 /* Make sure buffer is large enough. */
9424 if (size < sizeof(*out))
9426 /* Initialize buffer. */
9427 memset(out, 0x00, sizeof(*out));
9428 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
9431 ctx->objmask = NULL;
9432 if (!out->command) {
9433 if (ctx->curr != SET)
9435 if (sizeof(*out) > size)
9437 out->command = ctx->curr;
9438 out->args.vc.data = (uint8_t *)out + size;
9439 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9446 * Replace testpmd handles in a flex flow item with real values.
9449 parse_flex_handle(struct context *ctx, const struct token *token,
9450 const char *str, unsigned int len,
9451 void *buf, unsigned int size)
9453 struct rte_flow_item_flex *spec, *mask;
9454 const struct rte_flow_item_flex *src_spec, *src_mask;
9455 const struct arg *arg = pop_args(ctx);
9461 printf("Bad environment\n");
9464 offset = arg->offset;
9465 push_args(ctx, arg);
9466 ret = parse_int(ctx, token, str, len, buf, size);
9467 if (ret <= 0 || !ctx->object)
9469 if (ctx->port >= RTE_MAX_ETHPORTS) {
9470 printf("Bad port\n");
9473 if (offset == offsetof(struct rte_flow_item_flex, handle)) {
9474 const struct flex_item *fp;
9475 struct rte_flow_item_flex *item_flex = ctx->object;
9476 handle = (uint16_t)(uintptr_t)item_flex->handle;
9477 if (handle >= FLEX_MAX_PARSERS_NUM) {
9478 printf("Bad flex item handle\n");
9481 fp = flex_items[ctx->port][handle];
9483 printf("Bad flex item handle\n");
9486 item_flex->handle = fp->flex_handle;
9487 } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
9488 handle = (uint16_t)(uintptr_t)
9489 ((struct rte_flow_item_flex *)ctx->object)->pattern;
9490 if (handle >= FLEX_MAX_PATTERNS_NUM) {
9491 printf("Bad pattern handle\n");
9494 src_spec = &flex_patterns[handle].spec;
9495 src_mask = &flex_patterns[handle].mask;
9497 mask = spec + 2; /* spec, last, mask */
9498 /* fill flow rule spec and mask parameters */
9499 spec->length = src_spec->length;
9500 spec->pattern = src_spec->pattern;
9501 mask->length = src_mask->length;
9502 mask->pattern = src_mask->pattern;
9504 printf("Bad arguments - unknown flex item offset\n");
9510 /** No completion. */
9512 comp_none(struct context *ctx, const struct token *token,
9513 unsigned int ent, char *buf, unsigned int size)
9523 /** Complete boolean values. */
9525 comp_boolean(struct context *ctx, const struct token *token,
9526 unsigned int ent, char *buf, unsigned int size)
9532 for (i = 0; boolean_name[i]; ++i)
9533 if (buf && i == ent)
9534 return strlcpy(buf, boolean_name[i], size);
9540 /** Complete action names. */
9542 comp_action(struct context *ctx, const struct token *token,
9543 unsigned int ent, char *buf, unsigned int size)
9549 for (i = 0; next_action[i]; ++i)
9550 if (buf && i == ent)
9551 return strlcpy(buf, token_list[next_action[i]].name,
9558 /** Complete available ports. */
9560 comp_port(struct context *ctx, const struct token *token,
9561 unsigned int ent, char *buf, unsigned int size)
9568 RTE_ETH_FOREACH_DEV(p) {
9569 if (buf && i == ent)
9570 return snprintf(buf, size, "%u", p);
9578 /** Complete available rule IDs. */
9580 comp_rule_id(struct context *ctx, const struct token *token,
9581 unsigned int ent, char *buf, unsigned int size)
9584 struct rte_port *port;
9585 struct port_flow *pf;
9588 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9589 ctx->port == (portid_t)RTE_PORT_ALL)
9591 port = &ports[ctx->port];
9592 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
9593 if (buf && i == ent)
9594 return snprintf(buf, size, "%u", pf->id);
9602 /** Complete type field for RSS action. */
9604 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
9605 unsigned int ent, char *buf, unsigned int size)
9611 for (i = 0; rss_type_table[i].str; ++i)
9616 return strlcpy(buf, rss_type_table[ent].str, size);
9618 return snprintf(buf, size, "end");
9622 /** Complete queue field for RSS action. */
9624 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
9625 unsigned int ent, char *buf, unsigned int size)
9632 return snprintf(buf, size, "%u", ent);
9634 return snprintf(buf, size, "end");
9638 /** Complete index number for set raw_encap/raw_decap commands. */
9640 comp_set_raw_index(struct context *ctx, const struct token *token,
9641 unsigned int ent, char *buf, unsigned int size)
9647 RTE_SET_USED(token);
9648 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
9649 if (buf && idx == ent)
9650 return snprintf(buf, size, "%u", idx);
9656 /** Complete index number for set raw_encap/raw_decap commands. */
9658 comp_set_sample_index(struct context *ctx, const struct token *token,
9659 unsigned int ent, char *buf, unsigned int size)
9665 RTE_SET_USED(token);
9666 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
9667 if (buf && idx == ent)
9668 return snprintf(buf, size, "%u", idx);
9674 /** Complete operation for modify_field command. */
9676 comp_set_modify_field_op(struct context *ctx, const struct token *token,
9677 unsigned int ent, char *buf, unsigned int size)
9680 RTE_SET_USED(token);
9682 return RTE_DIM(modify_field_ops);
9683 if (ent < RTE_DIM(modify_field_ops) - 1)
9684 return strlcpy(buf, modify_field_ops[ent], size);
9688 /** Complete field id for modify_field command. */
9690 comp_set_modify_field_id(struct context *ctx, const struct token *token,
9691 unsigned int ent, char *buf, unsigned int size)
9695 RTE_SET_USED(token);
9697 return RTE_DIM(modify_field_ids);
9698 if (ent >= RTE_DIM(modify_field_ids) - 1)
9700 name = modify_field_ids[ent];
9701 if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
9702 (strcmp(name, "pointer") && strcmp(name, "value")))
9703 return strlcpy(buf, name, size);
9707 /** Complete available pattern template IDs. */
9709 comp_pattern_template_id(struct context *ctx, const struct token *token,
9710 unsigned int ent, char *buf, unsigned int size)
9713 struct rte_port *port;
9714 struct port_template *pt;
9717 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9718 ctx->port == (portid_t)RTE_PORT_ALL)
9720 port = &ports[ctx->port];
9721 for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
9722 if (buf && i == ent)
9723 return snprintf(buf, size, "%u", pt->id);
9731 /** Complete available actions template IDs. */
9733 comp_actions_template_id(struct context *ctx, const struct token *token,
9734 unsigned int ent, char *buf, unsigned int size)
9737 struct rte_port *port;
9738 struct port_template *pt;
9741 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9742 ctx->port == (portid_t)RTE_PORT_ALL)
9744 port = &ports[ctx->port];
9745 for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
9746 if (buf && i == ent)
9747 return snprintf(buf, size, "%u", pt->id);
9755 /** Complete available table IDs. */
9757 comp_table_id(struct context *ctx, const struct token *token,
9758 unsigned int ent, char *buf, unsigned int size)
9761 struct rte_port *port;
9762 struct port_table *pt;
9765 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9766 ctx->port == (portid_t)RTE_PORT_ALL)
9768 port = &ports[ctx->port];
9769 for (pt = port->table_list; pt != NULL; pt = pt->next) {
9770 if (buf && i == ent)
9771 return snprintf(buf, size, "%u", pt->id);
9779 /** Complete available queue IDs. */
9781 comp_queue_id(struct context *ctx, const struct token *token,
9782 unsigned int ent, char *buf, unsigned int size)
9785 struct rte_port *port;
9788 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
9789 ctx->port == (portid_t)RTE_PORT_ALL)
9791 port = &ports[ctx->port];
9792 for (i = 0; i < port->queue_nb; i++) {
9793 if (buf && i == ent)
9794 return snprintf(buf, size, "%u", i);
9801 /** Internal context. */
9802 static struct context cmd_flow_context;
9804 /** Global parser instance (cmdline API). */
9805 cmdline_parse_inst_t cmd_flow;
9806 cmdline_parse_inst_t cmd_set_raw;
9808 /** Initialize context. */
9810 cmd_flow_context_init(struct context *ctx)
9812 /* A full memset() is not necessary. */
9822 ctx->objmask = NULL;
9825 /** Parse a token (cmdline API). */
9827 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
9830 struct context *ctx = &cmd_flow_context;
9831 const struct token *token;
9832 const enum index *list;
9837 token = &token_list[ctx->curr];
9838 /* Check argument length. */
9841 for (len = 0; src[len]; ++len)
9842 if (src[len] == '#' || isspace(src[len]))
9846 /* Last argument and EOL detection. */
9847 for (i = len; src[i]; ++i)
9848 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
9850 else if (!isspace(src[i])) {
9855 if (src[i] == '\r' || src[i] == '\n') {
9859 /* Initialize context if necessary. */
9860 if (!ctx->next_num) {
9863 ctx->next[ctx->next_num++] = token->next[0];
9865 /* Process argument through candidates. */
9866 ctx->prev = ctx->curr;
9867 list = ctx->next[ctx->next_num - 1];
9868 for (i = 0; list[i]; ++i) {
9869 const struct token *next = &token_list[list[i]];
9872 ctx->curr = list[i];
9874 tmp = next->call(ctx, next, src, len, result, size);
9876 tmp = parse_default(ctx, next, src, len, result, size);
9877 if (tmp == -1 || tmp != len)
9885 /* Push subsequent tokens if any. */
9887 for (i = 0; token->next[i]; ++i) {
9888 if (ctx->next_num == RTE_DIM(ctx->next))
9890 ctx->next[ctx->next_num++] = token->next[i];
9892 /* Push arguments if any. */
9894 for (i = 0; token->args[i]; ++i) {
9895 if (ctx->args_num == RTE_DIM(ctx->args))
9897 ctx->args[ctx->args_num++] = token->args[i];
9903 flow_parse(const char *src, void *result, unsigned int size,
9904 struct rte_flow_attr **attr,
9905 struct rte_flow_item **pattern, struct rte_flow_action **actions)
9908 struct context saved_flow_ctx = cmd_flow_context;
9910 cmd_flow_context_init(&cmd_flow_context);
9912 ret = cmd_flow_parse(NULL, src, result, size);
9915 while (isspace(*src))
9918 } while (ret > 0 && strlen(src));
9919 cmd_flow_context = saved_flow_ctx;
9920 *attr = &((struct buffer *)result)->args.vc.attr;
9921 *pattern = ((struct buffer *)result)->args.vc.pattern;
9922 *actions = ((struct buffer *)result)->args.vc.actions;
9923 return (ret >= 0 && !strlen(src)) ? 0 : -1;
9926 /** Return number of completion entries (cmdline API). */
9928 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
9930 struct context *ctx = &cmd_flow_context;
9931 const struct token *token = &token_list[ctx->curr];
9932 const enum index *list;
9936 /* Count number of tokens in current list. */
9938 list = ctx->next[ctx->next_num - 1];
9940 list = token->next[0];
9941 for (i = 0; list[i]; ++i)
9946 * If there is a single token, use its completion callback, otherwise
9947 * return the number of entries.
9949 token = &token_list[list[0]];
9950 if (i == 1 && token->comp) {
9951 /* Save index for cmd_flow_get_help(). */
9952 ctx->prev = list[0];
9953 return token->comp(ctx, token, 0, NULL, 0);
9958 /** Return a completion entry (cmdline API). */
9960 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
9961 char *dst, unsigned int size)
9963 struct context *ctx = &cmd_flow_context;
9964 const struct token *token = &token_list[ctx->curr];
9965 const enum index *list;
9969 /* Count number of tokens in current list. */
9971 list = ctx->next[ctx->next_num - 1];
9973 list = token->next[0];
9974 for (i = 0; list[i]; ++i)
9978 /* If there is a single token, use its completion callback. */
9979 token = &token_list[list[0]];
9980 if (i == 1 && token->comp) {
9981 /* Save index for cmd_flow_get_help(). */
9982 ctx->prev = list[0];
9983 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
9985 /* Otherwise make sure the index is valid and use defaults. */
9988 token = &token_list[list[index]];
9989 strlcpy(dst, token->name, size);
9990 /* Save index for cmd_flow_get_help(). */
9991 ctx->prev = list[index];
9995 /** Populate help strings for current token (cmdline API). */
9997 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
9999 struct context *ctx = &cmd_flow_context;
10000 const struct token *token = &token_list[ctx->prev];
10005 /* Set token type and update global help with details. */
10006 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
10008 cmd_flow.help_str = token->help;
10010 cmd_flow.help_str = token->name;
10014 /** Token definition template (cmdline API). */
10015 static struct cmdline_token_hdr cmd_flow_token_hdr = {
10016 .ops = &(struct cmdline_token_ops){
10017 .parse = cmd_flow_parse,
10018 .complete_get_nb = cmd_flow_complete_get_nb,
10019 .complete_get_elt = cmd_flow_complete_get_elt,
10020 .get_help = cmd_flow_get_help,
10025 /** Populate the next dynamic token. */
10027 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
10028 cmdline_parse_token_hdr_t **hdr_inst)
10030 struct context *ctx = &cmd_flow_context;
10032 /* Always reinitialize context before requesting the first token. */
10033 if (!(hdr_inst - cmd_flow.tokens))
10034 cmd_flow_context_init(ctx);
10035 /* Return NULL when no more tokens are expected. */
10036 if (!ctx->next_num && ctx->curr) {
10040 /* Determine if command should end here. */
10041 if (ctx->eol && ctx->last && ctx->next_num) {
10042 const enum index *list = ctx->next[ctx->next_num - 1];
10045 for (i = 0; list[i]; ++i) {
10046 if (list[i] != END)
10052 *hdr = &cmd_flow_token_hdr;
10055 /** Dispatch parsed buffer to function calls. */
10057 cmd_flow_parsed(const struct buffer *in)
10059 switch (in->command) {
10061 port_flow_get_info(in->port);
10064 port_flow_configure(in->port,
10065 &in->args.configure.port_attr,
10066 in->args.configure.nb_queue,
10067 &in->args.configure.queue_attr);
10069 case PATTERN_TEMPLATE_CREATE:
10070 port_flow_pattern_template_create(in->port,
10071 in->args.vc.pat_templ_id,
10072 &((const struct rte_flow_pattern_template_attr) {
10073 .relaxed_matching = in->args.vc.attr.reserved,
10074 .ingress = in->args.vc.attr.ingress,
10075 .egress = in->args.vc.attr.egress,
10076 .transfer = in->args.vc.attr.transfer,
10078 in->args.vc.pattern);
10080 case PATTERN_TEMPLATE_DESTROY:
10081 port_flow_pattern_template_destroy(in->port,
10082 in->args.templ_destroy.template_id_n,
10083 in->args.templ_destroy.template_id);
10085 case ACTIONS_TEMPLATE_CREATE:
10086 port_flow_actions_template_create(in->port,
10087 in->args.vc.act_templ_id,
10088 &((const struct rte_flow_actions_template_attr) {
10089 .ingress = in->args.vc.attr.ingress,
10090 .egress = in->args.vc.attr.egress,
10091 .transfer = in->args.vc.attr.transfer,
10093 in->args.vc.actions,
10094 in->args.vc.masks);
10096 case ACTIONS_TEMPLATE_DESTROY:
10097 port_flow_actions_template_destroy(in->port,
10098 in->args.templ_destroy.template_id_n,
10099 in->args.templ_destroy.template_id);
10102 port_flow_template_table_create(in->port, in->args.table.id,
10103 &in->args.table.attr, in->args.table.pat_templ_id_n,
10104 in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
10105 in->args.table.act_templ_id);
10107 case TABLE_DESTROY:
10108 port_flow_template_table_destroy(in->port,
10109 in->args.table_destroy.table_id_n,
10110 in->args.table_destroy.table_id);
10113 port_queue_flow_create(in->port, in->queue, in->postpone,
10114 in->args.vc.table_id, in->args.vc.pat_templ_id,
10115 in->args.vc.act_templ_id, in->args.vc.pattern,
10116 in->args.vc.actions);
10118 case QUEUE_DESTROY:
10119 port_queue_flow_destroy(in->port, in->queue, in->postpone,
10120 in->args.destroy.rule_n,
10121 in->args.destroy.rule);
10123 case INDIRECT_ACTION_CREATE:
10124 port_action_handle_create(
10125 in->port, in->args.vc.attr.group,
10126 &((const struct rte_flow_indir_action_conf) {
10127 .ingress = in->args.vc.attr.ingress,
10128 .egress = in->args.vc.attr.egress,
10129 .transfer = in->args.vc.attr.transfer,
10131 in->args.vc.actions);
10133 case INDIRECT_ACTION_DESTROY:
10134 port_action_handle_destroy(in->port,
10135 in->args.ia_destroy.action_id_n,
10136 in->args.ia_destroy.action_id);
10138 case INDIRECT_ACTION_UPDATE:
10139 port_action_handle_update(in->port, in->args.vc.attr.group,
10140 in->args.vc.actions);
10142 case INDIRECT_ACTION_QUERY:
10143 port_action_handle_query(in->port, in->args.ia.action_id);
10146 port_flow_validate(in->port, &in->args.vc.attr,
10147 in->args.vc.pattern, in->args.vc.actions,
10148 &in->args.vc.tunnel_ops);
10151 port_flow_create(in->port, &in->args.vc.attr,
10152 in->args.vc.pattern, in->args.vc.actions,
10153 &in->args.vc.tunnel_ops);
10156 port_flow_destroy(in->port, in->args.destroy.rule_n,
10157 in->args.destroy.rule);
10160 port_flow_flush(in->port);
10164 port_flow_dump(in->port, in->args.dump.mode,
10165 in->args.dump.rule, in->args.dump.file);
10168 port_flow_query(in->port, in->args.query.rule,
10169 &in->args.query.action);
10172 port_flow_list(in->port, in->args.list.group_n,
10173 in->args.list.group);
10176 port_flow_isolate(in->port, in->args.isolate.set);
10179 port_flow_aged(in->port, in->args.aged.destroy);
10181 case TUNNEL_CREATE:
10182 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
10184 case TUNNEL_DESTROY:
10185 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
10188 port_flow_tunnel_list(in->port);
10191 port_meter_policy_add(in->port, in->args.policy.policy_id,
10192 in->args.vc.actions);
10194 case FLEX_ITEM_CREATE:
10195 flex_item_create(in->port, in->args.flex.token,
10196 in->args.flex.filename);
10198 case FLEX_ITEM_DESTROY:
10199 flex_item_destroy(in->port, in->args.flex.token);
10206 /** Token generator and output processing callback (cmdline API). */
10208 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
10211 cmd_flow_tok(arg0, arg2);
10213 cmd_flow_parsed(arg0);
10216 /** Global parser instance (cmdline API). */
10217 cmdline_parse_inst_t cmd_flow = {
10219 .data = NULL, /**< Unused. */
10220 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
10223 }, /**< Tokens are returned by cmd_flow_tok(). */
10226 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
10229 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
10231 struct rte_ipv4_hdr *ipv4;
10232 struct rte_ether_hdr *eth;
10233 struct rte_ipv6_hdr *ipv6;
10234 struct rte_vxlan_hdr *vxlan;
10235 struct rte_vxlan_gpe_hdr *gpe;
10236 struct rte_flow_item_nvgre *nvgre;
10237 uint32_t ipv6_vtc_flow;
10239 switch (item->type) {
10240 case RTE_FLOW_ITEM_TYPE_ETH:
10241 eth = (struct rte_ether_hdr *)buf;
10243 eth->ether_type = rte_cpu_to_be_16(next_proto);
10245 case RTE_FLOW_ITEM_TYPE_IPV4:
10246 ipv4 = (struct rte_ipv4_hdr *)buf;
10247 if (!ipv4->version_ihl)
10248 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
10249 if (next_proto && ipv4->next_proto_id == 0)
10250 ipv4->next_proto_id = (uint8_t)next_proto;
10252 case RTE_FLOW_ITEM_TYPE_IPV6:
10253 ipv6 = (struct rte_ipv6_hdr *)buf;
10254 if (next_proto && ipv6->proto == 0)
10255 ipv6->proto = (uint8_t)next_proto;
10256 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
10257 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
10258 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
10259 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
10261 case RTE_FLOW_ITEM_TYPE_VXLAN:
10262 vxlan = (struct rte_vxlan_hdr *)buf;
10263 vxlan->vx_flags = 0x08;
10265 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10266 gpe = (struct rte_vxlan_gpe_hdr *)buf;
10267 gpe->vx_flags = 0x0C;
10269 case RTE_FLOW_ITEM_TYPE_NVGRE:
10270 nvgre = (struct rte_flow_item_nvgre *)buf;
10271 nvgre->protocol = rte_cpu_to_be_16(0x6558);
10272 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
10279 /** Helper of get item's default mask. */
10280 static const void *
10281 flow_item_default_mask(const struct rte_flow_item *item)
10283 const void *mask = NULL;
10284 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
10286 switch (item->type) {
10287 case RTE_FLOW_ITEM_TYPE_ANY:
10288 mask = &rte_flow_item_any_mask;
10290 case RTE_FLOW_ITEM_TYPE_VF:
10291 mask = &rte_flow_item_vf_mask;
10293 case RTE_FLOW_ITEM_TYPE_PORT_ID:
10294 mask = &rte_flow_item_port_id_mask;
10296 case RTE_FLOW_ITEM_TYPE_RAW:
10297 mask = &rte_flow_item_raw_mask;
10299 case RTE_FLOW_ITEM_TYPE_ETH:
10300 mask = &rte_flow_item_eth_mask;
10302 case RTE_FLOW_ITEM_TYPE_VLAN:
10303 mask = &rte_flow_item_vlan_mask;
10305 case RTE_FLOW_ITEM_TYPE_IPV4:
10306 mask = &rte_flow_item_ipv4_mask;
10308 case RTE_FLOW_ITEM_TYPE_IPV6:
10309 mask = &rte_flow_item_ipv6_mask;
10311 case RTE_FLOW_ITEM_TYPE_ICMP:
10312 mask = &rte_flow_item_icmp_mask;
10314 case RTE_FLOW_ITEM_TYPE_UDP:
10315 mask = &rte_flow_item_udp_mask;
10317 case RTE_FLOW_ITEM_TYPE_TCP:
10318 mask = &rte_flow_item_tcp_mask;
10320 case RTE_FLOW_ITEM_TYPE_SCTP:
10321 mask = &rte_flow_item_sctp_mask;
10323 case RTE_FLOW_ITEM_TYPE_VXLAN:
10324 mask = &rte_flow_item_vxlan_mask;
10326 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10327 mask = &rte_flow_item_vxlan_gpe_mask;
10329 case RTE_FLOW_ITEM_TYPE_E_TAG:
10330 mask = &rte_flow_item_e_tag_mask;
10332 case RTE_FLOW_ITEM_TYPE_NVGRE:
10333 mask = &rte_flow_item_nvgre_mask;
10335 case RTE_FLOW_ITEM_TYPE_MPLS:
10336 mask = &rte_flow_item_mpls_mask;
10338 case RTE_FLOW_ITEM_TYPE_GRE:
10339 mask = &rte_flow_item_gre_mask;
10341 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
10342 mask = &gre_key_default_mask;
10344 case RTE_FLOW_ITEM_TYPE_META:
10345 mask = &rte_flow_item_meta_mask;
10347 case RTE_FLOW_ITEM_TYPE_FUZZY:
10348 mask = &rte_flow_item_fuzzy_mask;
10350 case RTE_FLOW_ITEM_TYPE_GTP:
10351 mask = &rte_flow_item_gtp_mask;
10353 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
10354 mask = &rte_flow_item_gtp_psc_mask;
10356 case RTE_FLOW_ITEM_TYPE_GENEVE:
10357 mask = &rte_flow_item_geneve_mask;
10359 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
10360 mask = &rte_flow_item_geneve_opt_mask;
10362 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
10363 mask = &rte_flow_item_pppoe_proto_id_mask;
10365 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
10366 mask = &rte_flow_item_l2tpv3oip_mask;
10368 case RTE_FLOW_ITEM_TYPE_ESP:
10369 mask = &rte_flow_item_esp_mask;
10371 case RTE_FLOW_ITEM_TYPE_AH:
10372 mask = &rte_flow_item_ah_mask;
10374 case RTE_FLOW_ITEM_TYPE_PFCP:
10375 mask = &rte_flow_item_pfcp_mask;
10377 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
10378 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
10379 mask = &rte_flow_item_ethdev_mask;
10381 case RTE_FLOW_ITEM_TYPE_L2TPV2:
10382 mask = &rte_flow_item_l2tpv2_mask;
10384 case RTE_FLOW_ITEM_TYPE_PPP:
10385 mask = &rte_flow_item_ppp_mask;
10393 /** Dispatch parsed buffer to function calls. */
10395 cmd_set_raw_parsed_sample(const struct buffer *in)
10397 uint32_t n = in->args.vc.actions_n;
10399 struct rte_flow_action *action = NULL;
10400 struct rte_flow_action *data = NULL;
10401 const struct rte_flow_action_rss *rss = NULL;
10403 uint16_t idx = in->port; /* We borrow port field as index */
10404 uint32_t max_size = sizeof(struct rte_flow_action) *
10405 ACTION_SAMPLE_ACTIONS_NUM;
10407 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
10408 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
10409 memset(data, 0x00, max_size);
10410 for (; i <= n - 1; i++) {
10411 action = in->args.vc.actions + i;
10412 if (action->type == RTE_FLOW_ACTION_TYPE_END)
10414 switch (action->type) {
10415 case RTE_FLOW_ACTION_TYPE_MARK:
10416 size = sizeof(struct rte_flow_action_mark);
10417 rte_memcpy(&sample_mark[idx],
10418 (const void *)action->conf, size);
10419 action->conf = &sample_mark[idx];
10421 case RTE_FLOW_ACTION_TYPE_COUNT:
10422 size = sizeof(struct rte_flow_action_count);
10423 rte_memcpy(&sample_count[idx],
10424 (const void *)action->conf, size);
10425 action->conf = &sample_count[idx];
10427 case RTE_FLOW_ACTION_TYPE_QUEUE:
10428 size = sizeof(struct rte_flow_action_queue);
10429 rte_memcpy(&sample_queue[idx],
10430 (const void *)action->conf, size);
10431 action->conf = &sample_queue[idx];
10433 case RTE_FLOW_ACTION_TYPE_RSS:
10434 size = sizeof(struct rte_flow_action_rss);
10435 rss = action->conf;
10436 rte_memcpy(&sample_rss_data[idx].conf,
10437 (const void *)rss, size);
10438 if (rss->key_len && rss->key) {
10439 sample_rss_data[idx].conf.key =
10440 sample_rss_data[idx].key;
10441 rte_memcpy((void *)((uintptr_t)
10442 sample_rss_data[idx].conf.key),
10443 (const void *)rss->key,
10444 sizeof(uint8_t) * rss->key_len);
10446 if (rss->queue_num && rss->queue) {
10447 sample_rss_data[idx].conf.queue =
10448 sample_rss_data[idx].queue;
10449 rte_memcpy((void *)((uintptr_t)
10450 sample_rss_data[idx].conf.queue),
10451 (const void *)rss->queue,
10452 sizeof(uint16_t) * rss->queue_num);
10454 action->conf = &sample_rss_data[idx].conf;
10456 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
10457 size = sizeof(struct rte_flow_action_raw_encap);
10458 rte_memcpy(&sample_encap[idx],
10459 (const void *)action->conf, size);
10460 action->conf = &sample_encap[idx];
10462 case RTE_FLOW_ACTION_TYPE_PORT_ID:
10463 size = sizeof(struct rte_flow_action_port_id);
10464 rte_memcpy(&sample_port_id[idx],
10465 (const void *)action->conf, size);
10466 action->conf = &sample_port_id[idx];
10468 case RTE_FLOW_ACTION_TYPE_PF:
10470 case RTE_FLOW_ACTION_TYPE_VF:
10471 size = sizeof(struct rte_flow_action_vf);
10472 rte_memcpy(&sample_vf[idx],
10473 (const void *)action->conf, size);
10474 action->conf = &sample_vf[idx];
10476 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
10477 size = sizeof(struct rte_flow_action_vxlan_encap);
10478 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
10479 action->conf = &sample_vxlan_encap[idx].conf;
10481 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
10482 size = sizeof(struct rte_flow_action_nvgre_encap);
10483 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
10484 action->conf = &sample_nvgre_encap[idx];
10487 fprintf(stderr, "Error - Not supported action\n");
10490 rte_memcpy(data, action, sizeof(struct rte_flow_action));
10495 /** Dispatch parsed buffer to function calls. */
10497 cmd_set_raw_parsed(const struct buffer *in)
10499 uint32_t n = in->args.vc.pattern_n;
10501 struct rte_flow_item *item = NULL;
10503 uint8_t *data = NULL;
10504 uint8_t *data_tail = NULL;
10505 size_t *total_size = NULL;
10506 uint16_t upper_layer = 0;
10507 uint16_t proto = 0;
10508 uint16_t idx = in->port; /* We borrow port field as index */
10509 int gtp_psc = -1; /* GTP PSC option index. */
10511 if (in->command == SET_SAMPLE_ACTIONS)
10512 return cmd_set_raw_parsed_sample(in);
10513 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
10514 in->command == SET_RAW_DECAP);
10515 if (in->command == SET_RAW_ENCAP) {
10516 total_size = &raw_encap_confs[idx].size;
10517 data = (uint8_t *)&raw_encap_confs[idx].data;
10519 total_size = &raw_decap_confs[idx].size;
10520 data = (uint8_t *)&raw_decap_confs[idx].data;
10523 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
10524 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
10525 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
10526 for (i = n - 1 ; i >= 0; --i) {
10527 const struct rte_flow_item_gtp *gtp;
10528 const struct rte_flow_item_geneve_opt *opt;
10530 item = in->args.vc.pattern + i;
10531 if (item->spec == NULL)
10532 item->spec = flow_item_default_mask(item);
10533 switch (item->type) {
10534 case RTE_FLOW_ITEM_TYPE_ETH:
10535 size = sizeof(struct rte_ether_hdr);
10537 case RTE_FLOW_ITEM_TYPE_VLAN:
10538 size = sizeof(struct rte_vlan_hdr);
10539 proto = RTE_ETHER_TYPE_VLAN;
10541 case RTE_FLOW_ITEM_TYPE_IPV4:
10542 size = sizeof(struct rte_ipv4_hdr);
10543 proto = RTE_ETHER_TYPE_IPV4;
10545 case RTE_FLOW_ITEM_TYPE_IPV6:
10546 size = sizeof(struct rte_ipv6_hdr);
10547 proto = RTE_ETHER_TYPE_IPV6;
10549 case RTE_FLOW_ITEM_TYPE_UDP:
10550 size = sizeof(struct rte_udp_hdr);
10553 case RTE_FLOW_ITEM_TYPE_TCP:
10554 size = sizeof(struct rte_tcp_hdr);
10557 case RTE_FLOW_ITEM_TYPE_VXLAN:
10558 size = sizeof(struct rte_vxlan_hdr);
10560 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
10561 size = sizeof(struct rte_vxlan_gpe_hdr);
10563 case RTE_FLOW_ITEM_TYPE_GRE:
10564 size = sizeof(struct rte_gre_hdr);
10567 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
10568 size = sizeof(rte_be32_t);
10571 case RTE_FLOW_ITEM_TYPE_MPLS:
10572 size = sizeof(struct rte_mpls_hdr);
10575 case RTE_FLOW_ITEM_TYPE_NVGRE:
10576 size = sizeof(struct rte_flow_item_nvgre);
10579 case RTE_FLOW_ITEM_TYPE_GENEVE:
10580 size = sizeof(struct rte_geneve_hdr);
10582 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
10583 opt = (const struct rte_flow_item_geneve_opt *)
10585 size = offsetof(struct rte_flow_item_geneve_opt, data);
10586 if (opt->option_len && opt->data) {
10587 *total_size += opt->option_len *
10589 rte_memcpy(data_tail - (*total_size),
10591 opt->option_len * sizeof(uint32_t));
10594 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
10595 size = sizeof(rte_be32_t);
10598 case RTE_FLOW_ITEM_TYPE_ESP:
10599 size = sizeof(struct rte_esp_hdr);
10602 case RTE_FLOW_ITEM_TYPE_AH:
10603 size = sizeof(struct rte_flow_item_ah);
10606 case RTE_FLOW_ITEM_TYPE_GTP:
10608 size = sizeof(struct rte_gtp_hdr);
10611 if (gtp_psc != i + 1) {
10613 "Error - GTP PSC does not follow GTP\n");
10617 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
10618 /* Only E flag should be set. */
10620 "Error - GTP unsupported flags\n");
10623 struct rte_gtp_hdr_ext_word ext_word = {
10627 /* We have to add GTP header extra word. */
10628 *total_size += sizeof(ext_word);
10629 rte_memcpy(data_tail - (*total_size),
10630 &ext_word, sizeof(ext_word));
10632 size = sizeof(struct rte_gtp_hdr);
10634 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
10635 if (gtp_psc >= 0) {
10637 "Error - Multiple GTP PSC items\n");
10640 const struct rte_flow_item_gtp_psc
10644 uint8_t pdu_type:4;
10648 psc.len = sizeof(psc) / 4;
10649 psc.pdu_type = opt->hdr.type;
10650 psc.qfi = opt->hdr.qfi;
10652 *total_size += sizeof(psc);
10653 rte_memcpy(data_tail - (*total_size),
10654 &psc, sizeof(psc));
10659 case RTE_FLOW_ITEM_TYPE_PFCP:
10660 size = sizeof(struct rte_flow_item_pfcp);
10662 case RTE_FLOW_ITEM_TYPE_FLEX:
10663 size = item->spec ?
10664 ((const struct rte_flow_item_flex *)
10665 item->spec)->length : 0;
10667 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
10670 const struct rte_flow_item_gre_opt
10672 if (opt->checksum_rsvd.checksum) {
10674 sizeof(opt->checksum_rsvd);
10675 rte_memcpy(data_tail - (*total_size),
10676 &opt->checksum_rsvd,
10677 sizeof(opt->checksum_rsvd));
10679 if (opt->key.key) {
10680 *total_size += sizeof(opt->key.key);
10681 rte_memcpy(data_tail - (*total_size),
10683 sizeof(opt->key.key));
10685 if (opt->sequence.sequence) {
10686 *total_size += sizeof(opt->sequence.sequence);
10687 rte_memcpy(data_tail - (*total_size),
10688 &opt->sequence.sequence,
10689 sizeof(opt->sequence.sequence));
10695 fprintf(stderr, "Error - Not supported item\n");
10698 *total_size += size;
10699 rte_memcpy(data_tail - (*total_size), item->spec, size);
10700 /* update some fields which cannot be set by cmdline */
10701 update_fields((data_tail - (*total_size)), item,
10703 upper_layer = proto;
10705 if (verbose_level & 0x1)
10706 printf("total data size is %zu\n", (*total_size));
10707 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
10708 memmove(data, (data_tail - (*total_size)), *total_size);
10713 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
10716 /** Populate help strings for current token (cmdline API). */
10718 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
10721 struct context *ctx = &cmd_flow_context;
10722 const struct token *token = &token_list[ctx->prev];
10727 /* Set token type and update global help with details. */
10728 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
10730 cmd_set_raw.help_str = token->help;
10732 cmd_set_raw.help_str = token->name;
10736 /** Token definition template (cmdline API). */
10737 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
10738 .ops = &(struct cmdline_token_ops){
10739 .parse = cmd_flow_parse,
10740 .complete_get_nb = cmd_flow_complete_get_nb,
10741 .complete_get_elt = cmd_flow_complete_get_elt,
10742 .get_help = cmd_set_raw_get_help,
10747 /** Populate the next dynamic token. */
10749 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
10750 cmdline_parse_token_hdr_t **hdr_inst)
10752 struct context *ctx = &cmd_flow_context;
10754 /* Always reinitialize context before requesting the first token. */
10755 if (!(hdr_inst - cmd_set_raw.tokens)) {
10756 cmd_flow_context_init(ctx);
10757 ctx->curr = START_SET;
10759 /* Return NULL when no more tokens are expected. */
10760 if (!ctx->next_num && (ctx->curr != START_SET)) {
10764 /* Determine if command should end here. */
10765 if (ctx->eol && ctx->last && ctx->next_num) {
10766 const enum index *list = ctx->next[ctx->next_num - 1];
10769 for (i = 0; list[i]; ++i) {
10770 if (list[i] != END)
10776 *hdr = &cmd_set_raw_token_hdr;
10779 /** Token generator and output processing callback (cmdline API). */
10781 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
10784 cmd_set_raw_tok(arg0, arg2);
10786 cmd_set_raw_parsed(arg0);
10789 /** Global parser instance (cmdline API). */
10790 cmdline_parse_inst_t cmd_set_raw = {
10791 .f = cmd_set_raw_cb,
10792 .data = NULL, /**< Unused. */
10793 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
10796 }, /**< Tokens are returned by cmd_flow_tok(). */
10799 /* *** display raw_encap/raw_decap buf */
10800 struct cmd_show_set_raw_result {
10801 cmdline_fixed_string_t cmd_show;
10802 cmdline_fixed_string_t cmd_what;
10803 cmdline_fixed_string_t cmd_all;
10804 uint16_t cmd_index;
10808 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
10810 struct cmd_show_set_raw_result *res = parsed_result;
10811 uint16_t index = res->cmd_index;
10813 uint8_t *raw_data = NULL;
10814 size_t raw_size = 0;
10815 char title[16] = {0};
10818 RTE_SET_USED(data);
10819 if (!strcmp(res->cmd_all, "all")) {
10822 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
10823 fprintf(stderr, "index should be 0-%u\n",
10824 RAW_ENCAP_CONFS_MAX_NUM - 1);
10828 if (!strcmp(res->cmd_what, "raw_encap")) {
10829 raw_data = (uint8_t *)&raw_encap_confs[index].data;
10830 raw_size = raw_encap_confs[index].size;
10831 snprintf(title, 16, "\nindex: %u", index);
10832 rte_hexdump(stdout, title, raw_data, raw_size);
10834 raw_data = (uint8_t *)&raw_decap_confs[index].data;
10835 raw_size = raw_decap_confs[index].size;
10836 snprintf(title, 16, "\nindex: %u", index);
10837 rte_hexdump(stdout, title, raw_data, raw_size);
10839 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
10842 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
10843 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
10845 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
10846 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
10847 cmd_what, "raw_encap#raw_decap");
10848 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
10849 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
10850 cmd_index, RTE_UINT16);
10851 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
10852 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
10854 cmdline_parse_inst_t cmd_show_set_raw = {
10855 .f = cmd_show_set_raw_parsed,
10857 .help_str = "show <raw_encap|raw_decap> <index>",
10859 (void *)&cmd_show_set_raw_cmd_show,
10860 (void *)&cmd_show_set_raw_cmd_what,
10861 (void *)&cmd_show_set_raw_cmd_index,
10865 cmdline_parse_inst_t cmd_show_set_raw_all = {
10866 .f = cmd_show_set_raw_parsed,
10868 .help_str = "show <raw_encap|raw_decap> all",
10870 (void *)&cmd_show_set_raw_cmd_show,
10871 (void *)&cmd_show_set_raw_cmd_what,
10872 (void *)&cmd_show_set_raw_cmd_all,