1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016 6WIND S.A.
3 * Copyright 2016 Mellanox Technologies, Ltd
14 #include <rte_string_fns.h>
15 #include <rte_common.h>
16 #include <rte_ethdev.h>
17 #include <rte_byteorder.h>
18 #include <cmdline_parse.h>
19 #include <cmdline_parse_etheraddr.h>
20 #include <cmdline_parse_string.h>
21 #include <cmdline_parse_num.h>
23 #include <rte_hexdump.h>
24 #include <rte_vxlan.h>
28 #include <rte_geneve.h>
32 /** Parser token indices. */
54 COMMON_PRIORITY_LEVEL,
55 COMMON_INDIRECT_ACTION_ID,
60 /* TOP-level command. */
63 /* Top-level command. */
65 /* Sub-leve commands. */
72 /* Top-level command. */
74 /* Sub-level commands. */
95 /* Tunnel arguments. */
102 /* Destroy arguments. */
105 /* Query arguments. */
108 /* List arguments. */
111 /* Destroy aged flow arguments. */
114 /* Validate/create arguments. */
127 /* Configure arguments */
128 CONFIG_QUEUES_NUMBER,
130 CONFIG_COUNTERS_NUMBER,
131 CONFIG_AGING_OBJECTS_NUMBER,
132 CONFIG_METERS_NUMBER,
134 /* Indirect action arguments */
135 INDIRECT_ACTION_CREATE,
136 INDIRECT_ACTION_UPDATE,
137 INDIRECT_ACTION_DESTROY,
138 INDIRECT_ACTION_QUERY,
140 /* Indirect action create arguments */
141 INDIRECT_ACTION_CREATE_ID,
142 INDIRECT_ACTION_INGRESS,
143 INDIRECT_ACTION_EGRESS,
144 INDIRECT_ACTION_TRANSFER,
145 INDIRECT_ACTION_SPEC,
147 /* Indirect action destroy arguments */
148 INDIRECT_ACTION_DESTROY_ID,
150 /* Validate/create pattern. */
178 ITEM_RAW_PATTERN_HEX,
189 ITEM_VLAN_INNER_TYPE,
190 ITEM_VLAN_HAS_MORE_VLAN,
195 ITEM_IPV4_FRAGMENT_OFFSET,
207 ITEM_IPV6_HAS_FRAG_EXT,
227 ITEM_VXLAN_LAST_RSVD,
229 ITEM_E_TAG_GRP_ECID_B,
238 ITEM_GRE_C_RSVD0_VER,
257 ITEM_ARP_ETH_IPV4_SHA,
258 ITEM_ARP_ETH_IPV4_SPA,
259 ITEM_ARP_ETH_IPV4_THA,
260 ITEM_ARP_ETH_IPV4_TPA,
262 ITEM_IPV6_EXT_NEXT_HDR,
264 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
265 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
266 ITEM_IPV6_FRAG_EXT_ID,
271 ITEM_ICMP6_ND_NS_TARGET_ADDR,
273 ITEM_ICMP6_ND_NA_TARGET_ADDR,
275 ITEM_ICMP6_ND_OPT_TYPE,
276 ITEM_ICMP6_ND_OPT_SLA_ETH,
277 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
278 ITEM_ICMP6_ND_OPT_TLA_ETH,
279 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
285 ITEM_GRE_OPTION_CHECKSUM,
287 ITEM_GRE_OPTION_SEQUENCE,
296 ITEM_HIGIG2_CLASSIFICATION,
302 ITEM_L2TPV3OIP_SESSION_ID,
312 ITEM_ECPRI_COMMON_TYPE,
313 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
314 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
315 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
316 ITEM_ECPRI_MSG_IQ_DATA_PCID,
317 ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
318 ITEM_ECPRI_MSG_DLY_MSR_MSRID,
320 ITEM_GENEVE_OPT_CLASS,
321 ITEM_GENEVE_OPT_TYPE,
322 ITEM_GENEVE_OPT_LENGTH,
323 ITEM_GENEVE_OPT_DATA,
325 ITEM_INTEGRITY_LEVEL,
326 ITEM_INTEGRITY_VALUE,
331 ITEM_PORT_REPRESENTOR,
332 ITEM_PORT_REPRESENTOR_PORT_ID,
333 ITEM_REPRESENTED_PORT,
334 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
336 ITEM_FLEX_ITEM_HANDLE,
337 ITEM_FLEX_PATTERN_HANDLE,
340 ITEM_L2TPV2_TYPE_DATA,
341 ITEM_L2TPV2_TYPE_DATA_L,
342 ITEM_L2TPV2_TYPE_DATA_S,
343 ITEM_L2TPV2_TYPE_DATA_O,
344 ITEM_L2TPV2_TYPE_DATA_L_S,
345 ITEM_L2TPV2_TYPE_CTRL,
346 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
347 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
348 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
349 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
350 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
351 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
352 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
353 ITEM_L2TPV2_MSG_DATA_S_NS,
354 ITEM_L2TPV2_MSG_DATA_S_NR,
355 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
356 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
357 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
358 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
359 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
360 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
361 ITEM_L2TPV2_MSG_DATA_L_S_NS,
362 ITEM_L2TPV2_MSG_DATA_L_S_NR,
363 ITEM_L2TPV2_MSG_CTRL_LENGTH,
364 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
365 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
366 ITEM_L2TPV2_MSG_CTRL_NS,
367 ITEM_L2TPV2_MSG_CTRL_NR,
373 /* Validate/create actions. */
392 ACTION_RSS_FUNC_DEFAULT,
393 ACTION_RSS_FUNC_TOEPLITZ,
394 ACTION_RSS_FUNC_SIMPLE_XOR,
395 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
407 ACTION_PHY_PORT_ORIGINAL,
408 ACTION_PHY_PORT_INDEX,
410 ACTION_PORT_ID_ORIGINAL,
414 ACTION_METER_COLOR_TYPE,
415 ACTION_METER_COLOR_GREEN,
416 ACTION_METER_COLOR_YELLOW,
417 ACTION_METER_COLOR_RED,
419 ACTION_OF_SET_MPLS_TTL,
420 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
421 ACTION_OF_DEC_MPLS_TTL,
422 ACTION_OF_SET_NW_TTL,
423 ACTION_OF_SET_NW_TTL_NW_TTL,
424 ACTION_OF_DEC_NW_TTL,
425 ACTION_OF_COPY_TTL_OUT,
426 ACTION_OF_COPY_TTL_IN,
429 ACTION_OF_PUSH_VLAN_ETHERTYPE,
430 ACTION_OF_SET_VLAN_VID,
431 ACTION_OF_SET_VLAN_VID_VLAN_VID,
432 ACTION_OF_SET_VLAN_PCP,
433 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
435 ACTION_OF_POP_MPLS_ETHERTYPE,
437 ACTION_OF_PUSH_MPLS_ETHERTYPE,
444 ACTION_MPLSOGRE_ENCAP,
445 ACTION_MPLSOGRE_DECAP,
446 ACTION_MPLSOUDP_ENCAP,
447 ACTION_MPLSOUDP_DECAP,
449 ACTION_SET_IPV4_SRC_IPV4_SRC,
451 ACTION_SET_IPV4_DST_IPV4_DST,
453 ACTION_SET_IPV6_SRC_IPV6_SRC,
455 ACTION_SET_IPV6_DST_IPV6_DST,
457 ACTION_SET_TP_SRC_TP_SRC,
459 ACTION_SET_TP_DST_TP_DST,
465 ACTION_SET_MAC_SRC_MAC_SRC,
467 ACTION_SET_MAC_DST_MAC_DST,
469 ACTION_INC_TCP_SEQ_VALUE,
471 ACTION_DEC_TCP_SEQ_VALUE,
473 ACTION_INC_TCP_ACK_VALUE,
475 ACTION_DEC_TCP_ACK_VALUE,
478 ACTION_RAW_ENCAP_INDEX,
479 ACTION_RAW_ENCAP_INDEX_VALUE,
480 ACTION_RAW_DECAP_INDEX,
481 ACTION_RAW_DECAP_INDEX_VALUE,
484 ACTION_SET_TAG_INDEX,
487 ACTION_SET_META_DATA,
488 ACTION_SET_META_MASK,
489 ACTION_SET_IPV4_DSCP,
490 ACTION_SET_IPV4_DSCP_VALUE,
491 ACTION_SET_IPV6_DSCP,
492 ACTION_SET_IPV6_DSCP_VALUE,
498 ACTION_SAMPLE_INDEX_VALUE,
500 INDIRECT_ACTION_ID2PTR,
502 ACTION_MODIFY_FIELD_OP,
503 ACTION_MODIFY_FIELD_OP_VALUE,
504 ACTION_MODIFY_FIELD_DST_TYPE,
505 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
506 ACTION_MODIFY_FIELD_DST_LEVEL,
507 ACTION_MODIFY_FIELD_DST_OFFSET,
508 ACTION_MODIFY_FIELD_SRC_TYPE,
509 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
510 ACTION_MODIFY_FIELD_SRC_LEVEL,
511 ACTION_MODIFY_FIELD_SRC_OFFSET,
512 ACTION_MODIFY_FIELD_SRC_VALUE,
513 ACTION_MODIFY_FIELD_SRC_POINTER,
514 ACTION_MODIFY_FIELD_WIDTH,
516 ACTION_CONNTRACK_UPDATE,
517 ACTION_CONNTRACK_UPDATE_DIR,
518 ACTION_CONNTRACK_UPDATE_CTX,
522 ACTION_PORT_REPRESENTOR,
523 ACTION_PORT_REPRESENTOR_PORT_ID,
524 ACTION_REPRESENTED_PORT,
525 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
528 /** Maximum size for pattern in struct rte_flow_item_raw. */
529 #define ITEM_RAW_PATTERN_SIZE 512
531 /** Maximum size for GENEVE option data pattern in bytes. */
532 #define ITEM_GENEVE_OPT_DATA_SIZE 124
534 /** Storage size for struct rte_flow_item_raw including pattern. */
535 #define ITEM_RAW_SIZE \
536 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
538 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
539 #define ACTION_MODIFY_PATTERN_SIZE 32
541 /** Storage size for struct rte_flow_action_modify_field including pattern. */
542 #define ACTION_MODIFY_SIZE \
543 (sizeof(struct rte_flow_action_modify_field) + \
544 ACTION_MODIFY_PATTERN_SIZE)
546 /** Maximum number of queue indices in struct rte_flow_action_rss. */
547 #define ACTION_RSS_QUEUE_NUM 128
549 /** Storage for struct rte_flow_action_rss including external data. */
550 struct action_rss_data {
551 struct rte_flow_action_rss conf;
552 uint8_t key[RSS_HASH_KEY_LENGTH];
553 uint16_t queue[ACTION_RSS_QUEUE_NUM];
556 /** Maximum data size in struct rte_flow_action_raw_encap. */
557 #define ACTION_RAW_ENCAP_MAX_DATA 512
558 #define RAW_ENCAP_CONFS_MAX_NUM 8
560 /** Storage for struct rte_flow_action_raw_encap. */
561 struct raw_encap_conf {
562 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
563 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
567 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
569 /** Storage for struct rte_flow_action_raw_encap including external data. */
570 struct action_raw_encap_data {
571 struct rte_flow_action_raw_encap conf;
572 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
573 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
577 /** Storage for struct rte_flow_action_raw_decap. */
578 struct raw_decap_conf {
579 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
583 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
585 /** Storage for struct rte_flow_action_raw_decap including external data. */
586 struct action_raw_decap_data {
587 struct rte_flow_action_raw_decap conf;
588 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
592 struct vxlan_encap_conf vxlan_encap_conf = {
596 .vni = "\x00\x00\x00",
598 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
599 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
600 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
601 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
602 "\x00\x00\x00\x00\x00\x00\x00\x01",
603 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
604 "\x00\x00\x00\x00\x00\x00\x11\x11",
608 .eth_src = "\x00\x00\x00\x00\x00\x00",
609 .eth_dst = "\xff\xff\xff\xff\xff\xff",
612 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
613 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
615 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
616 struct action_vxlan_encap_data {
617 struct rte_flow_action_vxlan_encap conf;
618 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
619 struct rte_flow_item_eth item_eth;
620 struct rte_flow_item_vlan item_vlan;
622 struct rte_flow_item_ipv4 item_ipv4;
623 struct rte_flow_item_ipv6 item_ipv6;
625 struct rte_flow_item_udp item_udp;
626 struct rte_flow_item_vxlan item_vxlan;
629 struct nvgre_encap_conf nvgre_encap_conf = {
632 .tni = "\x00\x00\x00",
633 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
634 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
635 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
636 "\x00\x00\x00\x00\x00\x00\x00\x01",
637 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
638 "\x00\x00\x00\x00\x00\x00\x11\x11",
640 .eth_src = "\x00\x00\x00\x00\x00\x00",
641 .eth_dst = "\xff\xff\xff\xff\xff\xff",
644 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
645 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
647 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
648 struct action_nvgre_encap_data {
649 struct rte_flow_action_nvgre_encap conf;
650 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
651 struct rte_flow_item_eth item_eth;
652 struct rte_flow_item_vlan item_vlan;
654 struct rte_flow_item_ipv4 item_ipv4;
655 struct rte_flow_item_ipv6 item_ipv6;
657 struct rte_flow_item_nvgre item_nvgre;
660 struct l2_encap_conf l2_encap_conf;
662 struct l2_decap_conf l2_decap_conf;
664 struct mplsogre_encap_conf mplsogre_encap_conf;
666 struct mplsogre_decap_conf mplsogre_decap_conf;
668 struct mplsoudp_encap_conf mplsoudp_encap_conf;
670 struct mplsoudp_decap_conf mplsoudp_decap_conf;
672 struct rte_flow_action_conntrack conntrack_context;
674 #define ACTION_SAMPLE_ACTIONS_NUM 10
675 #define RAW_SAMPLE_CONFS_MAX_NUM 8
676 /** Storage for struct rte_flow_action_sample including external data. */
677 struct action_sample_data {
678 struct rte_flow_action_sample conf;
681 /** Storage for struct rte_flow_action_sample. */
682 struct raw_sample_conf {
683 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
685 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
686 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
687 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
688 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
689 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
690 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
691 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
692 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
693 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
694 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
696 static const char *const modify_field_ops[] = {
697 "set", "add", "sub", NULL
700 static const char *const modify_field_ids[] = {
701 "start", "mac_dst", "mac_src",
702 "vlan_type", "vlan_id", "mac_type",
703 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
704 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
705 "tcp_port_src", "tcp_port_dst",
706 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
707 "udp_port_src", "udp_port_dst",
708 "vxlan_vni", "geneve_vni", "gtp_teid",
709 "tag", "mark", "meta", "pointer", "value", NULL
712 /** Maximum number of subsequent tokens and arguments on the stack. */
713 #define CTX_STACK_SIZE 16
715 /** Parser context. */
717 /** Stack of subsequent token lists to process. */
718 const enum index *next[CTX_STACK_SIZE];
719 /** Arguments for stacked tokens. */
720 const void *args[CTX_STACK_SIZE];
721 enum index curr; /**< Current token index. */
722 enum index prev; /**< Index of the last token seen. */
723 int next_num; /**< Number of entries in next[]. */
724 int args_num; /**< Number of entries in args[]. */
725 uint32_t eol:1; /**< EOL has been detected. */
726 uint32_t last:1; /**< No more arguments. */
727 portid_t port; /**< Current port ID (for completions). */
728 uint32_t objdata; /**< Object-specific data. */
729 void *object; /**< Address of current object for relative offsets. */
730 void *objmask; /**< Object a full mask must be written to. */
733 /** Token argument. */
735 uint32_t hton:1; /**< Use network byte ordering. */
736 uint32_t sign:1; /**< Value is signed. */
737 uint32_t bounded:1; /**< Value is bounded. */
738 uintmax_t min; /**< Minimum value if bounded. */
739 uintmax_t max; /**< Maximum value if bounded. */
740 uint32_t offset; /**< Relative offset from ctx->object. */
741 uint32_t size; /**< Field size. */
742 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
745 /** Parser token definition. */
747 /** Type displayed during completion (defaults to "TOKEN"). */
749 /** Help displayed during completion (defaults to token name). */
751 /** Private data used by parser functions. */
754 * Lists of subsequent tokens to push on the stack. Each call to the
755 * parser consumes the last entry of that stack.
757 const enum index *const *next;
758 /** Arguments stack for subsequent tokens that need them. */
759 const struct arg *const *args;
761 * Token-processing callback, returns -1 in case of error, the
762 * length of the matched string otherwise. If NULL, attempts to
763 * match the token name.
765 * If buf is not NULL, the result should be stored in it according
766 * to context. An error is returned if not large enough.
768 int (*call)(struct context *ctx, const struct token *token,
769 const char *str, unsigned int len,
770 void *buf, unsigned int size);
772 * Callback that provides possible values for this token, used for
773 * completion. Returns -1 in case of error, the number of possible
774 * values otherwise. If NULL, the token name is used.
776 * If buf is not NULL, entry index ent is written to buf and the
777 * full length of the entry is returned (same behavior as
780 int (*comp)(struct context *ctx, const struct token *token,
781 unsigned int ent, char *buf, unsigned int size);
782 /** Mandatory token name, no default value. */
786 /** Static initializer for the next field. */
787 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
789 /** Static initializer for a NEXT() entry. */
790 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
792 /** Static initializer for the args field. */
793 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
795 /** Static initializer for ARGS() to target a field. */
796 #define ARGS_ENTRY(s, f) \
797 (&(const struct arg){ \
798 .offset = offsetof(s, f), \
799 .size = sizeof(((s *)0)->f), \
802 /** Static initializer for ARGS() to target a bit-field. */
803 #define ARGS_ENTRY_BF(s, f, b) \
804 (&(const struct arg){ \
806 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
809 /** Static initializer for ARGS() to target a field with limits. */
810 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
811 (&(const struct arg){ \
815 .offset = offsetof(s, f), \
816 .size = sizeof(((s *)0)->f), \
819 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
820 #define ARGS_ENTRY_MASK(s, f, m) \
821 (&(const struct arg){ \
822 .offset = offsetof(s, f), \
823 .size = sizeof(((s *)0)->f), \
824 .mask = (const void *)(m), \
827 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
828 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
829 (&(const struct arg){ \
831 .offset = offsetof(s, f), \
832 .size = sizeof(((s *)0)->f), \
833 .mask = (const void *)(m), \
836 /** Static initializer for ARGS() to target a pointer. */
837 #define ARGS_ENTRY_PTR(s, f) \
838 (&(const struct arg){ \
839 .size = sizeof(*((s *)0)->f), \
842 /** Static initializer for ARGS() with arbitrary offset and size. */
843 #define ARGS_ENTRY_ARB(o, s) \
844 (&(const struct arg){ \
849 /** Same as ARGS_ENTRY_ARB() with bounded values. */
850 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
851 (&(const struct arg){ \
859 /** Same as ARGS_ENTRY() using network byte ordering. */
860 #define ARGS_ENTRY_HTON(s, f) \
861 (&(const struct arg){ \
863 .offset = offsetof(s, f), \
864 .size = sizeof(((s *)0)->f), \
867 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
868 #define ARG_ENTRY_HTON(s) \
869 (&(const struct arg){ \
875 /** Parser output buffer layout expected by cmd_flow_parsed(). */
877 enum index command; /**< Flow command. */
878 portid_t port; /**< Affected port ID. */
881 struct rte_flow_port_attr port_attr;
883 struct rte_flow_queue_attr queue_attr;
884 } configure; /**< Configuration arguments. */
887 uint32_t action_id_n;
888 } ia_destroy; /**< Indirect action destroy arguments. */
891 } ia; /* Indirect action query arguments */
893 struct rte_flow_attr attr;
894 struct tunnel_ops tunnel_ops;
895 struct rte_flow_item *pattern;
896 struct rte_flow_action *actions;
900 } vc; /**< Validate/create arguments. */
904 } destroy; /**< Destroy arguments. */
909 } dump; /**< Dump arguments. */
912 struct rte_flow_action action;
913 } query; /**< Query arguments. */
917 } list; /**< List arguments. */
920 } isolate; /**< Isolated mode arguments. */
923 } aged; /**< Aged arguments. */
926 } policy;/**< Policy arguments. */
931 } flex; /**< Flex arguments*/
932 } args; /**< Command arguments. */
935 /** Private data for pattern items. */
936 struct parse_item_priv {
937 enum rte_flow_item_type type; /**< Item type. */
938 uint32_t size; /**< Size of item specification structure. */
941 #define PRIV_ITEM(t, s) \
942 (&(const struct parse_item_priv){ \
943 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
947 /** Private data for actions. */
948 struct parse_action_priv {
949 enum rte_flow_action_type type; /**< Action type. */
950 uint32_t size; /**< Size of action configuration structure. */
953 #define PRIV_ACTION(t, s) \
954 (&(const struct parse_action_priv){ \
955 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
959 static const enum index next_flex_item[] = {
966 static const enum index next_config_attr[] = {
967 CONFIG_QUEUES_NUMBER,
969 CONFIG_COUNTERS_NUMBER,
970 CONFIG_AGING_OBJECTS_NUMBER,
971 CONFIG_METERS_NUMBER,
976 static const enum index next_ia_create_attr[] = {
977 INDIRECT_ACTION_CREATE_ID,
978 INDIRECT_ACTION_INGRESS,
979 INDIRECT_ACTION_EGRESS,
980 INDIRECT_ACTION_TRANSFER,
981 INDIRECT_ACTION_SPEC,
985 static const enum index next_dump_subcmd[] = {
991 static const enum index next_ia_subcmd[] = {
992 INDIRECT_ACTION_CREATE,
993 INDIRECT_ACTION_UPDATE,
994 INDIRECT_ACTION_DESTROY,
995 INDIRECT_ACTION_QUERY,
999 static const enum index next_vc_attr[] = {
1011 static const enum index next_destroy_attr[] = {
1017 static const enum index next_dump_attr[] = {
1023 static const enum index next_list_attr[] = {
1029 static const enum index next_aged_attr[] = {
1035 static const enum index next_ia_destroy_attr[] = {
1036 INDIRECT_ACTION_DESTROY_ID,
1041 static const enum index item_param[] = {
1050 static const enum index next_item[] = {
1087 ITEM_ICMP6_ND_OPT_SLA_ETH,
1088 ITEM_ICMP6_ND_OPT_TLA_ETH,
1095 ITEM_PPPOE_PROTO_ID,
1106 ITEM_PORT_REPRESENTOR,
1107 ITEM_REPRESENTED_PORT,
1115 static const enum index item_fuzzy[] = {
1121 static const enum index item_any[] = {
1127 static const enum index item_vf[] = {
1133 static const enum index item_phy_port[] = {
1134 ITEM_PHY_PORT_INDEX,
1139 static const enum index item_port_id[] = {
1145 static const enum index item_mark[] = {
1151 static const enum index item_raw[] = {
1157 ITEM_RAW_PATTERN_HEX,
1162 static const enum index item_eth[] = {
1171 static const enum index item_vlan[] = {
1176 ITEM_VLAN_INNER_TYPE,
1177 ITEM_VLAN_HAS_MORE_VLAN,
1182 static const enum index item_ipv4[] = {
1186 ITEM_IPV4_FRAGMENT_OFFSET,
1195 static const enum index item_ipv6[] = {
1202 ITEM_IPV6_HAS_FRAG_EXT,
1207 static const enum index item_icmp[] = {
1216 static const enum index item_udp[] = {
1223 static const enum index item_tcp[] = {
1231 static const enum index item_sctp[] = {
1240 static const enum index item_vxlan[] = {
1242 ITEM_VXLAN_LAST_RSVD,
1247 static const enum index item_e_tag[] = {
1248 ITEM_E_TAG_GRP_ECID_B,
1253 static const enum index item_nvgre[] = {
1259 static const enum index item_mpls[] = {
1267 static const enum index item_gre[] = {
1269 ITEM_GRE_C_RSVD0_VER,
1277 static const enum index item_gre_key[] = {
1283 static const enum index item_gre_option[] = {
1284 ITEM_GRE_OPTION_CHECKSUM,
1285 ITEM_GRE_OPTION_KEY,
1286 ITEM_GRE_OPTION_SEQUENCE,
1291 static const enum index item_gtp[] = {
1299 static const enum index item_geneve[] = {
1307 static const enum index item_vxlan_gpe[] = {
1313 static const enum index item_arp_eth_ipv4[] = {
1314 ITEM_ARP_ETH_IPV4_SHA,
1315 ITEM_ARP_ETH_IPV4_SPA,
1316 ITEM_ARP_ETH_IPV4_THA,
1317 ITEM_ARP_ETH_IPV4_TPA,
1322 static const enum index item_ipv6_ext[] = {
1323 ITEM_IPV6_EXT_NEXT_HDR,
1328 static const enum index item_ipv6_frag_ext[] = {
1329 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1330 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1331 ITEM_IPV6_FRAG_EXT_ID,
1336 static const enum index item_icmp6[] = {
1343 static const enum index item_icmp6_nd_ns[] = {
1344 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1349 static const enum index item_icmp6_nd_na[] = {
1350 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1355 static const enum index item_icmp6_nd_opt[] = {
1356 ITEM_ICMP6_ND_OPT_TYPE,
1361 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1362 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1367 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1368 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1373 static const enum index item_meta[] = {
1379 static const enum index item_gtp_psc[] = {
1386 static const enum index item_pppoed[] = {
1392 static const enum index item_pppoes[] = {
1398 static const enum index item_pppoe_proto_id[] = {
1403 static const enum index item_higig2[] = {
1404 ITEM_HIGIG2_CLASSIFICATION,
1410 static const enum index item_esp[] = {
1416 static const enum index item_ah[] = {
1422 static const enum index item_pfcp[] = {
1429 static const enum index next_set_raw[] = {
1435 static const enum index item_tag[] = {
1442 static const enum index item_l2tpv3oip[] = {
1443 ITEM_L2TPV3OIP_SESSION_ID,
1448 static const enum index item_ecpri[] = {
1454 static const enum index item_ecpri_common[] = {
1455 ITEM_ECPRI_COMMON_TYPE,
1459 static const enum index item_ecpri_common_type[] = {
1460 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1461 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1462 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1466 static const enum index item_geneve_opt[] = {
1467 ITEM_GENEVE_OPT_CLASS,
1468 ITEM_GENEVE_OPT_TYPE,
1469 ITEM_GENEVE_OPT_LENGTH,
1470 ITEM_GENEVE_OPT_DATA,
1475 static const enum index item_integrity[] = {
1476 ITEM_INTEGRITY_LEVEL,
1477 ITEM_INTEGRITY_VALUE,
1481 static const enum index item_integrity_lv[] = {
1482 ITEM_INTEGRITY_LEVEL,
1483 ITEM_INTEGRITY_VALUE,
1488 static const enum index item_port_representor[] = {
1489 ITEM_PORT_REPRESENTOR_PORT_ID,
1494 static const enum index item_represented_port[] = {
1495 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1500 static const enum index item_flex[] = {
1501 ITEM_FLEX_PATTERN_HANDLE,
1502 ITEM_FLEX_ITEM_HANDLE,
1507 static const enum index item_l2tpv2[] = {
1513 static const enum index item_l2tpv2_type[] = {
1514 ITEM_L2TPV2_TYPE_DATA,
1515 ITEM_L2TPV2_TYPE_DATA_L,
1516 ITEM_L2TPV2_TYPE_DATA_S,
1517 ITEM_L2TPV2_TYPE_DATA_O,
1518 ITEM_L2TPV2_TYPE_DATA_L_S,
1519 ITEM_L2TPV2_TYPE_CTRL,
1523 static const enum index item_l2tpv2_type_data[] = {
1524 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1525 ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1530 static const enum index item_l2tpv2_type_data_l[] = {
1531 ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1532 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1533 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1538 static const enum index item_l2tpv2_type_data_s[] = {
1539 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1540 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1541 ITEM_L2TPV2_MSG_DATA_S_NS,
1542 ITEM_L2TPV2_MSG_DATA_S_NR,
1547 static const enum index item_l2tpv2_type_data_o[] = {
1548 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1549 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1550 ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1555 static const enum index item_l2tpv2_type_data_l_s[] = {
1556 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1557 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1558 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1559 ITEM_L2TPV2_MSG_DATA_L_S_NS,
1560 ITEM_L2TPV2_MSG_DATA_L_S_NR,
1565 static const enum index item_l2tpv2_type_ctrl[] = {
1566 ITEM_L2TPV2_MSG_CTRL_LENGTH,
1567 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1568 ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1569 ITEM_L2TPV2_MSG_CTRL_NS,
1570 ITEM_L2TPV2_MSG_CTRL_NR,
1575 static const enum index item_ppp[] = {
1583 static const enum index next_action[] = {
1600 ACTION_OF_SET_MPLS_TTL,
1601 ACTION_OF_DEC_MPLS_TTL,
1602 ACTION_OF_SET_NW_TTL,
1603 ACTION_OF_DEC_NW_TTL,
1604 ACTION_OF_COPY_TTL_OUT,
1605 ACTION_OF_COPY_TTL_IN,
1607 ACTION_OF_PUSH_VLAN,
1608 ACTION_OF_SET_VLAN_VID,
1609 ACTION_OF_SET_VLAN_PCP,
1611 ACTION_OF_PUSH_MPLS,
1618 ACTION_MPLSOGRE_ENCAP,
1619 ACTION_MPLSOGRE_DECAP,
1620 ACTION_MPLSOUDP_ENCAP,
1621 ACTION_MPLSOUDP_DECAP,
1622 ACTION_SET_IPV4_SRC,
1623 ACTION_SET_IPV4_DST,
1624 ACTION_SET_IPV6_SRC,
1625 ACTION_SET_IPV6_DST,
1641 ACTION_SET_IPV4_DSCP,
1642 ACTION_SET_IPV6_DSCP,
1646 ACTION_MODIFY_FIELD,
1648 ACTION_CONNTRACK_UPDATE,
1649 ACTION_PORT_REPRESENTOR,
1650 ACTION_REPRESENTED_PORT,
1654 static const enum index action_mark[] = {
1660 static const enum index action_queue[] = {
1666 static const enum index action_count[] = {
1672 static const enum index action_rss[] = {
1683 static const enum index action_vf[] = {
1690 static const enum index action_phy_port[] = {
1691 ACTION_PHY_PORT_ORIGINAL,
1692 ACTION_PHY_PORT_INDEX,
1697 static const enum index action_port_id[] = {
1698 ACTION_PORT_ID_ORIGINAL,
1704 static const enum index action_meter[] = {
1710 static const enum index action_meter_color[] = {
1711 ACTION_METER_COLOR_TYPE,
1716 static const enum index action_of_set_mpls_ttl[] = {
1717 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1722 static const enum index action_of_set_nw_ttl[] = {
1723 ACTION_OF_SET_NW_TTL_NW_TTL,
1728 static const enum index action_of_push_vlan[] = {
1729 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1734 static const enum index action_of_set_vlan_vid[] = {
1735 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1740 static const enum index action_of_set_vlan_pcp[] = {
1741 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1746 static const enum index action_of_pop_mpls[] = {
1747 ACTION_OF_POP_MPLS_ETHERTYPE,
1752 static const enum index action_of_push_mpls[] = {
1753 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1758 static const enum index action_set_ipv4_src[] = {
1759 ACTION_SET_IPV4_SRC_IPV4_SRC,
1764 static const enum index action_set_mac_src[] = {
1765 ACTION_SET_MAC_SRC_MAC_SRC,
1770 static const enum index action_set_ipv4_dst[] = {
1771 ACTION_SET_IPV4_DST_IPV4_DST,
1776 static const enum index action_set_ipv6_src[] = {
1777 ACTION_SET_IPV6_SRC_IPV6_SRC,
1782 static const enum index action_set_ipv6_dst[] = {
1783 ACTION_SET_IPV6_DST_IPV6_DST,
1788 static const enum index action_set_tp_src[] = {
1789 ACTION_SET_TP_SRC_TP_SRC,
1794 static const enum index action_set_tp_dst[] = {
1795 ACTION_SET_TP_DST_TP_DST,
1800 static const enum index action_set_ttl[] = {
1806 static const enum index action_jump[] = {
1812 static const enum index action_set_mac_dst[] = {
1813 ACTION_SET_MAC_DST_MAC_DST,
1818 static const enum index action_inc_tcp_seq[] = {
1819 ACTION_INC_TCP_SEQ_VALUE,
1824 static const enum index action_dec_tcp_seq[] = {
1825 ACTION_DEC_TCP_SEQ_VALUE,
1830 static const enum index action_inc_tcp_ack[] = {
1831 ACTION_INC_TCP_ACK_VALUE,
1836 static const enum index action_dec_tcp_ack[] = {
1837 ACTION_DEC_TCP_ACK_VALUE,
1842 static const enum index action_raw_encap[] = {
1843 ACTION_RAW_ENCAP_INDEX,
1848 static const enum index action_raw_decap[] = {
1849 ACTION_RAW_DECAP_INDEX,
1854 static const enum index action_set_tag[] = {
1855 ACTION_SET_TAG_DATA,
1856 ACTION_SET_TAG_INDEX,
1857 ACTION_SET_TAG_MASK,
1862 static const enum index action_set_meta[] = {
1863 ACTION_SET_META_DATA,
1864 ACTION_SET_META_MASK,
1869 static const enum index action_set_ipv4_dscp[] = {
1870 ACTION_SET_IPV4_DSCP_VALUE,
1875 static const enum index action_set_ipv6_dscp[] = {
1876 ACTION_SET_IPV6_DSCP_VALUE,
1881 static const enum index action_age[] = {
1888 static const enum index action_sample[] = {
1890 ACTION_SAMPLE_RATIO,
1891 ACTION_SAMPLE_INDEX,
1896 static const enum index next_action_sample[] = {
1909 static const enum index action_modify_field_dst[] = {
1910 ACTION_MODIFY_FIELD_DST_LEVEL,
1911 ACTION_MODIFY_FIELD_DST_OFFSET,
1912 ACTION_MODIFY_FIELD_SRC_TYPE,
1916 static const enum index action_modify_field_src[] = {
1917 ACTION_MODIFY_FIELD_SRC_LEVEL,
1918 ACTION_MODIFY_FIELD_SRC_OFFSET,
1919 ACTION_MODIFY_FIELD_SRC_VALUE,
1920 ACTION_MODIFY_FIELD_SRC_POINTER,
1921 ACTION_MODIFY_FIELD_WIDTH,
1925 static const enum index action_update_conntrack[] = {
1926 ACTION_CONNTRACK_UPDATE_DIR,
1927 ACTION_CONNTRACK_UPDATE_CTX,
1932 static const enum index action_port_representor[] = {
1933 ACTION_PORT_REPRESENTOR_PORT_ID,
1938 static const enum index action_represented_port[] = {
1939 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
1944 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1945 const char *, unsigned int,
1946 void *, unsigned int);
1947 static int parse_set_sample_action(struct context *, const struct token *,
1948 const char *, unsigned int,
1949 void *, unsigned int);
1950 static int parse_set_init(struct context *, const struct token *,
1951 const char *, unsigned int,
1952 void *, unsigned int);
1954 parse_flex_handle(struct context *, const struct token *,
1955 const char *, unsigned int, void *, unsigned int);
1956 static int parse_init(struct context *, const struct token *,
1957 const char *, unsigned int,
1958 void *, unsigned int);
1959 static int parse_vc(struct context *, const struct token *,
1960 const char *, unsigned int,
1961 void *, unsigned int);
1962 static int parse_vc_spec(struct context *, const struct token *,
1963 const char *, unsigned int, void *, unsigned int);
1964 static int parse_vc_conf(struct context *, const struct token *,
1965 const char *, unsigned int, void *, unsigned int);
1966 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1967 const char *, unsigned int,
1968 void *, unsigned int);
1969 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
1970 const char *, unsigned int,
1971 void *, unsigned int);
1972 static int parse_vc_action_meter_color_type(struct context *,
1973 const struct token *,
1974 const char *, unsigned int, void *,
1976 static int parse_vc_action_rss(struct context *, const struct token *,
1977 const char *, unsigned int, void *,
1979 static int parse_vc_action_rss_func(struct context *, const struct token *,
1980 const char *, unsigned int, void *,
1982 static int parse_vc_action_rss_type(struct context *, const struct token *,
1983 const char *, unsigned int, void *,
1985 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1986 const char *, unsigned int, void *,
1988 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1989 const char *, unsigned int, void *,
1991 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1992 const char *, unsigned int, void *,
1994 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1995 const char *, unsigned int, void *,
1997 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1998 const char *, unsigned int, void *,
2000 static int parse_vc_action_mplsogre_encap(struct context *,
2001 const struct token *, const char *,
2002 unsigned int, void *, unsigned int);
2003 static int parse_vc_action_mplsogre_decap(struct context *,
2004 const struct token *, const char *,
2005 unsigned int, void *, unsigned int);
2006 static int parse_vc_action_mplsoudp_encap(struct context *,
2007 const struct token *, const char *,
2008 unsigned int, void *, unsigned int);
2009 static int parse_vc_action_mplsoudp_decap(struct context *,
2010 const struct token *, const char *,
2011 unsigned int, void *, unsigned int);
2012 static int parse_vc_action_raw_encap(struct context *,
2013 const struct token *, const char *,
2014 unsigned int, void *, unsigned int);
2015 static int parse_vc_action_raw_decap(struct context *,
2016 const struct token *, const char *,
2017 unsigned int, void *, unsigned int);
2018 static int parse_vc_action_raw_encap_index(struct context *,
2019 const struct token *, const char *,
2020 unsigned int, void *, unsigned int);
2021 static int parse_vc_action_raw_decap_index(struct context *,
2022 const struct token *, const char *,
2023 unsigned int, void *, unsigned int);
2024 static int parse_vc_action_set_meta(struct context *ctx,
2025 const struct token *token, const char *str,
2026 unsigned int len, void *buf,
2028 static int parse_vc_action_sample(struct context *ctx,
2029 const struct token *token, const char *str,
2030 unsigned int len, void *buf,
2033 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2034 const char *str, unsigned int len, void *buf,
2037 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2038 const char *str, unsigned int len, void *buf,
2041 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2042 const char *str, unsigned int len, void *buf,
2045 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2046 const char *str, unsigned int len, void *buf,
2048 static int parse_destroy(struct context *, const struct token *,
2049 const char *, unsigned int,
2050 void *, unsigned int);
2051 static int parse_flush(struct context *, const struct token *,
2052 const char *, unsigned int,
2053 void *, unsigned int);
2054 static int parse_dump(struct context *, const struct token *,
2055 const char *, unsigned int,
2056 void *, unsigned int);
2057 static int parse_query(struct context *, const struct token *,
2058 const char *, unsigned int,
2059 void *, unsigned int);
2060 static int parse_action(struct context *, const struct token *,
2061 const char *, unsigned int,
2062 void *, unsigned int);
2063 static int parse_list(struct context *, const struct token *,
2064 const char *, unsigned int,
2065 void *, unsigned int);
2066 static int parse_aged(struct context *, const struct token *,
2067 const char *, unsigned int,
2068 void *, unsigned int);
2069 static int parse_isolate(struct context *, const struct token *,
2070 const char *, unsigned int,
2071 void *, unsigned int);
2072 static int parse_configure(struct context *, const struct token *,
2073 const char *, unsigned int,
2074 void *, unsigned int);
2075 static int parse_tunnel(struct context *, const struct token *,
2076 const char *, unsigned int,
2077 void *, unsigned int);
2078 static int parse_flex(struct context *, const struct token *,
2079 const char *, unsigned int, void *, unsigned int);
2080 static int parse_int(struct context *, const struct token *,
2081 const char *, unsigned int,
2082 void *, unsigned int);
2083 static int parse_prefix(struct context *, const struct token *,
2084 const char *, unsigned int,
2085 void *, unsigned int);
2086 static int parse_boolean(struct context *, const struct token *,
2087 const char *, unsigned int,
2088 void *, unsigned int);
2089 static int parse_string(struct context *, const struct token *,
2090 const char *, unsigned int,
2091 void *, unsigned int);
2092 static int parse_hex(struct context *ctx, const struct token *token,
2093 const char *str, unsigned int len,
2094 void *buf, unsigned int size);
2095 static int parse_string0(struct context *, const struct token *,
2096 const char *, unsigned int,
2097 void *, unsigned int);
2098 static int parse_mac_addr(struct context *, const struct token *,
2099 const char *, unsigned int,
2100 void *, unsigned int);
2101 static int parse_ipv4_addr(struct context *, const struct token *,
2102 const char *, unsigned int,
2103 void *, unsigned int);
2104 static int parse_ipv6_addr(struct context *, const struct token *,
2105 const char *, unsigned int,
2106 void *, unsigned int);
2107 static int parse_port(struct context *, const struct token *,
2108 const char *, unsigned int,
2109 void *, unsigned int);
2110 static int parse_ia(struct context *, const struct token *,
2111 const char *, unsigned int,
2112 void *, unsigned int);
2113 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2114 const char *str, unsigned int len,
2115 void *buf, unsigned int size);
2116 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2117 const char *str, unsigned int len, void *buf,
2119 static int parse_mp(struct context *, const struct token *,
2120 const char *, unsigned int,
2121 void *, unsigned int);
2122 static int comp_none(struct context *, const struct token *,
2123 unsigned int, char *, unsigned int);
2124 static int comp_boolean(struct context *, const struct token *,
2125 unsigned int, char *, unsigned int);
2126 static int comp_action(struct context *, const struct token *,
2127 unsigned int, char *, unsigned int);
2128 static int comp_port(struct context *, const struct token *,
2129 unsigned int, char *, unsigned int);
2130 static int comp_rule_id(struct context *, const struct token *,
2131 unsigned int, char *, unsigned int);
2132 static int comp_vc_action_rss_type(struct context *, const struct token *,
2133 unsigned int, char *, unsigned int);
2134 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2135 unsigned int, char *, unsigned int);
2136 static int comp_set_raw_index(struct context *, const struct token *,
2137 unsigned int, char *, unsigned int);
2138 static int comp_set_sample_index(struct context *, const struct token *,
2139 unsigned int, char *, unsigned int);
2140 static int comp_set_modify_field_op(struct context *, const struct token *,
2141 unsigned int, char *, unsigned int);
2142 static int comp_set_modify_field_id(struct context *, const struct token *,
2143 unsigned int, char *, unsigned int);
2145 /** Token definitions. */
2146 static const struct token token_list[] = {
2147 /* Special tokens. */
2150 .help = "null entry, abused as the entry point",
2151 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2156 .help = "command may end here",
2159 .name = "START_SET",
2160 .help = "null entry, abused as the entry point for set",
2161 .next = NEXT(NEXT_ENTRY(SET)),
2166 .help = "set command may end here",
2168 /* Common tokens. */
2169 [COMMON_INTEGER] = {
2172 .help = "integer value",
2176 [COMMON_UNSIGNED] = {
2177 .name = "{unsigned}",
2179 .help = "unsigned integer value",
2186 .help = "prefix length for bit-mask",
2187 .call = parse_prefix,
2190 [COMMON_BOOLEAN] = {
2191 .name = "{boolean}",
2193 .help = "any boolean value",
2194 .call = parse_boolean,
2195 .comp = comp_boolean,
2200 .help = "fixed string",
2201 .call = parse_string,
2207 .help = "fixed string",
2210 [COMMON_FILE_PATH] = {
2211 .name = "{file path}",
2213 .help = "file path",
2214 .call = parse_string0,
2217 [COMMON_MAC_ADDR] = {
2218 .name = "{MAC address}",
2220 .help = "standard MAC address notation",
2221 .call = parse_mac_addr,
2224 [COMMON_IPV4_ADDR] = {
2225 .name = "{IPv4 address}",
2226 .type = "IPV4 ADDRESS",
2227 .help = "standard IPv4 address notation",
2228 .call = parse_ipv4_addr,
2231 [COMMON_IPV6_ADDR] = {
2232 .name = "{IPv6 address}",
2233 .type = "IPV6 ADDRESS",
2234 .help = "standard IPv6 address notation",
2235 .call = parse_ipv6_addr,
2238 [COMMON_RULE_ID] = {
2239 .name = "{rule id}",
2241 .help = "rule identifier",
2243 .comp = comp_rule_id,
2245 [COMMON_PORT_ID] = {
2246 .name = "{port_id}",
2248 .help = "port identifier",
2252 [COMMON_GROUP_ID] = {
2253 .name = "{group_id}",
2255 .help = "group identifier",
2259 [COMMON_PRIORITY_LEVEL] = {
2262 .help = "priority level",
2266 [COMMON_INDIRECT_ACTION_ID] = {
2267 .name = "{indirect_action_id}",
2268 .type = "INDIRECT_ACTION_ID",
2269 .help = "indirect action id",
2273 [COMMON_POLICY_ID] = {
2274 .name = "{policy_id}",
2275 .type = "POLICY_ID",
2276 .help = "policy id",
2280 [COMMON_FLEX_TOKEN] = {
2281 .name = "{flex token}",
2282 .type = "flex token",
2283 .help = "flex token",
2287 [COMMON_FLEX_HANDLE] = {
2288 .name = "{flex handle}",
2289 .type = "FLEX HANDLE",
2290 .help = "fill flex item data",
2291 .call = parse_flex_handle,
2294 /* Top-level command. */
2297 .type = "{command} {port_id} [{arg} [...]]",
2298 .help = "manage ingress/egress flow rules",
2299 .next = NEXT(NEXT_ENTRY
2316 /* Top-level command. */
2319 .help = "get information about flow engine",
2320 .next = NEXT(NEXT_ENTRY(END),
2321 NEXT_ENTRY(COMMON_PORT_ID)),
2322 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2323 .call = parse_configure,
2325 /* Top-level command. */
2327 .name = "configure",
2328 .help = "configure flow engine",
2329 .next = NEXT(next_config_attr,
2330 NEXT_ENTRY(COMMON_PORT_ID)),
2331 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2332 .call = parse_configure,
2334 /* Configure arguments. */
2335 [CONFIG_QUEUES_NUMBER] = {
2336 .name = "queues_number",
2337 .help = "number of queues",
2338 .next = NEXT(next_config_attr,
2339 NEXT_ENTRY(COMMON_UNSIGNED)),
2340 .args = ARGS(ARGS_ENTRY(struct buffer,
2341 args.configure.nb_queue)),
2343 [CONFIG_QUEUES_SIZE] = {
2344 .name = "queues_size",
2345 .help = "number of elements in queues",
2346 .next = NEXT(next_config_attr,
2347 NEXT_ENTRY(COMMON_UNSIGNED)),
2348 .args = ARGS(ARGS_ENTRY(struct buffer,
2349 args.configure.queue_attr.size)),
2351 [CONFIG_COUNTERS_NUMBER] = {
2352 .name = "counters_number",
2353 .help = "number of counters",
2354 .next = NEXT(next_config_attr,
2355 NEXT_ENTRY(COMMON_UNSIGNED)),
2356 .args = ARGS(ARGS_ENTRY(struct buffer,
2357 args.configure.port_attr.nb_counters)),
2359 [CONFIG_AGING_OBJECTS_NUMBER] = {
2360 .name = "aging_counters_number",
2361 .help = "number of aging objects",
2362 .next = NEXT(next_config_attr,
2363 NEXT_ENTRY(COMMON_UNSIGNED)),
2364 .args = ARGS(ARGS_ENTRY(struct buffer,
2365 args.configure.port_attr.nb_aging_objects)),
2367 [CONFIG_METERS_NUMBER] = {
2368 .name = "meters_number",
2369 .help = "number of meters",
2370 .next = NEXT(next_config_attr,
2371 NEXT_ENTRY(COMMON_UNSIGNED)),
2372 .args = ARGS(ARGS_ENTRY(struct buffer,
2373 args.configure.port_attr.nb_meters)),
2375 /* Top-level command. */
2376 [INDIRECT_ACTION] = {
2377 .name = "indirect_action",
2378 .type = "{command} {port_id} [{arg} [...]]",
2379 .help = "manage indirect actions",
2380 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2381 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2384 /* Sub-level commands. */
2385 [INDIRECT_ACTION_CREATE] = {
2387 .help = "create indirect action",
2388 .next = NEXT(next_ia_create_attr),
2391 [INDIRECT_ACTION_UPDATE] = {
2393 .help = "update indirect action",
2394 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2395 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2396 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2399 [INDIRECT_ACTION_DESTROY] = {
2401 .help = "destroy indirect action",
2402 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2403 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2404 .call = parse_ia_destroy,
2406 [INDIRECT_ACTION_QUERY] = {
2408 .help = "query indirect action",
2409 .next = NEXT(NEXT_ENTRY(END),
2410 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2411 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2416 .help = "check whether a flow rule can be created",
2417 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2418 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2423 .help = "create a flow rule",
2424 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2425 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2430 .help = "destroy specific flow rules",
2431 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2432 NEXT_ENTRY(COMMON_PORT_ID)),
2433 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2434 .call = parse_destroy,
2438 .help = "destroy all flow rules",
2439 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2440 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2441 .call = parse_flush,
2445 .help = "dump single/all flow rules to file",
2446 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2447 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2452 .help = "query an existing flow rule",
2453 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
2454 NEXT_ENTRY(COMMON_RULE_ID),
2455 NEXT_ENTRY(COMMON_PORT_ID)),
2456 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
2457 ARGS_ENTRY(struct buffer, args.query.rule),
2458 ARGS_ENTRY(struct buffer, port)),
2459 .call = parse_query,
2463 .help = "list existing flow rules",
2464 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2465 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2470 .help = "list and destroy aged flows",
2471 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2472 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2477 .help = "restrict ingress traffic to the defined flow rules",
2478 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
2479 NEXT_ENTRY(COMMON_PORT_ID)),
2480 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
2481 ARGS_ENTRY(struct buffer, port)),
2482 .call = parse_isolate,
2485 .name = "flex_item",
2486 .help = "flex item API",
2487 .next = NEXT(next_flex_item),
2490 [FLEX_ITEM_INIT] = {
2492 .help = "flex item init",
2493 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
2494 ARGS_ENTRY(struct buffer, port)),
2495 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
2496 NEXT_ENTRY(COMMON_PORT_ID)),
2499 [FLEX_ITEM_CREATE] = {
2501 .help = "flex item create",
2502 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
2503 ARGS_ENTRY(struct buffer, args.flex.token),
2504 ARGS_ENTRY(struct buffer, port)),
2505 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
2506 NEXT_ENTRY(COMMON_FLEX_TOKEN),
2507 NEXT_ENTRY(COMMON_PORT_ID)),
2510 [FLEX_ITEM_DESTROY] = {
2512 .help = "flex item destroy",
2513 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
2514 ARGS_ENTRY(struct buffer, port)),
2515 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
2516 NEXT_ENTRY(COMMON_PORT_ID)),
2521 .help = "new tunnel API",
2522 .next = NEXT(NEXT_ENTRY
2523 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
2524 .call = parse_tunnel,
2526 /* Tunnel arguments. */
2529 .help = "create new tunnel object",
2530 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
2531 NEXT_ENTRY(COMMON_PORT_ID)),
2532 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2533 .call = parse_tunnel,
2535 [TUNNEL_CREATE_TYPE] = {
2537 .help = "create new tunnel",
2538 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
2539 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
2540 .call = parse_tunnel,
2542 [TUNNEL_DESTROY] = {
2544 .help = "destroy tunnel",
2545 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
2546 NEXT_ENTRY(COMMON_PORT_ID)),
2547 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2548 .call = parse_tunnel,
2550 [TUNNEL_DESTROY_ID] = {
2552 .help = "tunnel identifier to destroy",
2553 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
2554 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2555 .call = parse_tunnel,
2559 .help = "list existing tunnels",
2560 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2561 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2562 .call = parse_tunnel,
2564 /* Destroy arguments. */
2567 .help = "specify a rule identifier",
2568 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2569 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
2570 .call = parse_destroy,
2572 /* Dump arguments. */
2576 .next = NEXT(next_dump_attr),
2577 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
2582 .help = "dump one rule",
2583 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2584 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
2585 ARGS_ENTRY(struct buffer, args.dump.rule)),
2588 /* Query arguments. */
2592 .help = "action to query, must be part of the rule",
2593 .call = parse_action,
2594 .comp = comp_action,
2596 /* List arguments. */
2599 .help = "specify a group",
2600 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2601 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
2606 .help = "specify aged flows need be destroyed",
2610 /* Validate/create attributes. */
2613 .help = "specify a group",
2614 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2615 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
2620 .help = "specify a priority level",
2621 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2622 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
2627 .help = "affect rule to ingress",
2628 .next = NEXT(next_vc_attr),
2633 .help = "affect rule to egress",
2634 .next = NEXT(next_vc_attr),
2639 .help = "apply rule directly to endpoints found in pattern",
2640 .next = NEXT(next_vc_attr),
2644 .name = "tunnel_set",
2645 .help = "tunnel steer rule",
2646 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2647 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2650 [VC_TUNNEL_MATCH] = {
2651 .name = "tunnel_match",
2652 .help = "tunnel match rule",
2653 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2654 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2657 /* Validate/create pattern. */
2660 .help = "submit a list of pattern items",
2661 .next = NEXT(next_item),
2666 .help = "match value perfectly (with full bit-mask)",
2667 .call = parse_vc_spec,
2669 [ITEM_PARAM_SPEC] = {
2671 .help = "match value according to configured bit-mask",
2672 .call = parse_vc_spec,
2674 [ITEM_PARAM_LAST] = {
2676 .help = "specify upper bound to establish a range",
2677 .call = parse_vc_spec,
2679 [ITEM_PARAM_MASK] = {
2681 .help = "specify bit-mask with relevant bits set to one",
2682 .call = parse_vc_spec,
2684 [ITEM_PARAM_PREFIX] = {
2686 .help = "generate bit-mask from a prefix length",
2687 .call = parse_vc_spec,
2691 .help = "specify next pattern item",
2692 .next = NEXT(next_item),
2696 .help = "end list of pattern items",
2697 .priv = PRIV_ITEM(END, 0),
2698 .next = NEXT(NEXT_ENTRY(ACTIONS)),
2703 .help = "no-op pattern item",
2704 .priv = PRIV_ITEM(VOID, 0),
2705 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2710 .help = "perform actions when pattern does not match",
2711 .priv = PRIV_ITEM(INVERT, 0),
2712 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2717 .help = "match any protocol for the current layer",
2718 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
2719 .next = NEXT(item_any),
2724 .help = "number of layers covered",
2725 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2726 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
2730 .help = "match traffic from/to the physical function",
2731 .priv = PRIV_ITEM(PF, 0),
2732 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2737 .help = "match traffic from/to a virtual function ID",
2738 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
2739 .next = NEXT(item_vf),
2745 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2746 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
2750 .help = "match traffic from/to a specific physical port",
2751 .priv = PRIV_ITEM(PHY_PORT,
2752 sizeof(struct rte_flow_item_phy_port)),
2753 .next = NEXT(item_phy_port),
2756 [ITEM_PHY_PORT_INDEX] = {
2758 .help = "physical port index",
2759 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
2761 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
2765 .help = "match traffic from/to a given DPDK port ID",
2766 .priv = PRIV_ITEM(PORT_ID,
2767 sizeof(struct rte_flow_item_port_id)),
2768 .next = NEXT(item_port_id),
2771 [ITEM_PORT_ID_ID] = {
2773 .help = "DPDK port ID",
2774 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
2776 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
2780 .help = "match traffic against value set in previously matched rule",
2781 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
2782 .next = NEXT(item_mark),
2787 .help = "Integer value to match against",
2788 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
2790 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
2794 .help = "match an arbitrary byte string",
2795 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
2796 .next = NEXT(item_raw),
2799 [ITEM_RAW_RELATIVE] = {
2801 .help = "look for pattern after the previous item",
2802 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2803 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2806 [ITEM_RAW_SEARCH] = {
2808 .help = "search pattern from offset (see also limit)",
2809 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2810 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2813 [ITEM_RAW_OFFSET] = {
2815 .help = "absolute or relative offset for pattern",
2816 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
2817 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
2819 [ITEM_RAW_LIMIT] = {
2821 .help = "search area limit for start of pattern",
2822 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2823 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
2825 [ITEM_RAW_PATTERN] = {
2827 .help = "byte string to look for",
2828 .next = NEXT(item_raw,
2829 NEXT_ENTRY(COMMON_STRING),
2830 NEXT_ENTRY(ITEM_PARAM_IS,
2833 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2834 ARGS_ENTRY(struct rte_flow_item_raw, length),
2835 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2836 ITEM_RAW_PATTERN_SIZE)),
2838 [ITEM_RAW_PATTERN_HEX] = {
2839 .name = "pattern_hex",
2840 .help = "hex string to look for",
2841 .next = NEXT(item_raw,
2842 NEXT_ENTRY(COMMON_HEX),
2843 NEXT_ENTRY(ITEM_PARAM_IS,
2846 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2847 ARGS_ENTRY(struct rte_flow_item_raw, length),
2848 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2849 ITEM_RAW_PATTERN_SIZE)),
2853 .help = "match Ethernet header",
2854 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
2855 .next = NEXT(item_eth),
2860 .help = "destination MAC",
2861 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2862 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
2866 .help = "source MAC",
2867 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2868 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
2872 .help = "EtherType",
2873 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2874 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
2876 [ITEM_ETH_HAS_VLAN] = {
2878 .help = "packet header contains VLAN",
2879 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2880 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
2885 .help = "match 802.1Q/ad VLAN tag",
2886 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
2887 .next = NEXT(item_vlan),
2892 .help = "tag control information",
2893 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2895 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
2899 .help = "priority code point",
2900 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2902 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2907 .help = "drop eligible indicator",
2908 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2910 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2915 .help = "VLAN identifier",
2916 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2918 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2921 [ITEM_VLAN_INNER_TYPE] = {
2922 .name = "inner_type",
2923 .help = "inner EtherType",
2924 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2926 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2929 [ITEM_VLAN_HAS_MORE_VLAN] = {
2930 .name = "has_more_vlan",
2931 .help = "packet header contains another VLAN",
2932 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2934 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
2939 .help = "match IPv4 header",
2940 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
2941 .next = NEXT(item_ipv4),
2944 [ITEM_IPV4_VER_IHL] = {
2945 .name = "version_ihl",
2946 .help = "match header length",
2947 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2949 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
2954 .help = "type of service",
2955 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2957 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2958 hdr.type_of_service)),
2961 .name = "packet_id",
2962 .help = "fragment packet id",
2963 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2965 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2968 [ITEM_IPV4_FRAGMENT_OFFSET] = {
2969 .name = "fragment_offset",
2970 .help = "fragmentation flags and fragment offset",
2971 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2973 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2974 hdr.fragment_offset)),
2978 .help = "time to live",
2979 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2981 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2984 [ITEM_IPV4_PROTO] = {
2986 .help = "next protocol ID",
2987 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2989 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2990 hdr.next_proto_id)),
2994 .help = "source address",
2995 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2997 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3002 .help = "destination address",
3003 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3005 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
3010 .help = "match IPv6 header",
3011 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
3012 .next = NEXT(item_ipv6),
3017 .help = "traffic class",
3018 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3020 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3022 "\x0f\xf0\x00\x00")),
3024 [ITEM_IPV6_FLOW] = {
3026 .help = "flow label",
3027 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3029 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
3031 "\x00\x0f\xff\xff")),
3033 [ITEM_IPV6_PROTO] = {
3035 .help = "protocol (next header)",
3036 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3038 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3043 .help = "hop limit",
3044 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3046 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3051 .help = "source address",
3052 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3054 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3059 .help = "destination address",
3060 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
3062 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
3065 [ITEM_IPV6_HAS_FRAG_EXT] = {
3066 .name = "has_frag_ext",
3067 .help = "fragment packet attribute",
3068 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
3070 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
3075 .help = "match ICMP header",
3076 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
3077 .next = NEXT(item_icmp),
3080 [ITEM_ICMP_TYPE] = {
3082 .help = "ICMP packet type",
3083 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3085 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3088 [ITEM_ICMP_CODE] = {
3090 .help = "ICMP packet code",
3091 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3093 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3096 [ITEM_ICMP_IDENT] = {
3098 .help = "ICMP packet identifier",
3099 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3101 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3106 .help = "ICMP packet sequence number",
3107 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
3109 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
3114 .help = "match UDP header",
3115 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
3116 .next = NEXT(item_udp),
3121 .help = "UDP source port",
3122 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
3124 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3129 .help = "UDP destination port",
3130 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3131 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
3136 .help = "match TCP header",
3137 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
3138 .next = NEXT(item_tcp),
3143 .help = "TCP source port",
3144 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3145 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3150 .help = "TCP destination port",
3151 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3152 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3155 [ITEM_TCP_FLAGS] = {
3157 .help = "TCP flags",
3158 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3159 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
3164 .help = "match SCTP header",
3165 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
3166 .next = NEXT(item_sctp),
3171 .help = "SCTP source port",
3172 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3174 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3179 .help = "SCTP destination port",
3180 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3182 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3187 .help = "validation tag",
3188 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3190 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3193 [ITEM_SCTP_CKSUM] = {
3196 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
3198 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
3203 .help = "match VXLAN header",
3204 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
3205 .next = NEXT(item_vxlan),
3208 [ITEM_VXLAN_VNI] = {
3210 .help = "VXLAN identifier",
3211 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3213 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
3215 [ITEM_VXLAN_LAST_RSVD] = {
3216 .name = "last_rsvd",
3217 .help = "VXLAN last reserved bits",
3218 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
3220 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
3225 .help = "match E-Tag header",
3226 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
3227 .next = NEXT(item_e_tag),
3230 [ITEM_E_TAG_GRP_ECID_B] = {
3231 .name = "grp_ecid_b",
3232 .help = "GRP and E-CID base",
3233 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3235 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
3241 .help = "match NVGRE header",
3242 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
3243 .next = NEXT(item_nvgre),
3246 [ITEM_NVGRE_TNI] = {
3248 .help = "virtual subnet ID",
3249 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
3251 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
3255 .help = "match MPLS header",
3256 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
3257 .next = NEXT(item_mpls),
3260 [ITEM_MPLS_LABEL] = {
3262 .help = "MPLS label",
3263 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3265 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3271 .help = "MPLS Traffic Class",
3272 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3274 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3280 .help = "MPLS Bottom-of-Stack",
3281 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
3283 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
3289 .help = "match GRE header",
3290 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
3291 .next = NEXT(item_gre),
3294 [ITEM_GRE_PROTO] = {
3296 .help = "GRE protocol type",
3297 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3299 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3302 [ITEM_GRE_C_RSVD0_VER] = {
3303 .name = "c_rsvd0_ver",
3305 "checksum (1b), undefined (1b), key bit (1b),"
3306 " sequence number (1b), reserved 0 (9b),"
3308 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
3310 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
3313 [ITEM_GRE_C_BIT] = {
3315 .help = "checksum bit (C)",
3316 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
3318 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3320 "\x80\x00\x00\x00")),
3322 [ITEM_GRE_S_BIT] = {
3324 .help = "sequence number bit (S)",
3325 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3326 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3328 "\x10\x00\x00\x00")),
3330 [ITEM_GRE_K_BIT] = {
3332 .help = "key bit (K)",
3333 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3334 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3336 "\x20\x00\x00\x00")),
3340 .help = "fuzzy pattern match, expect faster than default",
3341 .priv = PRIV_ITEM(FUZZY,
3342 sizeof(struct rte_flow_item_fuzzy)),
3343 .next = NEXT(item_fuzzy),
3346 [ITEM_FUZZY_THRESH] = {
3348 .help = "match accuracy threshold",
3349 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
3351 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
3356 .help = "match GTP header",
3357 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
3358 .next = NEXT(item_gtp),
3361 [ITEM_GTP_FLAGS] = {
3362 .name = "v_pt_rsv_flags",
3363 .help = "GTP flags",
3364 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3365 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3368 [ITEM_GTP_MSG_TYPE] = {
3370 .help = "GTP message type",
3371 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3372 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3376 .help = "tunnel endpoint identifier",
3377 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3378 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3382 .help = "match GTP header",
3383 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3384 .next = NEXT(item_gtp),
3389 .help = "match GTP header",
3390 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3391 .next = NEXT(item_gtp),
3396 .help = "match GENEVE header",
3397 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3398 .next = NEXT(item_geneve),
3401 [ITEM_GENEVE_VNI] = {
3403 .help = "virtual network identifier",
3404 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3406 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3408 [ITEM_GENEVE_PROTO] = {
3410 .help = "GENEVE protocol type",
3411 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3413 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3416 [ITEM_GENEVE_OPTLEN] = {
3418 .help = "GENEVE options length in dwords",
3419 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3421 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3422 ver_opt_len_o_c_rsvd0,
3425 [ITEM_VXLAN_GPE] = {
3426 .name = "vxlan-gpe",
3427 .help = "match VXLAN-GPE header",
3428 .priv = PRIV_ITEM(VXLAN_GPE,
3429 sizeof(struct rte_flow_item_vxlan_gpe)),
3430 .next = NEXT(item_vxlan_gpe),
3433 [ITEM_VXLAN_GPE_VNI] = {
3435 .help = "VXLAN-GPE identifier",
3436 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3438 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
3441 [ITEM_ARP_ETH_IPV4] = {
3442 .name = "arp_eth_ipv4",
3443 .help = "match ARP header for Ethernet/IPv4",
3444 .priv = PRIV_ITEM(ARP_ETH_IPV4,
3445 sizeof(struct rte_flow_item_arp_eth_ipv4)),
3446 .next = NEXT(item_arp_eth_ipv4),
3449 [ITEM_ARP_ETH_IPV4_SHA] = {
3451 .help = "sender hardware address",
3452 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3454 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3457 [ITEM_ARP_ETH_IPV4_SPA] = {
3459 .help = "sender IPv4 address",
3460 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3462 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3465 [ITEM_ARP_ETH_IPV4_THA] = {
3467 .help = "target hardware address",
3468 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3470 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3473 [ITEM_ARP_ETH_IPV4_TPA] = {
3475 .help = "target IPv4 address",
3476 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3478 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3483 .help = "match presence of any IPv6 extension header",
3484 .priv = PRIV_ITEM(IPV6_EXT,
3485 sizeof(struct rte_flow_item_ipv6_ext)),
3486 .next = NEXT(item_ipv6_ext),
3489 [ITEM_IPV6_EXT_NEXT_HDR] = {
3491 .help = "next header",
3492 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3494 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
3497 [ITEM_IPV6_FRAG_EXT] = {
3498 .name = "ipv6_frag_ext",
3499 .help = "match presence of IPv6 fragment extension header",
3500 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
3501 sizeof(struct rte_flow_item_ipv6_frag_ext)),
3502 .next = NEXT(item_ipv6_frag_ext),
3505 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
3507 .help = "next header",
3508 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3510 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
3513 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
3514 .name = "frag_data",
3515 .help = "fragment flags and offset",
3516 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3518 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3521 [ITEM_IPV6_FRAG_EXT_ID] = {
3522 .name = "packet_id",
3523 .help = "fragment packet id",
3524 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3526 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3531 .help = "match any ICMPv6 header",
3532 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
3533 .next = NEXT(item_icmp6),
3536 [ITEM_ICMP6_TYPE] = {
3538 .help = "ICMPv6 type",
3539 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3541 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3544 [ITEM_ICMP6_CODE] = {
3546 .help = "ICMPv6 code",
3547 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3549 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3552 [ITEM_ICMP6_ND_NS] = {
3553 .name = "icmp6_nd_ns",
3554 .help = "match ICMPv6 neighbor discovery solicitation",
3555 .priv = PRIV_ITEM(ICMP6_ND_NS,
3556 sizeof(struct rte_flow_item_icmp6_nd_ns)),
3557 .next = NEXT(item_icmp6_nd_ns),
3560 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
3561 .name = "target_addr",
3562 .help = "target address",
3563 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
3565 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
3568 [ITEM_ICMP6_ND_NA] = {
3569 .name = "icmp6_nd_na",
3570 .help = "match ICMPv6 neighbor discovery advertisement",
3571 .priv = PRIV_ITEM(ICMP6_ND_NA,
3572 sizeof(struct rte_flow_item_icmp6_nd_na)),
3573 .next = NEXT(item_icmp6_nd_na),
3576 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
3577 .name = "target_addr",
3578 .help = "target address",
3579 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
3581 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
3584 [ITEM_ICMP6_ND_OPT] = {
3585 .name = "icmp6_nd_opt",
3586 .help = "match presence of any ICMPv6 neighbor discovery"
3588 .priv = PRIV_ITEM(ICMP6_ND_OPT,
3589 sizeof(struct rte_flow_item_icmp6_nd_opt)),
3590 .next = NEXT(item_icmp6_nd_opt),
3593 [ITEM_ICMP6_ND_OPT_TYPE] = {
3595 .help = "ND option type",
3596 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3598 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
3601 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
3602 .name = "icmp6_nd_opt_sla_eth",
3603 .help = "match ICMPv6 neighbor discovery source Ethernet"
3604 " link-layer address option",
3606 (ICMP6_ND_OPT_SLA_ETH,
3607 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
3608 .next = NEXT(item_icmp6_nd_opt_sla_eth),
3611 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
3613 .help = "source Ethernet LLA",
3614 .next = NEXT(item_icmp6_nd_opt_sla_eth,
3615 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3616 .args = ARGS(ARGS_ENTRY_HTON
3617 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
3619 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
3620 .name = "icmp6_nd_opt_tla_eth",
3621 .help = "match ICMPv6 neighbor discovery target Ethernet"
3622 " link-layer address option",
3624 (ICMP6_ND_OPT_TLA_ETH,
3625 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
3626 .next = NEXT(item_icmp6_nd_opt_tla_eth),
3629 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
3631 .help = "target Ethernet LLA",
3632 .next = NEXT(item_icmp6_nd_opt_tla_eth,
3633 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3634 .args = ARGS(ARGS_ENTRY_HTON
3635 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
3639 .help = "match metadata header",
3640 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
3641 .next = NEXT(item_meta),
3644 [ITEM_META_DATA] = {
3646 .help = "metadata value",
3647 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
3649 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
3650 data, "\xff\xff\xff\xff")),
3654 .help = "match GRE key",
3655 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
3656 .next = NEXT(item_gre_key),
3659 [ITEM_GRE_KEY_VALUE] = {
3661 .help = "key value",
3662 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
3664 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3666 [ITEM_GRE_OPTION] = {
3667 .name = "gre_option",
3668 .help = "match GRE optional fields",
3669 .priv = PRIV_ITEM(GRE_OPTION,
3670 sizeof(struct rte_flow_item_gre_opt)),
3671 .next = NEXT(item_gre_option),
3674 [ITEM_GRE_OPTION_CHECKSUM] = {
3676 .help = "match GRE checksum",
3677 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
3679 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
3680 checksum_rsvd.checksum)),
3682 [ITEM_GRE_OPTION_KEY] = {
3684 .help = "match GRE key",
3685 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
3687 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
3690 [ITEM_GRE_OPTION_SEQUENCE] = {
3692 .help = "match GRE sequence",
3693 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
3695 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
3696 sequence.sequence)),
3700 .help = "match GTP extension header with type 0x85",
3701 .priv = PRIV_ITEM(GTP_PSC,
3702 sizeof(struct rte_flow_item_gtp_psc)),
3703 .next = NEXT(item_gtp_psc),
3706 [ITEM_GTP_PSC_QFI] = {
3708 .help = "QoS flow identifier",
3709 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3711 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3714 [ITEM_GTP_PSC_PDU_T] = {
3717 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3719 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3724 .help = "match PPPoE session header",
3725 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
3726 .next = NEXT(item_pppoes),
3731 .help = "match PPPoE discovery header",
3732 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
3733 .next = NEXT(item_pppoed),
3736 [ITEM_PPPOE_SEID] = {
3738 .help = "session identifier",
3739 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
3741 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
3744 [ITEM_PPPOE_PROTO_ID] = {
3745 .name = "pppoe_proto_id",
3746 .help = "match PPPoE session protocol identifier",
3747 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
3748 sizeof(struct rte_flow_item_pppoe_proto_id)),
3749 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
3751 .args = ARGS(ARGS_ENTRY_HTON
3752 (struct rte_flow_item_pppoe_proto_id, proto_id)),
3757 .help = "matches higig2 header",
3758 .priv = PRIV_ITEM(HIGIG2,
3759 sizeof(struct rte_flow_item_higig2_hdr)),
3760 .next = NEXT(item_higig2),
3763 [ITEM_HIGIG2_CLASSIFICATION] = {
3764 .name = "classification",
3765 .help = "matches classification of higig2 header",
3766 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3768 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3769 hdr.ppt1.classification)),
3771 [ITEM_HIGIG2_VID] = {
3773 .help = "matches vid of higig2 header",
3774 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3776 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3781 .help = "match tag value",
3782 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
3783 .next = NEXT(item_tag),
3788 .help = "tag value to match",
3789 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3790 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
3792 [ITEM_TAG_INDEX] = {
3794 .help = "index of tag array to match",
3795 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3796 NEXT_ENTRY(ITEM_PARAM_IS)),
3797 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
3799 [ITEM_L2TPV3OIP] = {
3800 .name = "l2tpv3oip",
3801 .help = "match L2TPv3 over IP header",
3802 .priv = PRIV_ITEM(L2TPV3OIP,
3803 sizeof(struct rte_flow_item_l2tpv3oip)),
3804 .next = NEXT(item_l2tpv3oip),
3807 [ITEM_L2TPV3OIP_SESSION_ID] = {
3808 .name = "session_id",
3809 .help = "session identifier",
3810 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
3812 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
3817 .help = "match ESP header",
3818 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
3819 .next = NEXT(item_esp),
3824 .help = "security policy index",
3825 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3826 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
3831 .help = "match AH header",
3832 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
3833 .next = NEXT(item_ah),
3838 .help = "security parameters index",
3839 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3840 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
3844 .help = "match pfcp header",
3845 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
3846 .next = NEXT(item_pfcp),
3849 [ITEM_PFCP_S_FIELD] = {
3852 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3854 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
3857 [ITEM_PFCP_SEID] = {
3859 .help = "session endpoint identifier",
3860 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3862 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
3866 .help = "match eCPRI header",
3867 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
3868 .next = NEXT(item_ecpri),
3871 [ITEM_ECPRI_COMMON] = {
3873 .help = "eCPRI common header",
3874 .next = NEXT(item_ecpri_common),
3876 [ITEM_ECPRI_COMMON_TYPE] = {
3878 .help = "type of common header",
3879 .next = NEXT(item_ecpri_common_type),
3880 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
3882 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
3884 .help = "Type #0: IQ Data",
3885 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3887 .call = parse_vc_item_ecpri_type,
3889 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
3891 .help = "Physical Channel ID",
3892 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3893 ITEM_ECPRI_COMMON, ITEM_NEXT),
3894 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3895 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3898 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
3900 .help = "Type #2: Real-Time Control Data",
3901 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3903 .call = parse_vc_item_ecpri_type,
3905 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
3907 .help = "Real-Time Control Data ID",
3908 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3909 ITEM_ECPRI_COMMON, ITEM_NEXT),
3910 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3911 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3914 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
3915 .name = "delay_measure",
3916 .help = "Type #5: One-Way Delay Measurement",
3917 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3919 .call = parse_vc_item_ecpri_type,
3921 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
3923 .help = "Measurement ID",
3924 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3925 ITEM_ECPRI_COMMON, ITEM_NEXT),
3926 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3927 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3930 [ITEM_GENEVE_OPT] = {
3931 .name = "geneve-opt",
3932 .help = "GENEVE header option",
3933 .priv = PRIV_ITEM(GENEVE_OPT,
3934 sizeof(struct rte_flow_item_geneve_opt) +
3935 ITEM_GENEVE_OPT_DATA_SIZE),
3936 .next = NEXT(item_geneve_opt),
3939 [ITEM_GENEVE_OPT_CLASS] = {
3941 .help = "GENEVE option class",
3942 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3944 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
3947 [ITEM_GENEVE_OPT_TYPE] = {
3949 .help = "GENEVE option type",
3950 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3952 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
3955 [ITEM_GENEVE_OPT_LENGTH] = {
3957 .help = "GENEVE option data length (in 32b words)",
3958 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3960 .args = ARGS(ARGS_ENTRY_BOUNDED(
3961 struct rte_flow_item_geneve_opt, option_len,
3964 [ITEM_GENEVE_OPT_DATA] = {
3966 .help = "GENEVE option data pattern",
3967 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
3969 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
3970 ARGS_ENTRY_ARB(0, 0),
3972 (sizeof(struct rte_flow_item_geneve_opt),
3973 ITEM_GENEVE_OPT_DATA_SIZE)),
3975 [ITEM_INTEGRITY] = {
3976 .name = "integrity",
3977 .help = "match packet integrity",
3978 .priv = PRIV_ITEM(INTEGRITY,
3979 sizeof(struct rte_flow_item_integrity)),
3980 .next = NEXT(item_integrity),
3983 [ITEM_INTEGRITY_LEVEL] = {
3985 .help = "integrity level",
3986 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3988 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
3990 [ITEM_INTEGRITY_VALUE] = {
3992 .help = "integrity value",
3993 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3995 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
3997 [ITEM_CONNTRACK] = {
3998 .name = "conntrack",
3999 .help = "conntrack state",
4000 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
4002 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
4004 [ITEM_PORT_REPRESENTOR] = {
4005 .name = "port_representor",
4006 .help = "match traffic entering the embedded switch from the given ethdev",
4007 .priv = PRIV_ITEM(PORT_REPRESENTOR,
4008 sizeof(struct rte_flow_item_ethdev)),
4009 .next = NEXT(item_port_representor),
4012 [ITEM_PORT_REPRESENTOR_PORT_ID] = {
4014 .help = "ethdev port ID",
4015 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
4017 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4019 [ITEM_REPRESENTED_PORT] = {
4020 .name = "represented_port",
4021 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
4022 .priv = PRIV_ITEM(REPRESENTED_PORT,
4023 sizeof(struct rte_flow_item_ethdev)),
4024 .next = NEXT(item_represented_port),
4027 [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
4028 .name = "ethdev_port_id",
4029 .help = "ethdev port ID",
4030 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
4032 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
4036 .help = "match flex header",
4037 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
4038 .next = NEXT(item_flex),
4041 [ITEM_FLEX_ITEM_HANDLE] = {
4043 .help = "flex item handle",
4044 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4045 NEXT_ENTRY(ITEM_PARAM_IS)),
4046 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
4048 [ITEM_FLEX_PATTERN_HANDLE] = {
4050 .help = "flex pattern handle",
4051 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
4052 NEXT_ENTRY(ITEM_PARAM_IS)),
4053 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
4057 .help = "match L2TPv2 header",
4058 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
4059 .next = NEXT(item_l2tpv2),
4062 [ITEM_L2TPV2_TYPE] = {
4064 .help = "type of l2tpv2",
4065 .next = NEXT(item_l2tpv2_type),
4066 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
4068 [ITEM_L2TPV2_TYPE_DATA] = {
4070 .help = "Type #7: data message without any options",
4071 .next = NEXT(item_l2tpv2_type_data),
4072 .call = parse_vc_item_l2tpv2_type,
4074 [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
4075 .name = "tunnel_id",
4076 .help = "tunnel identifier",
4077 .next = NEXT(item_l2tpv2_type_data,
4078 NEXT_ENTRY(COMMON_UNSIGNED),
4080 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4081 hdr.type7.tunnel_id)),
4083 [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
4084 .name = "session_id",
4085 .help = "session identifier",
4086 .next = NEXT(item_l2tpv2_type_data,
4087 NEXT_ENTRY(COMMON_UNSIGNED),
4089 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4090 hdr.type7.session_id)),
4092 [ITEM_L2TPV2_TYPE_DATA_L] = {
4094 .help = "Type #6: data message with length option",
4095 .next = NEXT(item_l2tpv2_type_data_l),
4096 .call = parse_vc_item_l2tpv2_type,
4098 [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
4100 .help = "message length",
4101 .next = NEXT(item_l2tpv2_type_data_l,
4102 NEXT_ENTRY(COMMON_UNSIGNED),
4104 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4107 [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
4108 .name = "tunnel_id",
4109 .help = "tunnel identifier",
4110 .next = NEXT(item_l2tpv2_type_data_l,
4111 NEXT_ENTRY(COMMON_UNSIGNED),
4113 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4114 hdr.type6.tunnel_id)),
4116 [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
4117 .name = "session_id",
4118 .help = "session identifier",
4119 .next = NEXT(item_l2tpv2_type_data_l,
4120 NEXT_ENTRY(COMMON_UNSIGNED),
4122 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4123 hdr.type6.session_id)),
4125 [ITEM_L2TPV2_TYPE_DATA_S] = {
4127 .help = "Type #5: data message with ns, nr option",
4128 .next = NEXT(item_l2tpv2_type_data_s),
4129 .call = parse_vc_item_l2tpv2_type,
4131 [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
4132 .name = "tunnel_id",
4133 .help = "tunnel identifier",
4134 .next = NEXT(item_l2tpv2_type_data_s,
4135 NEXT_ENTRY(COMMON_UNSIGNED),
4137 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4138 hdr.type5.tunnel_id)),
4140 [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
4141 .name = "session_id",
4142 .help = "session identifier",
4143 .next = NEXT(item_l2tpv2_type_data_s,
4144 NEXT_ENTRY(COMMON_UNSIGNED),
4146 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4147 hdr.type5.session_id)),
4149 [ITEM_L2TPV2_MSG_DATA_S_NS] = {
4151 .help = "sequence number for message",
4152 .next = NEXT(item_l2tpv2_type_data_s,
4153 NEXT_ENTRY(COMMON_UNSIGNED),
4155 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4158 [ITEM_L2TPV2_MSG_DATA_S_NR] = {
4160 .help = "sequence number for next receive message",
4161 .next = NEXT(item_l2tpv2_type_data_s,
4162 NEXT_ENTRY(COMMON_UNSIGNED),
4164 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4167 [ITEM_L2TPV2_TYPE_DATA_O] = {
4169 .help = "Type #4: data message with offset option",
4170 .next = NEXT(item_l2tpv2_type_data_o),
4171 .call = parse_vc_item_l2tpv2_type,
4173 [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
4174 .name = "tunnel_id",
4175 .help = "tunnel identifier",
4176 .next = NEXT(item_l2tpv2_type_data_o,
4177 NEXT_ENTRY(COMMON_UNSIGNED),
4179 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4180 hdr.type4.tunnel_id)),
4182 [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
4183 .name = "session_id",
4184 .help = "session identifier",
4185 .next = NEXT(item_l2tpv2_type_data_o,
4186 NEXT_ENTRY(COMMON_UNSIGNED),
4188 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4189 hdr.type5.session_id)),
4191 [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
4192 .name = "offset_size",
4193 .help = "the size of offset padding",
4194 .next = NEXT(item_l2tpv2_type_data_o,
4195 NEXT_ENTRY(COMMON_UNSIGNED),
4197 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4198 hdr.type4.offset_size)),
4200 [ITEM_L2TPV2_TYPE_DATA_L_S] = {
4202 .help = "Type #3: data message contains length, ns, nr "
4204 .next = NEXT(item_l2tpv2_type_data_l_s),
4205 .call = parse_vc_item_l2tpv2_type,
4207 [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
4209 .help = "message length",
4210 .next = NEXT(item_l2tpv2_type_data_l_s,
4211 NEXT_ENTRY(COMMON_UNSIGNED),
4213 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4216 [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
4217 .name = "tunnel_id",
4218 .help = "tunnel identifier",
4219 .next = NEXT(item_l2tpv2_type_data_l_s,
4220 NEXT_ENTRY(COMMON_UNSIGNED),
4222 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4223 hdr.type3.tunnel_id)),
4225 [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
4226 .name = "session_id",
4227 .help = "session identifier",
4228 .next = NEXT(item_l2tpv2_type_data_l_s,
4229 NEXT_ENTRY(COMMON_UNSIGNED),
4231 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4232 hdr.type3.session_id)),
4234 [ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
4236 .help = "sequence number for message",
4237 .next = NEXT(item_l2tpv2_type_data_l_s,
4238 NEXT_ENTRY(COMMON_UNSIGNED),
4240 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4243 [ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
4245 .help = "sequence number for next receive message",
4246 .next = NEXT(item_l2tpv2_type_data_l_s,
4247 NEXT_ENTRY(COMMON_UNSIGNED),
4249 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4252 [ITEM_L2TPV2_TYPE_CTRL] = {
4254 .help = "Type #3: conrtol message contains length, ns, nr "
4256 .next = NEXT(item_l2tpv2_type_ctrl),
4257 .call = parse_vc_item_l2tpv2_type,
4259 [ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
4261 .help = "message length",
4262 .next = NEXT(item_l2tpv2_type_ctrl,
4263 NEXT_ENTRY(COMMON_UNSIGNED),
4265 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4268 [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
4269 .name = "tunnel_id",
4270 .help = "tunnel identifier",
4271 .next = NEXT(item_l2tpv2_type_ctrl,
4272 NEXT_ENTRY(COMMON_UNSIGNED),
4274 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4275 hdr.type3.tunnel_id)),
4277 [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
4278 .name = "session_id",
4279 .help = "session identifier",
4280 .next = NEXT(item_l2tpv2_type_ctrl,
4281 NEXT_ENTRY(COMMON_UNSIGNED),
4283 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4284 hdr.type3.session_id)),
4286 [ITEM_L2TPV2_MSG_CTRL_NS] = {
4288 .help = "sequence number for message",
4289 .next = NEXT(item_l2tpv2_type_ctrl,
4290 NEXT_ENTRY(COMMON_UNSIGNED),
4292 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4295 [ITEM_L2TPV2_MSG_CTRL_NR] = {
4297 .help = "sequence number for next receive message",
4298 .next = NEXT(item_l2tpv2_type_ctrl,
4299 NEXT_ENTRY(COMMON_UNSIGNED),
4301 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
4306 .help = "match PPP header",
4307 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
4308 .next = NEXT(item_ppp),
4313 .help = "PPP address",
4314 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4316 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
4320 .help = "PPP control",
4321 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4323 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
4325 [ITEM_PPP_PROTO_ID] = {
4327 .help = "PPP protocol identifier",
4328 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
4330 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
4333 /* Validate/create actions. */
4336 .help = "submit a list of associated actions",
4337 .next = NEXT(next_action),
4342 .help = "specify next action",
4343 .next = NEXT(next_action),
4347 .help = "end list of actions",
4348 .priv = PRIV_ACTION(END, 0),
4353 .help = "no-op action",
4354 .priv = PRIV_ACTION(VOID, 0),
4355 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4358 [ACTION_PASSTHRU] = {
4360 .help = "let subsequent rule process matched packets",
4361 .priv = PRIV_ACTION(PASSTHRU, 0),
4362 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4367 .help = "redirect traffic to a given group",
4368 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
4369 .next = NEXT(action_jump),
4372 [ACTION_JUMP_GROUP] = {
4374 .help = "group to redirect traffic to",
4375 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
4376 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
4377 .call = parse_vc_conf,
4381 .help = "attach 32 bit value to packets",
4382 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
4383 .next = NEXT(action_mark),
4386 [ACTION_MARK_ID] = {
4388 .help = "32 bit value to return with packets",
4389 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
4390 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
4391 .call = parse_vc_conf,
4395 .help = "flag packets",
4396 .priv = PRIV_ACTION(FLAG, 0),
4397 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4402 .help = "assign packets to a given queue index",
4403 .priv = PRIV_ACTION(QUEUE,
4404 sizeof(struct rte_flow_action_queue)),
4405 .next = NEXT(action_queue),
4408 [ACTION_QUEUE_INDEX] = {
4410 .help = "queue index to use",
4411 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
4412 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
4413 .call = parse_vc_conf,
4417 .help = "drop packets (note: passthru has priority)",
4418 .priv = PRIV_ACTION(DROP, 0),
4419 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4424 .help = "enable counters for this rule",
4425 .priv = PRIV_ACTION(COUNT,
4426 sizeof(struct rte_flow_action_count)),
4427 .next = NEXT(action_count),
4430 [ACTION_COUNT_ID] = {
4431 .name = "identifier",
4432 .help = "counter identifier to use",
4433 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
4434 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
4435 .call = parse_vc_conf,
4439 .help = "spread packets among several queues",
4440 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
4441 .next = NEXT(action_rss),
4442 .call = parse_vc_action_rss,
4444 [ACTION_RSS_FUNC] = {
4446 .help = "RSS hash function to apply",
4447 .next = NEXT(action_rss,
4448 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
4449 ACTION_RSS_FUNC_TOEPLITZ,
4450 ACTION_RSS_FUNC_SIMPLE_XOR,
4451 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
4453 [ACTION_RSS_FUNC_DEFAULT] = {
4455 .help = "default hash function",
4456 .call = parse_vc_action_rss_func,
4458 [ACTION_RSS_FUNC_TOEPLITZ] = {
4460 .help = "Toeplitz hash function",
4461 .call = parse_vc_action_rss_func,
4463 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
4464 .name = "simple_xor",
4465 .help = "simple XOR hash function",
4466 .call = parse_vc_action_rss_func,
4468 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
4469 .name = "symmetric_toeplitz",
4470 .help = "Symmetric Toeplitz hash function",
4471 .call = parse_vc_action_rss_func,
4473 [ACTION_RSS_LEVEL] = {
4475 .help = "encapsulation level for \"types\"",
4476 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
4477 .args = ARGS(ARGS_ENTRY_ARB
4478 (offsetof(struct action_rss_data, conf) +
4479 offsetof(struct rte_flow_action_rss, level),
4480 sizeof(((struct rte_flow_action_rss *)0)->
4483 [ACTION_RSS_TYPES] = {
4485 .help = "specific RSS hash types",
4486 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
4488 [ACTION_RSS_TYPE] = {
4490 .help = "RSS hash type",
4491 .call = parse_vc_action_rss_type,
4492 .comp = comp_vc_action_rss_type,
4494 [ACTION_RSS_KEY] = {
4496 .help = "RSS hash key",
4497 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
4498 .args = ARGS(ARGS_ENTRY_ARB
4499 (offsetof(struct action_rss_data, conf) +
4500 offsetof(struct rte_flow_action_rss, key),
4501 sizeof(((struct rte_flow_action_rss *)0)->key)),
4503 (offsetof(struct action_rss_data, conf) +
4504 offsetof(struct rte_flow_action_rss, key_len),
4505 sizeof(((struct rte_flow_action_rss *)0)->
4507 ARGS_ENTRY(struct action_rss_data, key)),
4509 [ACTION_RSS_KEY_LEN] = {
4511 .help = "RSS hash key length in bytes",
4512 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
4513 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4514 (offsetof(struct action_rss_data, conf) +
4515 offsetof(struct rte_flow_action_rss, key_len),
4516 sizeof(((struct rte_flow_action_rss *)0)->
4519 RSS_HASH_KEY_LENGTH)),
4521 [ACTION_RSS_QUEUES] = {
4523 .help = "queue indices to use",
4524 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
4525 .call = parse_vc_conf,
4527 [ACTION_RSS_QUEUE] = {
4529 .help = "queue index",
4530 .call = parse_vc_action_rss_queue,
4531 .comp = comp_vc_action_rss_queue,
4535 .help = "direct traffic to physical function",
4536 .priv = PRIV_ACTION(PF, 0),
4537 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4542 .help = "direct traffic to a virtual function ID",
4543 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
4544 .next = NEXT(action_vf),
4547 [ACTION_VF_ORIGINAL] = {
4549 .help = "use original VF ID if possible",
4550 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
4551 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
4553 .call = parse_vc_conf,
4558 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
4559 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
4560 .call = parse_vc_conf,
4562 [ACTION_PHY_PORT] = {
4564 .help = "direct packets to physical port index",
4565 .priv = PRIV_ACTION(PHY_PORT,
4566 sizeof(struct rte_flow_action_phy_port)),
4567 .next = NEXT(action_phy_port),
4570 [ACTION_PHY_PORT_ORIGINAL] = {
4572 .help = "use original port index if possible",
4573 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
4574 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
4576 .call = parse_vc_conf,
4578 [ACTION_PHY_PORT_INDEX] = {
4580 .help = "physical port index",
4581 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
4582 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
4584 .call = parse_vc_conf,
4586 [ACTION_PORT_ID] = {
4588 .help = "direct matching traffic to a given DPDK port ID",
4589 .priv = PRIV_ACTION(PORT_ID,
4590 sizeof(struct rte_flow_action_port_id)),
4591 .next = NEXT(action_port_id),
4594 [ACTION_PORT_ID_ORIGINAL] = {
4596 .help = "use original DPDK port ID if possible",
4597 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
4598 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
4600 .call = parse_vc_conf,
4602 [ACTION_PORT_ID_ID] = {
4604 .help = "DPDK port ID",
4605 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
4606 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
4607 .call = parse_vc_conf,
4611 .help = "meter the directed packets at given id",
4612 .priv = PRIV_ACTION(METER,
4613 sizeof(struct rte_flow_action_meter)),
4614 .next = NEXT(action_meter),
4617 [ACTION_METER_COLOR] = {
4619 .help = "meter color for the packets",
4620 .priv = PRIV_ACTION(METER_COLOR,
4621 sizeof(struct rte_flow_action_meter_color)),
4622 .next = NEXT(action_meter_color),
4625 [ACTION_METER_COLOR_TYPE] = {
4627 .help = "specific meter color",
4628 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
4629 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
4630 ACTION_METER_COLOR_YELLOW,
4631 ACTION_METER_COLOR_RED)),
4633 [ACTION_METER_COLOR_GREEN] = {
4635 .help = "meter color green",
4636 .call = parse_vc_action_meter_color_type,
4638 [ACTION_METER_COLOR_YELLOW] = {
4640 .help = "meter color yellow",
4641 .call = parse_vc_action_meter_color_type,
4643 [ACTION_METER_COLOR_RED] = {
4645 .help = "meter color red",
4646 .call = parse_vc_action_meter_color_type,
4648 [ACTION_METER_ID] = {
4650 .help = "meter id to use",
4651 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
4652 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
4653 .call = parse_vc_conf,
4655 [ACTION_OF_SET_MPLS_TTL] = {
4656 .name = "of_set_mpls_ttl",
4657 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
4660 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
4661 .next = NEXT(action_of_set_mpls_ttl),
4664 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
4667 .next = NEXT(action_of_set_mpls_ttl,
4668 NEXT_ENTRY(COMMON_UNSIGNED)),
4669 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
4671 .call = parse_vc_conf,
4673 [ACTION_OF_DEC_MPLS_TTL] = {
4674 .name = "of_dec_mpls_ttl",
4675 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
4676 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
4677 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4680 [ACTION_OF_SET_NW_TTL] = {
4681 .name = "of_set_nw_ttl",
4682 .help = "OpenFlow's OFPAT_SET_NW_TTL",
4685 sizeof(struct rte_flow_action_of_set_nw_ttl)),
4686 .next = NEXT(action_of_set_nw_ttl),
4689 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
4692 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4693 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
4695 .call = parse_vc_conf,
4697 [ACTION_OF_DEC_NW_TTL] = {
4698 .name = "of_dec_nw_ttl",
4699 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
4700 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
4701 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4704 [ACTION_OF_COPY_TTL_OUT] = {
4705 .name = "of_copy_ttl_out",
4706 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
4707 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
4708 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4711 [ACTION_OF_COPY_TTL_IN] = {
4712 .name = "of_copy_ttl_in",
4713 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
4714 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
4715 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4718 [ACTION_OF_POP_VLAN] = {
4719 .name = "of_pop_vlan",
4720 .help = "OpenFlow's OFPAT_POP_VLAN",
4721 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
4722 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4725 [ACTION_OF_PUSH_VLAN] = {
4726 .name = "of_push_vlan",
4727 .help = "OpenFlow's OFPAT_PUSH_VLAN",
4730 sizeof(struct rte_flow_action_of_push_vlan)),
4731 .next = NEXT(action_of_push_vlan),
4734 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
4735 .name = "ethertype",
4736 .help = "EtherType",
4737 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
4738 .args = ARGS(ARGS_ENTRY_HTON
4739 (struct rte_flow_action_of_push_vlan,
4741 .call = parse_vc_conf,
4743 [ACTION_OF_SET_VLAN_VID] = {
4744 .name = "of_set_vlan_vid",
4745 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
4748 sizeof(struct rte_flow_action_of_set_vlan_vid)),
4749 .next = NEXT(action_of_set_vlan_vid),
4752 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
4755 .next = NEXT(action_of_set_vlan_vid,
4756 NEXT_ENTRY(COMMON_UNSIGNED)),
4757 .args = ARGS(ARGS_ENTRY_HTON
4758 (struct rte_flow_action_of_set_vlan_vid,
4760 .call = parse_vc_conf,
4762 [ACTION_OF_SET_VLAN_PCP] = {
4763 .name = "of_set_vlan_pcp",
4764 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
4767 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
4768 .next = NEXT(action_of_set_vlan_pcp),
4771 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
4773 .help = "VLAN priority",
4774 .next = NEXT(action_of_set_vlan_pcp,
4775 NEXT_ENTRY(COMMON_UNSIGNED)),
4776 .args = ARGS(ARGS_ENTRY_HTON
4777 (struct rte_flow_action_of_set_vlan_pcp,
4779 .call = parse_vc_conf,
4781 [ACTION_OF_POP_MPLS] = {
4782 .name = "of_pop_mpls",
4783 .help = "OpenFlow's OFPAT_POP_MPLS",
4784 .priv = PRIV_ACTION(OF_POP_MPLS,
4785 sizeof(struct rte_flow_action_of_pop_mpls)),
4786 .next = NEXT(action_of_pop_mpls),
4789 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
4790 .name = "ethertype",
4791 .help = "EtherType",
4792 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4793 .args = ARGS(ARGS_ENTRY_HTON
4794 (struct rte_flow_action_of_pop_mpls,
4796 .call = parse_vc_conf,
4798 [ACTION_OF_PUSH_MPLS] = {
4799 .name = "of_push_mpls",
4800 .help = "OpenFlow's OFPAT_PUSH_MPLS",
4803 sizeof(struct rte_flow_action_of_push_mpls)),
4804 .next = NEXT(action_of_push_mpls),
4807 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
4808 .name = "ethertype",
4809 .help = "EtherType",
4810 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4811 .args = ARGS(ARGS_ENTRY_HTON
4812 (struct rte_flow_action_of_push_mpls,
4814 .call = parse_vc_conf,
4816 [ACTION_VXLAN_ENCAP] = {
4817 .name = "vxlan_encap",
4818 .help = "VXLAN encapsulation, uses configuration set by \"set"
4820 .priv = PRIV_ACTION(VXLAN_ENCAP,
4821 sizeof(struct action_vxlan_encap_data)),
4822 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4823 .call = parse_vc_action_vxlan_encap,
4825 [ACTION_VXLAN_DECAP] = {
4826 .name = "vxlan_decap",
4827 .help = "Performs a decapsulation action by stripping all"
4828 " headers of the VXLAN tunnel network overlay from the"
4830 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
4831 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4834 [ACTION_NVGRE_ENCAP] = {
4835 .name = "nvgre_encap",
4836 .help = "NVGRE encapsulation, uses configuration set by \"set"
4838 .priv = PRIV_ACTION(NVGRE_ENCAP,
4839 sizeof(struct action_nvgre_encap_data)),
4840 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4841 .call = parse_vc_action_nvgre_encap,
4843 [ACTION_NVGRE_DECAP] = {
4844 .name = "nvgre_decap",
4845 .help = "Performs a decapsulation action by stripping all"
4846 " headers of the NVGRE tunnel network overlay from the"
4848 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
4849 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4852 [ACTION_L2_ENCAP] = {
4854 .help = "l2 encap, uses configuration set by"
4855 " \"set l2_encap\"",
4856 .priv = PRIV_ACTION(RAW_ENCAP,
4857 sizeof(struct action_raw_encap_data)),
4858 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4859 .call = parse_vc_action_l2_encap,
4861 [ACTION_L2_DECAP] = {
4863 .help = "l2 decap, uses configuration set by"
4864 " \"set l2_decap\"",
4865 .priv = PRIV_ACTION(RAW_DECAP,
4866 sizeof(struct action_raw_decap_data)),
4867 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4868 .call = parse_vc_action_l2_decap,
4870 [ACTION_MPLSOGRE_ENCAP] = {
4871 .name = "mplsogre_encap",
4872 .help = "mplsogre encapsulation, uses configuration set by"
4873 " \"set mplsogre_encap\"",
4874 .priv = PRIV_ACTION(RAW_ENCAP,
4875 sizeof(struct action_raw_encap_data)),
4876 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4877 .call = parse_vc_action_mplsogre_encap,
4879 [ACTION_MPLSOGRE_DECAP] = {
4880 .name = "mplsogre_decap",
4881 .help = "mplsogre decapsulation, uses configuration set by"
4882 " \"set mplsogre_decap\"",
4883 .priv = PRIV_ACTION(RAW_DECAP,
4884 sizeof(struct action_raw_decap_data)),
4885 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4886 .call = parse_vc_action_mplsogre_decap,
4888 [ACTION_MPLSOUDP_ENCAP] = {
4889 .name = "mplsoudp_encap",
4890 .help = "mplsoudp encapsulation, uses configuration set by"
4891 " \"set mplsoudp_encap\"",
4892 .priv = PRIV_ACTION(RAW_ENCAP,
4893 sizeof(struct action_raw_encap_data)),
4894 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4895 .call = parse_vc_action_mplsoudp_encap,
4897 [ACTION_MPLSOUDP_DECAP] = {
4898 .name = "mplsoudp_decap",
4899 .help = "mplsoudp decapsulation, uses configuration set by"
4900 " \"set mplsoudp_decap\"",
4901 .priv = PRIV_ACTION(RAW_DECAP,
4902 sizeof(struct action_raw_decap_data)),
4903 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4904 .call = parse_vc_action_mplsoudp_decap,
4906 [ACTION_SET_IPV4_SRC] = {
4907 .name = "set_ipv4_src",
4908 .help = "Set a new IPv4 source address in the outermost"
4910 .priv = PRIV_ACTION(SET_IPV4_SRC,
4911 sizeof(struct rte_flow_action_set_ipv4)),
4912 .next = NEXT(action_set_ipv4_src),
4915 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
4916 .name = "ipv4_addr",
4917 .help = "new IPv4 source address to set",
4918 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4919 .args = ARGS(ARGS_ENTRY_HTON
4920 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4921 .call = parse_vc_conf,
4923 [ACTION_SET_IPV4_DST] = {
4924 .name = "set_ipv4_dst",
4925 .help = "Set a new IPv4 destination address in the outermost"
4927 .priv = PRIV_ACTION(SET_IPV4_DST,
4928 sizeof(struct rte_flow_action_set_ipv4)),
4929 .next = NEXT(action_set_ipv4_dst),
4932 [ACTION_SET_IPV4_DST_IPV4_DST] = {
4933 .name = "ipv4_addr",
4934 .help = "new IPv4 destination address to set",
4935 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4936 .args = ARGS(ARGS_ENTRY_HTON
4937 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4938 .call = parse_vc_conf,
4940 [ACTION_SET_IPV6_SRC] = {
4941 .name = "set_ipv6_src",
4942 .help = "Set a new IPv6 source address in the outermost"
4944 .priv = PRIV_ACTION(SET_IPV6_SRC,
4945 sizeof(struct rte_flow_action_set_ipv6)),
4946 .next = NEXT(action_set_ipv6_src),
4949 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
4950 .name = "ipv6_addr",
4951 .help = "new IPv6 source address to set",
4952 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4953 .args = ARGS(ARGS_ENTRY_HTON
4954 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4955 .call = parse_vc_conf,
4957 [ACTION_SET_IPV6_DST] = {
4958 .name = "set_ipv6_dst",
4959 .help = "Set a new IPv6 destination address in the outermost"
4961 .priv = PRIV_ACTION(SET_IPV6_DST,
4962 sizeof(struct rte_flow_action_set_ipv6)),
4963 .next = NEXT(action_set_ipv6_dst),
4966 [ACTION_SET_IPV6_DST_IPV6_DST] = {
4967 .name = "ipv6_addr",
4968 .help = "new IPv6 destination address to set",
4969 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4970 .args = ARGS(ARGS_ENTRY_HTON
4971 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4972 .call = parse_vc_conf,
4974 [ACTION_SET_TP_SRC] = {
4975 .name = "set_tp_src",
4976 .help = "set a new source port number in the outermost"
4978 .priv = PRIV_ACTION(SET_TP_SRC,
4979 sizeof(struct rte_flow_action_set_tp)),
4980 .next = NEXT(action_set_tp_src),
4983 [ACTION_SET_TP_SRC_TP_SRC] = {
4985 .help = "new source port number to set",
4986 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
4987 .args = ARGS(ARGS_ENTRY_HTON
4988 (struct rte_flow_action_set_tp, port)),
4989 .call = parse_vc_conf,
4991 [ACTION_SET_TP_DST] = {
4992 .name = "set_tp_dst",
4993 .help = "set a new destination port number in the outermost"
4995 .priv = PRIV_ACTION(SET_TP_DST,
4996 sizeof(struct rte_flow_action_set_tp)),
4997 .next = NEXT(action_set_tp_dst),
5000 [ACTION_SET_TP_DST_TP_DST] = {
5002 .help = "new destination port number to set",
5003 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
5004 .args = ARGS(ARGS_ENTRY_HTON
5005 (struct rte_flow_action_set_tp, port)),
5006 .call = parse_vc_conf,
5008 [ACTION_MAC_SWAP] = {
5010 .help = "Swap the source and destination MAC addresses"
5011 " in the outermost Ethernet header",
5012 .priv = PRIV_ACTION(MAC_SWAP, 0),
5013 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5016 [ACTION_DEC_TTL] = {
5018 .help = "decrease network TTL if available",
5019 .priv = PRIV_ACTION(DEC_TTL, 0),
5020 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5023 [ACTION_SET_TTL] = {
5025 .help = "set ttl value",
5026 .priv = PRIV_ACTION(SET_TTL,
5027 sizeof(struct rte_flow_action_set_ttl)),
5028 .next = NEXT(action_set_ttl),
5031 [ACTION_SET_TTL_TTL] = {
5032 .name = "ttl_value",
5033 .help = "new ttl value to set",
5034 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
5035 .args = ARGS(ARGS_ENTRY_HTON
5036 (struct rte_flow_action_set_ttl, ttl_value)),
5037 .call = parse_vc_conf,
5039 [ACTION_SET_MAC_SRC] = {
5040 .name = "set_mac_src",
5041 .help = "set source mac address",
5042 .priv = PRIV_ACTION(SET_MAC_SRC,
5043 sizeof(struct rte_flow_action_set_mac)),
5044 .next = NEXT(action_set_mac_src),
5047 [ACTION_SET_MAC_SRC_MAC_SRC] = {
5049 .help = "new source mac address",
5050 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
5051 .args = ARGS(ARGS_ENTRY_HTON
5052 (struct rte_flow_action_set_mac, mac_addr)),
5053 .call = parse_vc_conf,
5055 [ACTION_SET_MAC_DST] = {
5056 .name = "set_mac_dst",
5057 .help = "set destination mac address",
5058 .priv = PRIV_ACTION(SET_MAC_DST,
5059 sizeof(struct rte_flow_action_set_mac)),
5060 .next = NEXT(action_set_mac_dst),
5063 [ACTION_SET_MAC_DST_MAC_DST] = {
5065 .help = "new destination mac address to set",
5066 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
5067 .args = ARGS(ARGS_ENTRY_HTON
5068 (struct rte_flow_action_set_mac, mac_addr)),
5069 .call = parse_vc_conf,
5071 [ACTION_INC_TCP_SEQ] = {
5072 .name = "inc_tcp_seq",
5073 .help = "increase TCP sequence number",
5074 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
5075 .next = NEXT(action_inc_tcp_seq),
5078 [ACTION_INC_TCP_SEQ_VALUE] = {
5080 .help = "the value to increase TCP sequence number by",
5081 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5082 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5083 .call = parse_vc_conf,
5085 [ACTION_DEC_TCP_SEQ] = {
5086 .name = "dec_tcp_seq",
5087 .help = "decrease TCP sequence number",
5088 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
5089 .next = NEXT(action_dec_tcp_seq),
5092 [ACTION_DEC_TCP_SEQ_VALUE] = {
5094 .help = "the value to decrease TCP sequence number by",
5095 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
5096 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5097 .call = parse_vc_conf,
5099 [ACTION_INC_TCP_ACK] = {
5100 .name = "inc_tcp_ack",
5101 .help = "increase TCP acknowledgment number",
5102 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
5103 .next = NEXT(action_inc_tcp_ack),
5106 [ACTION_INC_TCP_ACK_VALUE] = {
5108 .help = "the value to increase TCP acknowledgment number by",
5109 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5110 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5111 .call = parse_vc_conf,
5113 [ACTION_DEC_TCP_ACK] = {
5114 .name = "dec_tcp_ack",
5115 .help = "decrease TCP acknowledgment number",
5116 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
5117 .next = NEXT(action_dec_tcp_ack),
5120 [ACTION_DEC_TCP_ACK_VALUE] = {
5122 .help = "the value to decrease TCP acknowledgment number by",
5123 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
5124 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5125 .call = parse_vc_conf,
5127 [ACTION_RAW_ENCAP] = {
5128 .name = "raw_encap",
5129 .help = "encapsulation data, defined by set raw_encap",
5130 .priv = PRIV_ACTION(RAW_ENCAP,
5131 sizeof(struct action_raw_encap_data)),
5132 .next = NEXT(action_raw_encap),
5133 .call = parse_vc_action_raw_encap,
5135 [ACTION_RAW_ENCAP_INDEX] = {
5137 .help = "the index of raw_encap_confs",
5138 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
5140 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
5143 .help = "unsigned integer value",
5144 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5145 .call = parse_vc_action_raw_encap_index,
5146 .comp = comp_set_raw_index,
5148 [ACTION_RAW_DECAP] = {
5149 .name = "raw_decap",
5150 .help = "decapsulation data, defined by set raw_encap",
5151 .priv = PRIV_ACTION(RAW_DECAP,
5152 sizeof(struct action_raw_decap_data)),
5153 .next = NEXT(action_raw_decap),
5154 .call = parse_vc_action_raw_decap,
5156 [ACTION_RAW_DECAP_INDEX] = {
5158 .help = "the index of raw_encap_confs",
5159 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
5161 [ACTION_RAW_DECAP_INDEX_VALUE] = {
5164 .help = "unsigned integer value",
5165 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5166 .call = parse_vc_action_raw_decap_index,
5167 .comp = comp_set_raw_index,
5169 [ACTION_MODIFY_FIELD] = {
5170 .name = "modify_field",
5171 .help = "modify destination field with data from source field",
5172 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
5173 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
5176 [ACTION_MODIFY_FIELD_OP] = {
5178 .help = "operation type",
5179 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
5180 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
5181 .call = parse_vc_conf,
5183 [ACTION_MODIFY_FIELD_OP_VALUE] = {
5184 .name = "{operation}",
5185 .help = "operation type value",
5186 .call = parse_vc_modify_field_op,
5187 .comp = comp_set_modify_field_op,
5189 [ACTION_MODIFY_FIELD_DST_TYPE] = {
5191 .help = "destination field type",
5192 .next = NEXT(action_modify_field_dst,
5193 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
5194 .call = parse_vc_conf,
5196 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
5197 .name = "{dst_type}",
5198 .help = "destination field type value",
5199 .call = parse_vc_modify_field_id,
5200 .comp = comp_set_modify_field_id,
5202 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
5203 .name = "dst_level",
5204 .help = "destination field level",
5205 .next = NEXT(action_modify_field_dst,
5206 NEXT_ENTRY(COMMON_UNSIGNED)),
5207 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5209 .call = parse_vc_conf,
5211 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
5212 .name = "dst_offset",
5213 .help = "destination field bit offset",
5214 .next = NEXT(action_modify_field_dst,
5215 NEXT_ENTRY(COMMON_UNSIGNED)),
5216 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5218 .call = parse_vc_conf,
5220 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
5222 .help = "source field type",
5223 .next = NEXT(action_modify_field_src,
5224 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
5225 .call = parse_vc_conf,
5227 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
5228 .name = "{src_type}",
5229 .help = "source field type value",
5230 .call = parse_vc_modify_field_id,
5231 .comp = comp_set_modify_field_id,
5233 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
5234 .name = "src_level",
5235 .help = "source field level",
5236 .next = NEXT(action_modify_field_src,
5237 NEXT_ENTRY(COMMON_UNSIGNED)),
5238 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5240 .call = parse_vc_conf,
5242 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
5243 .name = "src_offset",
5244 .help = "source field bit offset",
5245 .next = NEXT(action_modify_field_src,
5246 NEXT_ENTRY(COMMON_UNSIGNED)),
5247 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5249 .call = parse_vc_conf,
5251 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
5252 .name = "src_value",
5253 .help = "source immediate value",
5254 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5255 NEXT_ENTRY(COMMON_HEX)),
5256 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
5257 ARGS_ENTRY_ARB(0, 0),
5258 ARGS_ENTRY(struct rte_flow_action_modify_field,
5260 .call = parse_vc_conf,
5262 [ACTION_MODIFY_FIELD_SRC_POINTER] = {
5264 .help = "pointer to source immediate value",
5265 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
5266 NEXT_ENTRY(COMMON_HEX)),
5267 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5269 ARGS_ENTRY_ARB(0, 0),
5271 (sizeof(struct rte_flow_action_modify_field),
5272 ACTION_MODIFY_PATTERN_SIZE)),
5273 .call = parse_vc_conf,
5275 [ACTION_MODIFY_FIELD_WIDTH] = {
5277 .help = "number of bits to copy",
5278 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5279 NEXT_ENTRY(COMMON_UNSIGNED)),
5280 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
5282 .call = parse_vc_conf,
5284 /* Top level command. */
5287 .help = "set raw encap/decap/sample data",
5288 .type = "set raw_encap|raw_decap <index> <pattern>"
5289 " or set sample_actions <index> <action>",
5290 .next = NEXT(NEXT_ENTRY
5293 SET_SAMPLE_ACTIONS)),
5294 .call = parse_set_init,
5296 /* Sub-level commands. */
5298 .name = "raw_encap",
5299 .help = "set raw encap data",
5300 .next = NEXT(next_set_raw),
5301 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5302 (offsetof(struct buffer, port),
5303 sizeof(((struct buffer *)0)->port),
5304 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5305 .call = parse_set_raw_encap_decap,
5308 .name = "raw_decap",
5309 .help = "set raw decap data",
5310 .next = NEXT(next_set_raw),
5311 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5312 (offsetof(struct buffer, port),
5313 sizeof(((struct buffer *)0)->port),
5314 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
5315 .call = parse_set_raw_encap_decap,
5319 .type = "COMMON_UNSIGNED",
5320 .help = "index of raw_encap/raw_decap data",
5321 .next = NEXT(next_item),
5324 [SET_SAMPLE_INDEX] = {
5327 .help = "index of sample actions",
5328 .next = NEXT(next_action_sample),
5331 [SET_SAMPLE_ACTIONS] = {
5332 .name = "sample_actions",
5333 .help = "set sample actions list",
5334 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
5335 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5336 (offsetof(struct buffer, port),
5337 sizeof(((struct buffer *)0)->port),
5338 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
5339 .call = parse_set_sample_action,
5341 [ACTION_SET_TAG] = {
5344 .priv = PRIV_ACTION(SET_TAG,
5345 sizeof(struct rte_flow_action_set_tag)),
5346 .next = NEXT(action_set_tag),
5349 [ACTION_SET_TAG_INDEX] = {
5351 .help = "index of tag array",
5352 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5353 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
5354 .call = parse_vc_conf,
5356 [ACTION_SET_TAG_DATA] = {
5358 .help = "tag value",
5359 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5360 .args = ARGS(ARGS_ENTRY
5361 (struct rte_flow_action_set_tag, data)),
5362 .call = parse_vc_conf,
5364 [ACTION_SET_TAG_MASK] = {
5366 .help = "mask for tag value",
5367 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
5368 .args = ARGS(ARGS_ENTRY
5369 (struct rte_flow_action_set_tag, mask)),
5370 .call = parse_vc_conf,
5372 [ACTION_SET_META] = {
5374 .help = "set metadata",
5375 .priv = PRIV_ACTION(SET_META,
5376 sizeof(struct rte_flow_action_set_meta)),
5377 .next = NEXT(action_set_meta),
5378 .call = parse_vc_action_set_meta,
5380 [ACTION_SET_META_DATA] = {
5382 .help = "metadata value",
5383 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5384 .args = ARGS(ARGS_ENTRY
5385 (struct rte_flow_action_set_meta, data)),
5386 .call = parse_vc_conf,
5388 [ACTION_SET_META_MASK] = {
5390 .help = "mask for metadata value",
5391 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
5392 .args = ARGS(ARGS_ENTRY
5393 (struct rte_flow_action_set_meta, mask)),
5394 .call = parse_vc_conf,
5396 [ACTION_SET_IPV4_DSCP] = {
5397 .name = "set_ipv4_dscp",
5398 .help = "set DSCP value",
5399 .priv = PRIV_ACTION(SET_IPV4_DSCP,
5400 sizeof(struct rte_flow_action_set_dscp)),
5401 .next = NEXT(action_set_ipv4_dscp),
5404 [ACTION_SET_IPV4_DSCP_VALUE] = {
5405 .name = "dscp_value",
5406 .help = "new IPv4 DSCP value to set",
5407 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5408 .args = ARGS(ARGS_ENTRY
5409 (struct rte_flow_action_set_dscp, dscp)),
5410 .call = parse_vc_conf,
5412 [ACTION_SET_IPV6_DSCP] = {
5413 .name = "set_ipv6_dscp",
5414 .help = "set DSCP value",
5415 .priv = PRIV_ACTION(SET_IPV6_DSCP,
5416 sizeof(struct rte_flow_action_set_dscp)),
5417 .next = NEXT(action_set_ipv6_dscp),
5420 [ACTION_SET_IPV6_DSCP_VALUE] = {
5421 .name = "dscp_value",
5422 .help = "new IPv6 DSCP value to set",
5423 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
5424 .args = ARGS(ARGS_ENTRY
5425 (struct rte_flow_action_set_dscp, dscp)),
5426 .call = parse_vc_conf,
5430 .help = "set a specific metadata header",
5431 .next = NEXT(action_age),
5432 .priv = PRIV_ACTION(AGE,
5433 sizeof(struct rte_flow_action_age)),
5436 [ACTION_AGE_TIMEOUT] = {
5438 .help = "flow age timeout value",
5439 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
5441 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
5442 .call = parse_vc_conf,
5446 .help = "set a sample action",
5447 .next = NEXT(action_sample),
5448 .priv = PRIV_ACTION(SAMPLE,
5449 sizeof(struct action_sample_data)),
5450 .call = parse_vc_action_sample,
5452 [ACTION_SAMPLE_RATIO] = {
5454 .help = "flow sample ratio value",
5455 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
5456 .args = ARGS(ARGS_ENTRY_ARB
5457 (offsetof(struct action_sample_data, conf) +
5458 offsetof(struct rte_flow_action_sample, ratio),
5459 sizeof(((struct rte_flow_action_sample *)0)->
5462 [ACTION_SAMPLE_INDEX] = {
5464 .help = "the index of sample actions list",
5465 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
5467 [ACTION_SAMPLE_INDEX_VALUE] = {
5469 .type = "COMMON_UNSIGNED",
5470 .help = "unsigned integer value",
5471 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5472 .call = parse_vc_action_sample_index,
5473 .comp = comp_set_sample_index,
5475 [ACTION_CONNTRACK] = {
5476 .name = "conntrack",
5477 .help = "create a conntrack object",
5478 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5479 .priv = PRIV_ACTION(CONNTRACK,
5480 sizeof(struct rte_flow_action_conntrack)),
5483 [ACTION_CONNTRACK_UPDATE] = {
5484 .name = "conntrack_update",
5485 .help = "update a conntrack object",
5486 .next = NEXT(action_update_conntrack),
5487 .priv = PRIV_ACTION(CONNTRACK,
5488 sizeof(struct rte_flow_modify_conntrack)),
5491 [ACTION_CONNTRACK_UPDATE_DIR] = {
5493 .help = "update a conntrack object direction",
5494 .next = NEXT(action_update_conntrack),
5495 .call = parse_vc_action_conntrack_update,
5497 [ACTION_CONNTRACK_UPDATE_CTX] = {
5499 .help = "update a conntrack object context",
5500 .next = NEXT(action_update_conntrack),
5501 .call = parse_vc_action_conntrack_update,
5503 [ACTION_PORT_REPRESENTOR] = {
5504 .name = "port_representor",
5505 .help = "at embedded switch level, send matching traffic to the given ethdev",
5506 .priv = PRIV_ACTION(PORT_REPRESENTOR,
5507 sizeof(struct rte_flow_action_ethdev)),
5508 .next = NEXT(action_port_representor),
5511 [ACTION_PORT_REPRESENTOR_PORT_ID] = {
5513 .help = "ethdev port ID",
5514 .next = NEXT(action_port_representor,
5515 NEXT_ENTRY(COMMON_UNSIGNED)),
5516 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
5518 .call = parse_vc_conf,
5520 [ACTION_REPRESENTED_PORT] = {
5521 .name = "represented_port",
5522 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
5523 .priv = PRIV_ACTION(REPRESENTED_PORT,
5524 sizeof(struct rte_flow_action_ethdev)),
5525 .next = NEXT(action_represented_port),
5528 [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5529 .name = "ethdev_port_id",
5530 .help = "ethdev port ID",
5531 .next = NEXT(action_represented_port,
5532 NEXT_ENTRY(COMMON_UNSIGNED)),
5533 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
5535 .call = parse_vc_conf,
5537 /* Indirect action destroy arguments. */
5538 [INDIRECT_ACTION_DESTROY_ID] = {
5539 .name = "action_id",
5540 .help = "specify a indirect action id to destroy",
5541 .next = NEXT(next_ia_destroy_attr,
5542 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
5543 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
5544 args.ia_destroy.action_id)),
5545 .call = parse_ia_destroy,
5547 /* Indirect action create arguments. */
5548 [INDIRECT_ACTION_CREATE_ID] = {
5549 .name = "action_id",
5550 .help = "specify a indirect action id to create",
5551 .next = NEXT(next_ia_create_attr,
5552 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
5553 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
5555 [ACTION_INDIRECT] = {
5557 .help = "apply indirect action by id",
5558 .priv = PRIV_ACTION(INDIRECT, 0),
5559 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
5560 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
5563 [INDIRECT_ACTION_ID2PTR] = {
5564 .name = "{action_id}",
5565 .type = "INDIRECT_ACTION_ID",
5566 .help = "indirect action id",
5567 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5568 .call = parse_ia_id2ptr,
5571 [INDIRECT_ACTION_INGRESS] = {
5573 .help = "affect rule to ingress",
5574 .next = NEXT(next_ia_create_attr),
5577 [INDIRECT_ACTION_EGRESS] = {
5579 .help = "affect rule to egress",
5580 .next = NEXT(next_ia_create_attr),
5583 [INDIRECT_ACTION_TRANSFER] = {
5585 .help = "affect rule to transfer",
5586 .next = NEXT(next_ia_create_attr),
5589 [INDIRECT_ACTION_SPEC] = {
5591 .help = "specify action to create indirect handle",
5592 .next = NEXT(next_action),
5595 .name = "g_actions",
5596 .help = "submit a list of associated actions for green",
5597 .next = NEXT(next_action),
5601 .name = "y_actions",
5602 .help = "submit a list of associated actions for yellow",
5603 .next = NEXT(next_action),
5606 .name = "r_actions",
5607 .help = "submit a list of associated actions for red",
5608 .next = NEXT(next_action),
5611 /* Top-level command. */
5614 .type = "port meter policy {port_id} {arg}",
5615 .help = "add port meter policy",
5616 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
5619 /* Sub-level commands. */
5622 .help = "add port meter policy",
5623 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
5625 [ITEM_POL_METER] = {
5627 .help = "add port meter policy",
5628 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
5630 [ITEM_POL_POLICY] = {
5632 .help = "add port meter policy",
5633 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
5634 NEXT_ENTRY(ACTION_POL_Y),
5635 NEXT_ENTRY(ACTION_POL_G),
5636 NEXT_ENTRY(COMMON_POLICY_ID),
5637 NEXT_ENTRY(COMMON_PORT_ID)),
5638 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
5639 ARGS_ENTRY(struct buffer, port)),
5644 /** Remove and return last entry from argument stack. */
5645 static const struct arg *
5646 pop_args(struct context *ctx)
5648 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
5651 /** Add entry on top of the argument stack. */
5653 push_args(struct context *ctx, const struct arg *arg)
5655 if (ctx->args_num == CTX_STACK_SIZE)
5657 ctx->args[ctx->args_num++] = arg;
5661 /** Spread value into buffer according to bit-mask. */
5663 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
5665 uint32_t i = arg->size;
5673 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5682 unsigned int shift = 0;
5683 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
5685 for (shift = 0; arg->mask[i] >> shift; ++shift) {
5686 if (!(arg->mask[i] & (1 << shift)))
5691 *buf &= ~(1 << shift);
5692 *buf |= (val & 1) << shift;
5700 /** Compare a string with a partial one of a given length. */
5702 strcmp_partial(const char *full, const char *partial, size_t partial_len)
5704 int r = strncmp(full, partial, partial_len);
5708 if (strlen(full) <= partial_len)
5710 return full[partial_len];
5714 * Parse a prefix length and generate a bit-mask.
5716 * Last argument (ctx->args) is retrieved to determine mask size, storage
5717 * location and whether the result must use network byte ordering.
5720 parse_prefix(struct context *ctx, const struct token *token,
5721 const char *str, unsigned int len,
5722 void *buf, unsigned int size)
5724 const struct arg *arg = pop_args(ctx);
5725 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
5732 /* Argument is expected. */
5736 u = strtoumax(str, &end, 0);
5737 if (errno || (size_t)(end - str) != len)
5742 extra = arg_entry_bf_fill(NULL, 0, arg);
5751 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
5752 !arg_entry_bf_fill(ctx->objmask, -1, arg))
5759 if (bytes > size || bytes + !!extra > size)
5763 buf = (uint8_t *)ctx->object + arg->offset;
5764 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5766 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
5767 memset(buf, 0x00, size - bytes);
5769 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
5773 memset(buf, 0xff, bytes);
5774 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
5776 ((uint8_t *)buf)[bytes] = conv[extra];
5779 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5782 push_args(ctx, arg);
5786 /** Default parsing function for token name matching. */
5788 parse_default(struct context *ctx, const struct token *token,
5789 const char *str, unsigned int len,
5790 void *buf, unsigned int size)
5795 if (strcmp_partial(token->name, str, len))
5800 /** Parse flow command, initialize output buffer for subsequent tokens. */
5802 parse_init(struct context *ctx, const struct token *token,
5803 const char *str, unsigned int len,
5804 void *buf, unsigned int size)
5806 struct buffer *out = buf;
5808 /* Token name must match. */
5809 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5811 /* Nothing else to do if there is no buffer. */
5814 /* Make sure buffer is large enough. */
5815 if (size < sizeof(*out))
5817 /* Initialize buffer. */
5818 memset(out, 0x00, sizeof(*out));
5819 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5822 ctx->objmask = NULL;
5826 /** Parse tokens for indirect action commands. */
5828 parse_ia(struct context *ctx, const struct token *token,
5829 const char *str, unsigned int len,
5830 void *buf, unsigned int size)
5832 struct buffer *out = buf;
5834 /* Token name must match. */
5835 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5837 /* Nothing else to do if there is no buffer. */
5840 if (!out->command) {
5841 if (ctx->curr != INDIRECT_ACTION)
5843 if (sizeof(*out) > size)
5845 out->command = ctx->curr;
5848 ctx->objmask = NULL;
5849 out->args.vc.data = (uint8_t *)out + size;
5852 switch (ctx->curr) {
5853 case INDIRECT_ACTION_CREATE:
5854 case INDIRECT_ACTION_UPDATE:
5855 out->args.vc.actions =
5856 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5858 out->args.vc.attr.group = UINT32_MAX;
5860 case INDIRECT_ACTION_QUERY:
5861 out->command = ctx->curr;
5864 ctx->objmask = NULL;
5866 case INDIRECT_ACTION_EGRESS:
5867 out->args.vc.attr.egress = 1;
5869 case INDIRECT_ACTION_INGRESS:
5870 out->args.vc.attr.ingress = 1;
5872 case INDIRECT_ACTION_TRANSFER:
5873 out->args.vc.attr.transfer = 1;
5881 /** Parse tokens for indirect action destroy command. */
5883 parse_ia_destroy(struct context *ctx, const struct token *token,
5884 const char *str, unsigned int len,
5885 void *buf, unsigned int size)
5887 struct buffer *out = buf;
5888 uint32_t *action_id;
5890 /* Token name must match. */
5891 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5893 /* Nothing else to do if there is no buffer. */
5896 if (!out->command || out->command == INDIRECT_ACTION) {
5897 if (ctx->curr != INDIRECT_ACTION_DESTROY)
5899 if (sizeof(*out) > size)
5901 out->command = ctx->curr;
5904 ctx->objmask = NULL;
5905 out->args.ia_destroy.action_id =
5906 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5910 action_id = out->args.ia_destroy.action_id
5911 + out->args.ia_destroy.action_id_n++;
5912 if ((uint8_t *)action_id > (uint8_t *)out + size)
5915 ctx->object = action_id;
5916 ctx->objmask = NULL;
5920 /** Parse tokens for meter policy action commands. */
5922 parse_mp(struct context *ctx, const struct token *token,
5923 const char *str, unsigned int len,
5924 void *buf, unsigned int size)
5926 struct buffer *out = buf;
5928 /* Token name must match. */
5929 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5931 /* Nothing else to do if there is no buffer. */
5934 if (!out->command) {
5935 if (ctx->curr != ITEM_POL_POLICY)
5937 if (sizeof(*out) > size)
5939 out->command = ctx->curr;
5942 ctx->objmask = NULL;
5943 out->args.vc.data = (uint8_t *)out + size;
5946 switch (ctx->curr) {
5948 out->args.vc.actions =
5949 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5951 out->command = ctx->curr;
5954 ctx->objmask = NULL;
5961 /** Parse tokens for validate/create commands. */
5963 parse_vc(struct context *ctx, const struct token *token,
5964 const char *str, unsigned int len,
5965 void *buf, unsigned int size)
5967 struct buffer *out = buf;
5971 /* Token name must match. */
5972 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5974 /* Nothing else to do if there is no buffer. */
5977 if (!out->command) {
5978 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
5980 if (sizeof(*out) > size)
5982 out->command = ctx->curr;
5985 ctx->objmask = NULL;
5986 out->args.vc.data = (uint8_t *)out + size;
5990 switch (ctx->curr) {
5992 ctx->object = &out->args.vc.attr;
5995 case VC_TUNNEL_MATCH:
5996 ctx->object = &out->args.vc.tunnel_ops;
5999 ctx->objmask = NULL;
6000 switch (ctx->curr) {
6005 out->args.vc.tunnel_ops.enabled = 1;
6006 out->args.vc.tunnel_ops.actions = 1;
6008 case VC_TUNNEL_MATCH:
6009 out->args.vc.tunnel_ops.enabled = 1;
6010 out->args.vc.tunnel_ops.items = 1;
6013 out->args.vc.attr.ingress = 1;
6016 out->args.vc.attr.egress = 1;
6019 out->args.vc.attr.transfer = 1;
6022 out->args.vc.pattern =
6023 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6025 ctx->object = out->args.vc.pattern;
6026 ctx->objmask = NULL;
6029 out->args.vc.actions =
6030 (void *)RTE_ALIGN_CEIL((uintptr_t)
6031 (out->args.vc.pattern +
6032 out->args.vc.pattern_n),
6034 ctx->object = out->args.vc.actions;
6035 ctx->objmask = NULL;
6042 if (!out->args.vc.actions) {
6043 const struct parse_item_priv *priv = token->priv;
6044 struct rte_flow_item *item =
6045 out->args.vc.pattern + out->args.vc.pattern_n;
6047 data_size = priv->size * 3; /* spec, last, mask */
6048 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6049 (out->args.vc.data - data_size),
6051 if ((uint8_t *)item + sizeof(*item) > data)
6053 *item = (struct rte_flow_item){
6056 ++out->args.vc.pattern_n;
6058 ctx->objmask = NULL;
6060 const struct parse_action_priv *priv = token->priv;
6061 struct rte_flow_action *action =
6062 out->args.vc.actions + out->args.vc.actions_n;
6064 data_size = priv->size; /* configuration */
6065 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
6066 (out->args.vc.data - data_size),
6068 if ((uint8_t *)action + sizeof(*action) > data)
6070 *action = (struct rte_flow_action){
6072 .conf = data_size ? data : NULL,
6074 ++out->args.vc.actions_n;
6075 ctx->object = action;
6076 ctx->objmask = NULL;
6078 memset(data, 0, data_size);
6079 out->args.vc.data = data;
6080 ctx->objdata = data_size;
6084 /** Parse pattern item parameter type. */
6086 parse_vc_spec(struct context *ctx, const struct token *token,
6087 const char *str, unsigned int len,
6088 void *buf, unsigned int size)
6090 struct buffer *out = buf;
6091 struct rte_flow_item *item;
6097 /* Token name must match. */
6098 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6100 /* Parse parameter types. */
6101 switch (ctx->curr) {
6102 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
6108 case ITEM_PARAM_SPEC:
6111 case ITEM_PARAM_LAST:
6114 case ITEM_PARAM_PREFIX:
6115 /* Modify next token to expect a prefix. */
6116 if (ctx->next_num < 2)
6118 ctx->next[ctx->next_num - 2] = prefix;
6120 case ITEM_PARAM_MASK:
6126 /* Nothing else to do if there is no buffer. */
6129 if (!out->args.vc.pattern_n)
6131 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6132 data_size = ctx->objdata / 3; /* spec, last, mask */
6133 /* Point to selected object. */
6134 ctx->object = out->args.vc.data + (data_size * index);
6136 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
6137 item->mask = ctx->objmask;
6139 ctx->objmask = NULL;
6140 /* Update relevant item pointer. */
6141 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
6146 /** Parse action configuration field. */
6148 parse_vc_conf(struct context *ctx, const struct token *token,
6149 const char *str, unsigned int len,
6150 void *buf, unsigned int size)
6152 struct buffer *out = buf;
6155 /* Token name must match. */
6156 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6158 /* Nothing else to do if there is no buffer. */
6161 /* Point to selected object. */
6162 ctx->object = out->args.vc.data;
6163 ctx->objmask = NULL;
6167 /** Parse eCPRI common header type field. */
6169 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
6170 const char *str, unsigned int len,
6171 void *buf, unsigned int size)
6173 struct rte_flow_item_ecpri *ecpri;
6174 struct rte_flow_item_ecpri *ecpri_mask;
6175 struct rte_flow_item *item;
6178 struct buffer *out = buf;
6179 const struct arg *arg;
6182 /* Token name must match. */
6183 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6185 switch (ctx->curr) {
6186 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
6187 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
6189 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
6190 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
6192 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
6193 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
6200 arg = pop_args(ctx);
6203 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
6204 ecpri->hdr.common.type = msg_type;
6205 data_size = ctx->objdata / 3; /* spec, last, mask */
6206 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
6208 ecpri_mask->hdr.common.type = 0xFF;
6210 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
6211 ecpri_mask->hdr.common.u32 =
6212 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
6214 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6216 item->mask = ecpri_mask;
6220 /** Parse L2TPv2 common header type field. */
6222 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
6223 const char *str, unsigned int len,
6224 void *buf, unsigned int size)
6226 struct rte_flow_item_l2tpv2 *l2tpv2;
6227 struct rte_flow_item_l2tpv2 *l2tpv2_mask;
6228 struct rte_flow_item *item;
6230 uint16_t msg_type = 0;
6231 struct buffer *out = buf;
6232 const struct arg *arg;
6235 /* Token name must match. */
6236 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6238 switch (ctx->curr) {
6239 case ITEM_L2TPV2_TYPE_DATA:
6240 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
6242 case ITEM_L2TPV2_TYPE_DATA_L:
6243 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
6245 case ITEM_L2TPV2_TYPE_DATA_S:
6246 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
6248 case ITEM_L2TPV2_TYPE_DATA_O:
6249 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
6251 case ITEM_L2TPV2_TYPE_DATA_L_S:
6252 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
6254 case ITEM_L2TPV2_TYPE_CTRL:
6255 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
6262 arg = pop_args(ctx);
6265 l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
6266 l2tpv2->hdr.common.flags_version |= msg_type;
6267 data_size = ctx->objdata / 3; /* spec, last, mask */
6268 l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
6270 l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
6272 l2tpv2->hdr.common.flags_version =
6273 rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
6274 l2tpv2_mask->hdr.common.flags_version =
6275 rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
6277 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
6278 item->spec = l2tpv2;
6279 item->mask = l2tpv2_mask;
6283 /** Parse meter color action type. */
6285 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
6286 const char *str, unsigned int len,
6287 void *buf, unsigned int size)
6289 struct rte_flow_action *action_data;
6290 struct rte_flow_action_meter_color *conf;
6291 enum rte_color color;
6295 /* Token name must match. */
6296 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6298 switch (ctx->curr) {
6299 case ACTION_METER_COLOR_GREEN:
6300 color = RTE_COLOR_GREEN;
6302 case ACTION_METER_COLOR_YELLOW:
6303 color = RTE_COLOR_YELLOW;
6305 case ACTION_METER_COLOR_RED:
6306 color = RTE_COLOR_RED;
6314 action_data = ctx->object;
6315 conf = (struct rte_flow_action_meter_color *)
6316 (uintptr_t)(action_data->conf);
6317 conf->color = color;
6321 /** Parse RSS action. */
6323 parse_vc_action_rss(struct context *ctx, const struct token *token,
6324 const char *str, unsigned int len,
6325 void *buf, unsigned int size)
6327 struct buffer *out = buf;
6328 struct rte_flow_action *action;
6329 struct action_rss_data *action_rss_data;
6333 ret = parse_vc(ctx, token, str, len, buf, size);
6336 /* Nothing else to do if there is no buffer. */
6339 if (!out->args.vc.actions_n)
6341 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6342 /* Point to selected object. */
6343 ctx->object = out->args.vc.data;
6344 ctx->objmask = NULL;
6345 /* Set up default configuration. */
6346 action_rss_data = ctx->object;
6347 *action_rss_data = (struct action_rss_data){
6348 .conf = (struct rte_flow_action_rss){
6349 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
6353 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
6355 .queue = action_rss_data->queue,
6359 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
6360 action_rss_data->queue[i] = i;
6361 action->conf = &action_rss_data->conf;
6366 * Parse func field for RSS action.
6368 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
6369 * ACTION_RSS_FUNC_* index that called this function.
6372 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
6373 const char *str, unsigned int len,
6374 void *buf, unsigned int size)
6376 struct action_rss_data *action_rss_data;
6377 enum rte_eth_hash_function func;
6381 /* Token name must match. */
6382 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6384 switch (ctx->curr) {
6385 case ACTION_RSS_FUNC_DEFAULT:
6386 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
6388 case ACTION_RSS_FUNC_TOEPLITZ:
6389 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
6391 case ACTION_RSS_FUNC_SIMPLE_XOR:
6392 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
6394 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
6395 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
6402 action_rss_data = ctx->object;
6403 action_rss_data->conf.func = func;
6408 * Parse type field for RSS action.
6410 * Valid tokens are type field names and the "end" token.
6413 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
6414 const char *str, unsigned int len,
6415 void *buf, unsigned int size)
6417 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
6418 struct action_rss_data *action_rss_data;
6424 if (ctx->curr != ACTION_RSS_TYPE)
6426 if (!(ctx->objdata >> 16) && ctx->object) {
6427 action_rss_data = ctx->object;
6428 action_rss_data->conf.types = 0;
6430 if (!strcmp_partial("end", str, len)) {
6431 ctx->objdata &= 0xffff;
6434 for (i = 0; rss_type_table[i].str; ++i)
6435 if (!strcmp_partial(rss_type_table[i].str, str, len))
6437 if (!rss_type_table[i].str)
6439 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
6441 if (ctx->next_num == RTE_DIM(ctx->next))
6443 ctx->next[ctx->next_num++] = next;
6446 action_rss_data = ctx->object;
6447 action_rss_data->conf.types |= rss_type_table[i].rss_type;
6452 * Parse queue field for RSS action.
6454 * Valid tokens are queue indices and the "end" token.
6457 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
6458 const char *str, unsigned int len,
6459 void *buf, unsigned int size)
6461 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
6462 struct action_rss_data *action_rss_data;
6463 const struct arg *arg;
6470 if (ctx->curr != ACTION_RSS_QUEUE)
6472 i = ctx->objdata >> 16;
6473 if (!strcmp_partial("end", str, len)) {
6474 ctx->objdata &= 0xffff;
6477 if (i >= ACTION_RSS_QUEUE_NUM)
6479 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
6480 i * sizeof(action_rss_data->queue[i]),
6481 sizeof(action_rss_data->queue[i]));
6482 if (push_args(ctx, arg))
6484 ret = parse_int(ctx, token, str, len, NULL, 0);
6490 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
6492 if (ctx->next_num == RTE_DIM(ctx->next))
6494 ctx->next[ctx->next_num++] = next;
6498 action_rss_data = ctx->object;
6499 action_rss_data->conf.queue_num = i;
6500 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
6504 /** Setup VXLAN encap configuration. */
6506 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
6508 /* Set up default configuration. */
6509 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
6510 .conf = (struct rte_flow_action_vxlan_encap){
6511 .definition = action_vxlan_encap_data->items,
6515 .type = RTE_FLOW_ITEM_TYPE_ETH,
6516 .spec = &action_vxlan_encap_data->item_eth,
6517 .mask = &rte_flow_item_eth_mask,
6520 .type = RTE_FLOW_ITEM_TYPE_VLAN,
6521 .spec = &action_vxlan_encap_data->item_vlan,
6522 .mask = &rte_flow_item_vlan_mask,
6525 .type = RTE_FLOW_ITEM_TYPE_IPV4,
6526 .spec = &action_vxlan_encap_data->item_ipv4,
6527 .mask = &rte_flow_item_ipv4_mask,
6530 .type = RTE_FLOW_ITEM_TYPE_UDP,
6531 .spec = &action_vxlan_encap_data->item_udp,
6532 .mask = &rte_flow_item_udp_mask,
6535 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
6536 .spec = &action_vxlan_encap_data->item_vxlan,
6537 .mask = &rte_flow_item_vxlan_mask,
6540 .type = RTE_FLOW_ITEM_TYPE_END,
6545 .tci = vxlan_encap_conf.vlan_tci,
6549 .src_addr = vxlan_encap_conf.ipv4_src,
6550 .dst_addr = vxlan_encap_conf.ipv4_dst,
6553 .src_port = vxlan_encap_conf.udp_src,
6554 .dst_port = vxlan_encap_conf.udp_dst,
6556 .item_vxlan.flags = 0,
6558 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
6559 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6560 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
6561 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6562 if (!vxlan_encap_conf.select_ipv4) {
6563 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
6564 &vxlan_encap_conf.ipv6_src,
6565 sizeof(vxlan_encap_conf.ipv6_src));
6566 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
6567 &vxlan_encap_conf.ipv6_dst,
6568 sizeof(vxlan_encap_conf.ipv6_dst));
6569 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
6570 .type = RTE_FLOW_ITEM_TYPE_IPV6,
6571 .spec = &action_vxlan_encap_data->item_ipv6,
6572 .mask = &rte_flow_item_ipv6_mask,
6575 if (!vxlan_encap_conf.select_vlan)
6576 action_vxlan_encap_data->items[1].type =
6577 RTE_FLOW_ITEM_TYPE_VOID;
6578 if (vxlan_encap_conf.select_tos_ttl) {
6579 if (vxlan_encap_conf.select_ipv4) {
6580 static struct rte_flow_item_ipv4 ipv4_mask_tos;
6582 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
6583 sizeof(ipv4_mask_tos));
6584 ipv4_mask_tos.hdr.type_of_service = 0xff;
6585 ipv4_mask_tos.hdr.time_to_live = 0xff;
6586 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
6587 vxlan_encap_conf.ip_tos;
6588 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
6589 vxlan_encap_conf.ip_ttl;
6590 action_vxlan_encap_data->items[2].mask =
6593 static struct rte_flow_item_ipv6 ipv6_mask_tos;
6595 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
6596 sizeof(ipv6_mask_tos));
6597 ipv6_mask_tos.hdr.vtc_flow |=
6598 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
6599 ipv6_mask_tos.hdr.hop_limits = 0xff;
6600 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
6602 ((uint32_t)vxlan_encap_conf.ip_tos <<
6603 RTE_IPV6_HDR_TC_SHIFT);
6604 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
6605 vxlan_encap_conf.ip_ttl;
6606 action_vxlan_encap_data->items[2].mask =
6610 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
6611 RTE_DIM(vxlan_encap_conf.vni));
6615 /** Parse VXLAN encap action. */
6617 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
6618 const char *str, unsigned int len,
6619 void *buf, unsigned int size)
6621 struct buffer *out = buf;
6622 struct rte_flow_action *action;
6623 struct action_vxlan_encap_data *action_vxlan_encap_data;
6626 ret = parse_vc(ctx, token, str, len, buf, size);
6629 /* Nothing else to do if there is no buffer. */
6632 if (!out->args.vc.actions_n)
6634 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6635 /* Point to selected object. */
6636 ctx->object = out->args.vc.data;
6637 ctx->objmask = NULL;
6638 action_vxlan_encap_data = ctx->object;
6639 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
6640 action->conf = &action_vxlan_encap_data->conf;
6644 /** Setup NVGRE encap configuration. */
6646 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
6648 /* Set up default configuration. */
6649 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
6650 .conf = (struct rte_flow_action_nvgre_encap){
6651 .definition = action_nvgre_encap_data->items,
6655 .type = RTE_FLOW_ITEM_TYPE_ETH,
6656 .spec = &action_nvgre_encap_data->item_eth,
6657 .mask = &rte_flow_item_eth_mask,
6660 .type = RTE_FLOW_ITEM_TYPE_VLAN,
6661 .spec = &action_nvgre_encap_data->item_vlan,
6662 .mask = &rte_flow_item_vlan_mask,
6665 .type = RTE_FLOW_ITEM_TYPE_IPV4,
6666 .spec = &action_nvgre_encap_data->item_ipv4,
6667 .mask = &rte_flow_item_ipv4_mask,
6670 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
6671 .spec = &action_nvgre_encap_data->item_nvgre,
6672 .mask = &rte_flow_item_nvgre_mask,
6675 .type = RTE_FLOW_ITEM_TYPE_END,
6680 .tci = nvgre_encap_conf.vlan_tci,
6684 .src_addr = nvgre_encap_conf.ipv4_src,
6685 .dst_addr = nvgre_encap_conf.ipv4_dst,
6687 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
6688 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
6689 .item_nvgre.flow_id = 0,
6691 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
6692 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6693 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
6694 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6695 if (!nvgre_encap_conf.select_ipv4) {
6696 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
6697 &nvgre_encap_conf.ipv6_src,
6698 sizeof(nvgre_encap_conf.ipv6_src));
6699 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
6700 &nvgre_encap_conf.ipv6_dst,
6701 sizeof(nvgre_encap_conf.ipv6_dst));
6702 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
6703 .type = RTE_FLOW_ITEM_TYPE_IPV6,
6704 .spec = &action_nvgre_encap_data->item_ipv6,
6705 .mask = &rte_flow_item_ipv6_mask,
6708 if (!nvgre_encap_conf.select_vlan)
6709 action_nvgre_encap_data->items[1].type =
6710 RTE_FLOW_ITEM_TYPE_VOID;
6711 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
6712 RTE_DIM(nvgre_encap_conf.tni));
6716 /** Parse NVGRE encap action. */
6718 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
6719 const char *str, unsigned int len,
6720 void *buf, unsigned int size)
6722 struct buffer *out = buf;
6723 struct rte_flow_action *action;
6724 struct action_nvgre_encap_data *action_nvgre_encap_data;
6727 ret = parse_vc(ctx, token, str, len, buf, size);
6730 /* Nothing else to do if there is no buffer. */
6733 if (!out->args.vc.actions_n)
6735 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6736 /* Point to selected object. */
6737 ctx->object = out->args.vc.data;
6738 ctx->objmask = NULL;
6739 action_nvgre_encap_data = ctx->object;
6740 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
6741 action->conf = &action_nvgre_encap_data->conf;
6745 /** Parse l2 encap action. */
6747 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
6748 const char *str, unsigned int len,
6749 void *buf, unsigned int size)
6751 struct buffer *out = buf;
6752 struct rte_flow_action *action;
6753 struct action_raw_encap_data *action_encap_data;
6754 struct rte_flow_item_eth eth = { .type = 0, };
6755 struct rte_flow_item_vlan vlan = {
6756 .tci = mplsoudp_encap_conf.vlan_tci,
6762 ret = parse_vc(ctx, token, str, len, buf, size);
6765 /* Nothing else to do if there is no buffer. */
6768 if (!out->args.vc.actions_n)
6770 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6771 /* Point to selected object. */
6772 ctx->object = out->args.vc.data;
6773 ctx->objmask = NULL;
6774 /* Copy the headers to the buffer. */
6775 action_encap_data = ctx->object;
6776 *action_encap_data = (struct action_raw_encap_data) {
6777 .conf = (struct rte_flow_action_raw_encap){
6778 .data = action_encap_data->data,
6782 header = action_encap_data->data;
6783 if (l2_encap_conf.select_vlan)
6784 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6785 else if (l2_encap_conf.select_ipv4)
6786 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6788 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6789 memcpy(eth.dst.addr_bytes,
6790 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6791 memcpy(eth.src.addr_bytes,
6792 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6793 memcpy(header, ð, sizeof(eth));
6794 header += sizeof(eth);
6795 if (l2_encap_conf.select_vlan) {
6796 if (l2_encap_conf.select_ipv4)
6797 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6799 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6800 memcpy(header, &vlan, sizeof(vlan));
6801 header += sizeof(vlan);
6803 action_encap_data->conf.size = header -
6804 action_encap_data->data;
6805 action->conf = &action_encap_data->conf;
6809 /** Parse l2 decap action. */
6811 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
6812 const char *str, unsigned int len,
6813 void *buf, unsigned int size)
6815 struct buffer *out = buf;
6816 struct rte_flow_action *action;
6817 struct action_raw_decap_data *action_decap_data;
6818 struct rte_flow_item_eth eth = { .type = 0, };
6819 struct rte_flow_item_vlan vlan = {
6820 .tci = mplsoudp_encap_conf.vlan_tci,
6826 ret = parse_vc(ctx, token, str, len, buf, size);
6829 /* Nothing else to do if there is no buffer. */
6832 if (!out->args.vc.actions_n)
6834 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6835 /* Point to selected object. */
6836 ctx->object = out->args.vc.data;
6837 ctx->objmask = NULL;
6838 /* Copy the headers to the buffer. */
6839 action_decap_data = ctx->object;
6840 *action_decap_data = (struct action_raw_decap_data) {
6841 .conf = (struct rte_flow_action_raw_decap){
6842 .data = action_decap_data->data,
6846 header = action_decap_data->data;
6847 if (l2_decap_conf.select_vlan)
6848 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6849 memcpy(header, ð, sizeof(eth));
6850 header += sizeof(eth);
6851 if (l2_decap_conf.select_vlan) {
6852 memcpy(header, &vlan, sizeof(vlan));
6853 header += sizeof(vlan);
6855 action_decap_data->conf.size = header -
6856 action_decap_data->data;
6857 action->conf = &action_decap_data->conf;
6861 #define ETHER_TYPE_MPLS_UNICAST 0x8847
6863 /** Parse MPLSOGRE encap action. */
6865 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
6866 const char *str, unsigned int len,
6867 void *buf, unsigned int size)
6869 struct buffer *out = buf;
6870 struct rte_flow_action *action;
6871 struct action_raw_encap_data *action_encap_data;
6872 struct rte_flow_item_eth eth = { .type = 0, };
6873 struct rte_flow_item_vlan vlan = {
6874 .tci = mplsogre_encap_conf.vlan_tci,
6877 struct rte_flow_item_ipv4 ipv4 = {
6879 .src_addr = mplsogre_encap_conf.ipv4_src,
6880 .dst_addr = mplsogre_encap_conf.ipv4_dst,
6881 .next_proto_id = IPPROTO_GRE,
6882 .version_ihl = RTE_IPV4_VHL_DEF,
6883 .time_to_live = IPDEFTTL,
6886 struct rte_flow_item_ipv6 ipv6 = {
6888 .proto = IPPROTO_GRE,
6889 .hop_limits = IPDEFTTL,
6892 struct rte_flow_item_gre gre = {
6893 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6895 struct rte_flow_item_mpls mpls = {
6901 ret = parse_vc(ctx, token, str, len, buf, size);
6904 /* Nothing else to do if there is no buffer. */
6907 if (!out->args.vc.actions_n)
6909 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6910 /* Point to selected object. */
6911 ctx->object = out->args.vc.data;
6912 ctx->objmask = NULL;
6913 /* Copy the headers to the buffer. */
6914 action_encap_data = ctx->object;
6915 *action_encap_data = (struct action_raw_encap_data) {
6916 .conf = (struct rte_flow_action_raw_encap){
6917 .data = action_encap_data->data,
6922 header = action_encap_data->data;
6923 if (mplsogre_encap_conf.select_vlan)
6924 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6925 else if (mplsogre_encap_conf.select_ipv4)
6926 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6928 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6929 memcpy(eth.dst.addr_bytes,
6930 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6931 memcpy(eth.src.addr_bytes,
6932 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6933 memcpy(header, ð, sizeof(eth));
6934 header += sizeof(eth);
6935 if (mplsogre_encap_conf.select_vlan) {
6936 if (mplsogre_encap_conf.select_ipv4)
6937 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6939 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6940 memcpy(header, &vlan, sizeof(vlan));
6941 header += sizeof(vlan);
6943 if (mplsogre_encap_conf.select_ipv4) {
6944 memcpy(header, &ipv4, sizeof(ipv4));
6945 header += sizeof(ipv4);
6947 memcpy(&ipv6.hdr.src_addr,
6948 &mplsogre_encap_conf.ipv6_src,
6949 sizeof(mplsogre_encap_conf.ipv6_src));
6950 memcpy(&ipv6.hdr.dst_addr,
6951 &mplsogre_encap_conf.ipv6_dst,
6952 sizeof(mplsogre_encap_conf.ipv6_dst));
6953 memcpy(header, &ipv6, sizeof(ipv6));
6954 header += sizeof(ipv6);
6956 memcpy(header, &gre, sizeof(gre));
6957 header += sizeof(gre);
6958 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
6959 RTE_DIM(mplsogre_encap_conf.label));
6960 mpls.label_tc_s[2] |= 0x1;
6961 memcpy(header, &mpls, sizeof(mpls));
6962 header += sizeof(mpls);
6963 action_encap_data->conf.size = header -
6964 action_encap_data->data;
6965 action->conf = &action_encap_data->conf;
6969 /** Parse MPLSOGRE decap action. */
6971 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
6972 const char *str, unsigned int len,
6973 void *buf, unsigned int size)
6975 struct buffer *out = buf;
6976 struct rte_flow_action *action;
6977 struct action_raw_decap_data *action_decap_data;
6978 struct rte_flow_item_eth eth = { .type = 0, };
6979 struct rte_flow_item_vlan vlan = {.tci = 0};
6980 struct rte_flow_item_ipv4 ipv4 = {
6982 .next_proto_id = IPPROTO_GRE,
6985 struct rte_flow_item_ipv6 ipv6 = {
6987 .proto = IPPROTO_GRE,
6990 struct rte_flow_item_gre gre = {
6991 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6993 struct rte_flow_item_mpls mpls;
6997 ret = parse_vc(ctx, token, str, len, buf, size);
7000 /* Nothing else to do if there is no buffer. */
7003 if (!out->args.vc.actions_n)
7005 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7006 /* Point to selected object. */
7007 ctx->object = out->args.vc.data;
7008 ctx->objmask = NULL;
7009 /* Copy the headers to the buffer. */
7010 action_decap_data = ctx->object;
7011 *action_decap_data = (struct action_raw_decap_data) {
7012 .conf = (struct rte_flow_action_raw_decap){
7013 .data = action_decap_data->data,
7017 header = action_decap_data->data;
7018 if (mplsogre_decap_conf.select_vlan)
7019 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7020 else if (mplsogre_encap_conf.select_ipv4)
7021 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7023 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7024 memcpy(eth.dst.addr_bytes,
7025 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7026 memcpy(eth.src.addr_bytes,
7027 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7028 memcpy(header, ð, sizeof(eth));
7029 header += sizeof(eth);
7030 if (mplsogre_encap_conf.select_vlan) {
7031 if (mplsogre_encap_conf.select_ipv4)
7032 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7034 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7035 memcpy(header, &vlan, sizeof(vlan));
7036 header += sizeof(vlan);
7038 if (mplsogre_encap_conf.select_ipv4) {
7039 memcpy(header, &ipv4, sizeof(ipv4));
7040 header += sizeof(ipv4);
7042 memcpy(header, &ipv6, sizeof(ipv6));
7043 header += sizeof(ipv6);
7045 memcpy(header, &gre, sizeof(gre));
7046 header += sizeof(gre);
7047 memset(&mpls, 0, sizeof(mpls));
7048 memcpy(header, &mpls, sizeof(mpls));
7049 header += sizeof(mpls);
7050 action_decap_data->conf.size = header -
7051 action_decap_data->data;
7052 action->conf = &action_decap_data->conf;
7056 /** Parse MPLSOUDP encap action. */
7058 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
7059 const char *str, unsigned int len,
7060 void *buf, unsigned int size)
7062 struct buffer *out = buf;
7063 struct rte_flow_action *action;
7064 struct action_raw_encap_data *action_encap_data;
7065 struct rte_flow_item_eth eth = { .type = 0, };
7066 struct rte_flow_item_vlan vlan = {
7067 .tci = mplsoudp_encap_conf.vlan_tci,
7070 struct rte_flow_item_ipv4 ipv4 = {
7072 .src_addr = mplsoudp_encap_conf.ipv4_src,
7073 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
7074 .next_proto_id = IPPROTO_UDP,
7075 .version_ihl = RTE_IPV4_VHL_DEF,
7076 .time_to_live = IPDEFTTL,
7079 struct rte_flow_item_ipv6 ipv6 = {
7081 .proto = IPPROTO_UDP,
7082 .hop_limits = IPDEFTTL,
7085 struct rte_flow_item_udp udp = {
7087 .src_port = mplsoudp_encap_conf.udp_src,
7088 .dst_port = mplsoudp_encap_conf.udp_dst,
7091 struct rte_flow_item_mpls mpls;
7095 ret = parse_vc(ctx, token, str, len, buf, size);
7098 /* Nothing else to do if there is no buffer. */
7101 if (!out->args.vc.actions_n)
7103 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7104 /* Point to selected object. */
7105 ctx->object = out->args.vc.data;
7106 ctx->objmask = NULL;
7107 /* Copy the headers to the buffer. */
7108 action_encap_data = ctx->object;
7109 *action_encap_data = (struct action_raw_encap_data) {
7110 .conf = (struct rte_flow_action_raw_encap){
7111 .data = action_encap_data->data,
7116 header = action_encap_data->data;
7117 if (mplsoudp_encap_conf.select_vlan)
7118 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7119 else if (mplsoudp_encap_conf.select_ipv4)
7120 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7122 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7123 memcpy(eth.dst.addr_bytes,
7124 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7125 memcpy(eth.src.addr_bytes,
7126 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7127 memcpy(header, ð, sizeof(eth));
7128 header += sizeof(eth);
7129 if (mplsoudp_encap_conf.select_vlan) {
7130 if (mplsoudp_encap_conf.select_ipv4)
7131 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7133 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7134 memcpy(header, &vlan, sizeof(vlan));
7135 header += sizeof(vlan);
7137 if (mplsoudp_encap_conf.select_ipv4) {
7138 memcpy(header, &ipv4, sizeof(ipv4));
7139 header += sizeof(ipv4);
7141 memcpy(&ipv6.hdr.src_addr,
7142 &mplsoudp_encap_conf.ipv6_src,
7143 sizeof(mplsoudp_encap_conf.ipv6_src));
7144 memcpy(&ipv6.hdr.dst_addr,
7145 &mplsoudp_encap_conf.ipv6_dst,
7146 sizeof(mplsoudp_encap_conf.ipv6_dst));
7147 memcpy(header, &ipv6, sizeof(ipv6));
7148 header += sizeof(ipv6);
7150 memcpy(header, &udp, sizeof(udp));
7151 header += sizeof(udp);
7152 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
7153 RTE_DIM(mplsoudp_encap_conf.label));
7154 mpls.label_tc_s[2] |= 0x1;
7155 memcpy(header, &mpls, sizeof(mpls));
7156 header += sizeof(mpls);
7157 action_encap_data->conf.size = header -
7158 action_encap_data->data;
7159 action->conf = &action_encap_data->conf;
7163 /** Parse MPLSOUDP decap action. */
7165 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
7166 const char *str, unsigned int len,
7167 void *buf, unsigned int size)
7169 struct buffer *out = buf;
7170 struct rte_flow_action *action;
7171 struct action_raw_decap_data *action_decap_data;
7172 struct rte_flow_item_eth eth = { .type = 0, };
7173 struct rte_flow_item_vlan vlan = {.tci = 0};
7174 struct rte_flow_item_ipv4 ipv4 = {
7176 .next_proto_id = IPPROTO_UDP,
7179 struct rte_flow_item_ipv6 ipv6 = {
7181 .proto = IPPROTO_UDP,
7184 struct rte_flow_item_udp udp = {
7186 .dst_port = rte_cpu_to_be_16(6635),
7189 struct rte_flow_item_mpls mpls;
7193 ret = parse_vc(ctx, token, str, len, buf, size);
7196 /* Nothing else to do if there is no buffer. */
7199 if (!out->args.vc.actions_n)
7201 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7202 /* Point to selected object. */
7203 ctx->object = out->args.vc.data;
7204 ctx->objmask = NULL;
7205 /* Copy the headers to the buffer. */
7206 action_decap_data = ctx->object;
7207 *action_decap_data = (struct action_raw_decap_data) {
7208 .conf = (struct rte_flow_action_raw_decap){
7209 .data = action_decap_data->data,
7213 header = action_decap_data->data;
7214 if (mplsoudp_decap_conf.select_vlan)
7215 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
7216 else if (mplsoudp_encap_conf.select_ipv4)
7217 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7219 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7220 memcpy(eth.dst.addr_bytes,
7221 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
7222 memcpy(eth.src.addr_bytes,
7223 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
7224 memcpy(header, ð, sizeof(eth));
7225 header += sizeof(eth);
7226 if (mplsoudp_encap_conf.select_vlan) {
7227 if (mplsoudp_encap_conf.select_ipv4)
7228 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
7230 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
7231 memcpy(header, &vlan, sizeof(vlan));
7232 header += sizeof(vlan);
7234 if (mplsoudp_encap_conf.select_ipv4) {
7235 memcpy(header, &ipv4, sizeof(ipv4));
7236 header += sizeof(ipv4);
7238 memcpy(header, &ipv6, sizeof(ipv6));
7239 header += sizeof(ipv6);
7241 memcpy(header, &udp, sizeof(udp));
7242 header += sizeof(udp);
7243 memset(&mpls, 0, sizeof(mpls));
7244 memcpy(header, &mpls, sizeof(mpls));
7245 header += sizeof(mpls);
7246 action_decap_data->conf.size = header -
7247 action_decap_data->data;
7248 action->conf = &action_decap_data->conf;
7253 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
7254 const char *str, unsigned int len, void *buf,
7257 struct action_raw_decap_data *action_raw_decap_data;
7258 struct rte_flow_action *action;
7259 const struct arg *arg;
7260 struct buffer *out = buf;
7264 RTE_SET_USED(token);
7267 arg = ARGS_ENTRY_ARB_BOUNDED
7268 (offsetof(struct action_raw_decap_data, idx),
7269 sizeof(((struct action_raw_decap_data *)0)->idx),
7270 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7271 if (push_args(ctx, arg))
7273 ret = parse_int(ctx, token, str, len, NULL, 0);
7280 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7281 action_raw_decap_data = ctx->object;
7282 idx = action_raw_decap_data->idx;
7283 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
7284 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
7285 action->conf = &action_raw_decap_data->conf;
7291 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
7292 const char *str, unsigned int len, void *buf,
7295 struct action_raw_encap_data *action_raw_encap_data;
7296 struct rte_flow_action *action;
7297 const struct arg *arg;
7298 struct buffer *out = buf;
7302 RTE_SET_USED(token);
7305 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
7307 arg = ARGS_ENTRY_ARB_BOUNDED
7308 (offsetof(struct action_raw_encap_data, idx),
7309 sizeof(((struct action_raw_encap_data *)0)->idx),
7310 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
7311 if (push_args(ctx, arg))
7313 ret = parse_int(ctx, token, str, len, NULL, 0);
7320 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7321 action_raw_encap_data = ctx->object;
7322 idx = action_raw_encap_data->idx;
7323 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
7324 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
7325 action_raw_encap_data->conf.preserve = NULL;
7326 action->conf = &action_raw_encap_data->conf;
7331 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
7332 const char *str, unsigned int len, void *buf,
7335 struct buffer *out = buf;
7336 struct rte_flow_action *action;
7337 struct action_raw_encap_data *action_raw_encap_data = NULL;
7340 ret = parse_vc(ctx, token, str, len, buf, size);
7343 /* Nothing else to do if there is no buffer. */
7346 if (!out->args.vc.actions_n)
7348 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7349 /* Point to selected object. */
7350 ctx->object = out->args.vc.data;
7351 ctx->objmask = NULL;
7352 /* Copy the headers to the buffer. */
7353 action_raw_encap_data = ctx->object;
7354 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
7355 action_raw_encap_data->conf.preserve = NULL;
7356 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
7357 action->conf = &action_raw_encap_data->conf;
7362 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
7363 const char *str, unsigned int len, void *buf,
7366 struct buffer *out = buf;
7367 struct rte_flow_action *action;
7368 struct action_raw_decap_data *action_raw_decap_data = NULL;
7371 ret = parse_vc(ctx, token, str, len, buf, size);
7374 /* Nothing else to do if there is no buffer. */
7377 if (!out->args.vc.actions_n)
7379 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7380 /* Point to selected object. */
7381 ctx->object = out->args.vc.data;
7382 ctx->objmask = NULL;
7383 /* Copy the headers to the buffer. */
7384 action_raw_decap_data = ctx->object;
7385 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
7386 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
7387 action->conf = &action_raw_decap_data->conf;
7392 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
7393 const char *str, unsigned int len, void *buf,
7398 ret = parse_vc(ctx, token, str, len, buf, size);
7401 ret = rte_flow_dynf_metadata_register();
7408 parse_vc_action_sample(struct context *ctx, const struct token *token,
7409 const char *str, unsigned int len, void *buf,
7412 struct buffer *out = buf;
7413 struct rte_flow_action *action;
7414 struct action_sample_data *action_sample_data = NULL;
7415 static struct rte_flow_action end_action = {
7416 RTE_FLOW_ACTION_TYPE_END, 0
7420 ret = parse_vc(ctx, token, str, len, buf, size);
7423 /* Nothing else to do if there is no buffer. */
7426 if (!out->args.vc.actions_n)
7428 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7429 /* Point to selected object. */
7430 ctx->object = out->args.vc.data;
7431 ctx->objmask = NULL;
7432 /* Copy the headers to the buffer. */
7433 action_sample_data = ctx->object;
7434 action_sample_data->conf.actions = &end_action;
7435 action->conf = &action_sample_data->conf;
7440 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
7441 const char *str, unsigned int len, void *buf,
7444 struct action_sample_data *action_sample_data;
7445 struct rte_flow_action *action;
7446 const struct arg *arg;
7447 struct buffer *out = buf;
7451 RTE_SET_USED(token);
7454 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
7456 arg = ARGS_ENTRY_ARB_BOUNDED
7457 (offsetof(struct action_sample_data, idx),
7458 sizeof(((struct action_sample_data *)0)->idx),
7459 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
7460 if (push_args(ctx, arg))
7462 ret = parse_int(ctx, token, str, len, NULL, 0);
7469 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7470 action_sample_data = ctx->object;
7471 idx = action_sample_data->idx;
7472 action_sample_data->conf.actions = raw_sample_confs[idx].data;
7473 action->conf = &action_sample_data->conf;
7477 /** Parse operation for modify_field command. */
7479 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
7480 const char *str, unsigned int len, void *buf,
7483 struct rte_flow_action_modify_field *action_modify_field;
7489 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
7491 for (i = 0; modify_field_ops[i]; ++i)
7492 if (!strcmp_partial(modify_field_ops[i], str, len))
7494 if (!modify_field_ops[i])
7498 action_modify_field = ctx->object;
7499 action_modify_field->operation = (enum rte_flow_modify_op)i;
7503 /** Parse id for modify_field command. */
7505 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
7506 const char *str, unsigned int len, void *buf,
7509 struct rte_flow_action_modify_field *action_modify_field;
7515 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
7516 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
7518 for (i = 0; modify_field_ids[i]; ++i)
7519 if (!strcmp_partial(modify_field_ids[i], str, len))
7521 if (!modify_field_ids[i])
7525 action_modify_field = ctx->object;
7526 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
7527 action_modify_field->dst.field = (enum rte_flow_field_id)i;
7529 action_modify_field->src.field = (enum rte_flow_field_id)i;
7533 /** Parse the conntrack update, not a rte_flow_action. */
7535 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
7536 const char *str, unsigned int len, void *buf,
7539 struct buffer *out = buf;
7540 struct rte_flow_modify_conntrack *ct_modify = NULL;
7543 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
7544 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
7546 /* Token name must match. */
7547 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7549 /* Nothing else to do if there is no buffer. */
7552 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
7553 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
7554 ct_modify->new_ct.is_original_dir =
7555 conntrack_context.is_original_dir;
7556 ct_modify->direction = 1;
7560 old_dir = ct_modify->new_ct.is_original_dir;
7561 memcpy(&ct_modify->new_ct, &conntrack_context,
7562 sizeof(conntrack_context));
7563 ct_modify->new_ct.is_original_dir = old_dir;
7564 ct_modify->state = 1;
7569 /** Parse tokens for destroy command. */
7571 parse_destroy(struct context *ctx, const struct token *token,
7572 const char *str, unsigned int len,
7573 void *buf, unsigned int size)
7575 struct buffer *out = buf;
7577 /* Token name must match. */
7578 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7580 /* Nothing else to do if there is no buffer. */
7583 if (!out->command) {
7584 if (ctx->curr != DESTROY)
7586 if (sizeof(*out) > size)
7588 out->command = ctx->curr;
7591 ctx->objmask = NULL;
7592 out->args.destroy.rule =
7593 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7597 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
7598 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
7601 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
7602 ctx->objmask = NULL;
7606 /** Parse tokens for flush command. */
7608 parse_flush(struct context *ctx, const struct token *token,
7609 const char *str, unsigned int len,
7610 void *buf, unsigned int size)
7612 struct buffer *out = buf;
7614 /* Token name must match. */
7615 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7617 /* Nothing else to do if there is no buffer. */
7620 if (!out->command) {
7621 if (ctx->curr != FLUSH)
7623 if (sizeof(*out) > size)
7625 out->command = ctx->curr;
7628 ctx->objmask = NULL;
7633 /** Parse tokens for dump command. */
7635 parse_dump(struct context *ctx, const struct token *token,
7636 const char *str, unsigned int len,
7637 void *buf, unsigned int size)
7639 struct buffer *out = buf;
7641 /* Token name must match. */
7642 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7644 /* Nothing else to do if there is no buffer. */
7647 if (!out->command) {
7648 if (ctx->curr != DUMP)
7650 if (sizeof(*out) > size)
7652 out->command = ctx->curr;
7655 ctx->objmask = NULL;
7658 switch (ctx->curr) {
7661 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
7662 out->command = ctx->curr;
7665 ctx->objmask = NULL;
7672 /** Parse tokens for query command. */
7674 parse_query(struct context *ctx, const struct token *token,
7675 const char *str, unsigned int len,
7676 void *buf, unsigned int size)
7678 struct buffer *out = buf;
7680 /* Token name must match. */
7681 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7683 /* Nothing else to do if there is no buffer. */
7686 if (!out->command) {
7687 if (ctx->curr != QUERY)
7689 if (sizeof(*out) > size)
7691 out->command = ctx->curr;
7694 ctx->objmask = NULL;
7699 /** Parse action names. */
7701 parse_action(struct context *ctx, const struct token *token,
7702 const char *str, unsigned int len,
7703 void *buf, unsigned int size)
7705 struct buffer *out = buf;
7706 const struct arg *arg = pop_args(ctx);
7710 /* Argument is expected. */
7713 /* Parse action name. */
7714 for (i = 0; next_action[i]; ++i) {
7715 const struct parse_action_priv *priv;
7717 token = &token_list[next_action[i]];
7718 if (strcmp_partial(token->name, str, len))
7724 memcpy((uint8_t *)ctx->object + arg->offset,
7730 push_args(ctx, arg);
7734 /** Parse tokens for list command. */
7736 parse_list(struct context *ctx, const struct token *token,
7737 const char *str, unsigned int len,
7738 void *buf, unsigned int size)
7740 struct buffer *out = buf;
7742 /* Token name must match. */
7743 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7745 /* Nothing else to do if there is no buffer. */
7748 if (!out->command) {
7749 if (ctx->curr != LIST)
7751 if (sizeof(*out) > size)
7753 out->command = ctx->curr;
7756 ctx->objmask = NULL;
7757 out->args.list.group =
7758 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7762 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
7763 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
7766 ctx->object = out->args.list.group + out->args.list.group_n++;
7767 ctx->objmask = NULL;
7771 /** Parse tokens for list all aged flows command. */
7773 parse_aged(struct context *ctx, const struct token *token,
7774 const char *str, unsigned int len,
7775 void *buf, unsigned int size)
7777 struct buffer *out = buf;
7779 /* Token name must match. */
7780 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7782 /* Nothing else to do if there is no buffer. */
7785 if (!out->command) {
7786 if (ctx->curr != AGED)
7788 if (sizeof(*out) > size)
7790 out->command = ctx->curr;
7793 ctx->objmask = NULL;
7795 if (ctx->curr == AGED_DESTROY)
7796 out->args.aged.destroy = 1;
7800 /** Parse tokens for isolate command. */
7802 parse_isolate(struct context *ctx, const struct token *token,
7803 const char *str, unsigned int len,
7804 void *buf, unsigned int size)
7806 struct buffer *out = buf;
7808 /* Token name must match. */
7809 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7811 /* Nothing else to do if there is no buffer. */
7814 if (!out->command) {
7815 if (ctx->curr != ISOLATE)
7817 if (sizeof(*out) > size)
7819 out->command = ctx->curr;
7822 ctx->objmask = NULL;
7827 /** Parse tokens for info/configure command. */
7829 parse_configure(struct context *ctx, const struct token *token,
7830 const char *str, unsigned int len,
7831 void *buf, unsigned int size)
7833 struct buffer *out = buf;
7835 /* Token name must match. */
7836 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7838 /* Nothing else to do if there is no buffer. */
7841 if (!out->command) {
7842 if (ctx->curr != INFO && ctx->curr != CONFIGURE)
7844 if (sizeof(*out) > size)
7846 out->command = ctx->curr;
7849 ctx->objmask = NULL;
7855 parse_flex(struct context *ctx, const struct token *token,
7856 const char *str, unsigned int len,
7857 void *buf, unsigned int size)
7859 struct buffer *out = buf;
7861 /* Token name must match. */
7862 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7864 /* Nothing else to do if there is no buffer. */
7867 if (out->command == ZERO) {
7868 if (ctx->curr != FLEX)
7870 if (sizeof(*out) > size)
7872 out->command = ctx->curr;
7875 ctx->objmask = NULL;
7877 switch (ctx->curr) {
7880 case FLEX_ITEM_INIT:
7881 case FLEX_ITEM_CREATE:
7882 case FLEX_ITEM_DESTROY:
7883 out->command = ctx->curr;
7892 parse_tunnel(struct context *ctx, const struct token *token,
7893 const char *str, unsigned int len,
7894 void *buf, unsigned int size)
7896 struct buffer *out = buf;
7898 /* Token name must match. */
7899 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7901 /* Nothing else to do if there is no buffer. */
7904 if (!out->command) {
7905 if (ctx->curr != TUNNEL)
7907 if (sizeof(*out) > size)
7909 out->command = ctx->curr;
7912 ctx->objmask = NULL;
7914 switch (ctx->curr) {
7918 case TUNNEL_DESTROY:
7920 out->command = ctx->curr;
7922 case TUNNEL_CREATE_TYPE:
7923 case TUNNEL_DESTROY_ID:
7924 ctx->object = &out->args.vc.tunnel_ops;
7933 * Parse signed/unsigned integers 8 to 64-bit long.
7935 * Last argument (ctx->args) is retrieved to determine integer type and
7939 parse_int(struct context *ctx, const struct token *token,
7940 const char *str, unsigned int len,
7941 void *buf, unsigned int size)
7943 const struct arg *arg = pop_args(ctx);
7948 /* Argument is expected. */
7953 (uintmax_t)strtoimax(str, &end, 0) :
7954 strtoumax(str, &end, 0);
7955 if (errno || (size_t)(end - str) != len)
7958 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
7959 (intmax_t)u > (intmax_t)arg->max)) ||
7960 (!arg->sign && (u < arg->min || u > arg->max))))
7965 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
7966 !arg_entry_bf_fill(ctx->objmask, -1, arg))
7970 buf = (uint8_t *)ctx->object + arg->offset;
7972 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
7976 case sizeof(uint8_t):
7977 *(uint8_t *)buf = u;
7979 case sizeof(uint16_t):
7980 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
7982 case sizeof(uint8_t [3]):
7983 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7985 ((uint8_t *)buf)[0] = u;
7986 ((uint8_t *)buf)[1] = u >> 8;
7987 ((uint8_t *)buf)[2] = u >> 16;
7991 ((uint8_t *)buf)[0] = u >> 16;
7992 ((uint8_t *)buf)[1] = u >> 8;
7993 ((uint8_t *)buf)[2] = u;
7995 case sizeof(uint32_t):
7996 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
7998 case sizeof(uint64_t):
7999 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
8004 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
8006 buf = (uint8_t *)ctx->objmask + arg->offset;
8011 push_args(ctx, arg);
8018 * Three arguments (ctx->args) are retrieved from the stack to store data,
8019 * its actual length and address (in that order).
8022 parse_string(struct context *ctx, const struct token *token,
8023 const char *str, unsigned int len,
8024 void *buf, unsigned int size)
8026 const struct arg *arg_data = pop_args(ctx);
8027 const struct arg *arg_len = pop_args(ctx);
8028 const struct arg *arg_addr = pop_args(ctx);
8029 char tmp[16]; /* Ought to be enough. */
8032 /* Arguments are expected. */
8036 push_args(ctx, arg_data);
8040 push_args(ctx, arg_len);
8041 push_args(ctx, arg_data);
8044 size = arg_data->size;
8045 /* Bit-mask fill is not supported. */
8046 if (arg_data->mask || size < len)
8050 /* Let parse_int() fill length information first. */
8051 ret = snprintf(tmp, sizeof(tmp), "%u", len);
8054 push_args(ctx, arg_len);
8055 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
8060 buf = (uint8_t *)ctx->object + arg_data->offset;
8061 /* Output buffer is not necessarily NUL-terminated. */
8062 memcpy(buf, str, len);
8063 memset((uint8_t *)buf + len, 0x00, size - len);
8065 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
8066 /* Save address if requested. */
8067 if (arg_addr->size) {
8068 memcpy((uint8_t *)ctx->object + arg_addr->offset,
8070 (uint8_t *)ctx->object + arg_data->offset
8074 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
8076 (uint8_t *)ctx->objmask + arg_data->offset
8082 push_args(ctx, arg_addr);
8083 push_args(ctx, arg_len);
8084 push_args(ctx, arg_data);
8089 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
8091 const uint8_t *head = dst;
8094 /* Check input parameters */
8095 if ((src == NULL) ||
8103 /* Convert chars to bytes */
8105 char tmp[3], *end = tmp;
8106 uint32_t read_lim = left & 1 ? 1 : 2;
8108 snprintf(tmp, read_lim + 1, "%s", src);
8109 *dst = strtoul(tmp, &end, 16);
8112 *size = (uint32_t)(dst - head);
8120 *size = (uint32_t)(dst - head);
8125 parse_hex(struct context *ctx, const struct token *token,
8126 const char *str, unsigned int len,
8127 void *buf, unsigned int size)
8129 const struct arg *arg_data = pop_args(ctx);
8130 const struct arg *arg_len = pop_args(ctx);
8131 const struct arg *arg_addr = pop_args(ctx);
8132 char tmp[16]; /* Ought to be enough. */
8134 unsigned int hexlen = len;
8135 unsigned int length = 256;
8136 uint8_t hex_tmp[length];
8138 /* Arguments are expected. */
8142 push_args(ctx, arg_data);
8146 push_args(ctx, arg_len);
8147 push_args(ctx, arg_data);
8150 size = arg_data->size;
8151 /* Bit-mask fill is not supported. */
8157 /* translate bytes string to array. */
8158 if (str[0] == '0' && ((str[1] == 'x') ||
8163 if (hexlen > length)
8165 ret = parse_hex_string(str, hex_tmp, &hexlen);
8168 /* Check the converted binary fits into data buffer. */
8171 /* Let parse_int() fill length information first. */
8172 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
8175 /* Save length if requested. */
8176 if (arg_len->size) {
8177 push_args(ctx, arg_len);
8178 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
8184 buf = (uint8_t *)ctx->object + arg_data->offset;
8185 /* Output buffer is not necessarily NUL-terminated. */
8186 memcpy(buf, hex_tmp, hexlen);
8187 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
8189 memset((uint8_t *)ctx->objmask + arg_data->offset,
8191 /* Save address if requested. */
8192 if (arg_addr->size) {
8193 memcpy((uint8_t *)ctx->object + arg_addr->offset,
8195 (uint8_t *)ctx->object + arg_data->offset
8199 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
8201 (uint8_t *)ctx->objmask + arg_data->offset
8207 push_args(ctx, arg_addr);
8208 push_args(ctx, arg_len);
8209 push_args(ctx, arg_data);
8215 * Parse a zero-ended string.
8218 parse_string0(struct context *ctx, const struct token *token __rte_unused,
8219 const char *str, unsigned int len,
8220 void *buf, unsigned int size)
8222 const struct arg *arg_data = pop_args(ctx);
8224 /* Arguments are expected. */
8227 size = arg_data->size;
8228 /* Bit-mask fill is not supported. */
8229 if (arg_data->mask || size < len + 1)
8233 buf = (uint8_t *)ctx->object + arg_data->offset;
8234 strncpy(buf, str, len);
8236 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
8239 push_args(ctx, arg_data);
8244 * Parse a MAC address.
8246 * Last argument (ctx->args) is retrieved to determine storage size and
8250 parse_mac_addr(struct context *ctx, const struct token *token,
8251 const char *str, unsigned int len,
8252 void *buf, unsigned int size)
8254 const struct arg *arg = pop_args(ctx);
8255 struct rte_ether_addr tmp;
8259 /* Argument is expected. */
8263 /* Bit-mask fill is not supported. */
8264 if (arg->mask || size != sizeof(tmp))
8266 /* Only network endian is supported. */
8269 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
8270 if (ret < 0 || (unsigned int)ret != len)
8274 buf = (uint8_t *)ctx->object + arg->offset;
8275 memcpy(buf, &tmp, size);
8277 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8280 push_args(ctx, arg);
8285 * Parse an IPv4 address.
8287 * Last argument (ctx->args) is retrieved to determine storage size and
8291 parse_ipv4_addr(struct context *ctx, const struct token *token,
8292 const char *str, unsigned int len,
8293 void *buf, unsigned int size)
8295 const struct arg *arg = pop_args(ctx);
8300 /* Argument is expected. */
8304 /* Bit-mask fill is not supported. */
8305 if (arg->mask || size != sizeof(tmp))
8307 /* Only network endian is supported. */
8310 memcpy(str2, str, len);
8312 ret = inet_pton(AF_INET, str2, &tmp);
8314 /* Attempt integer parsing. */
8315 push_args(ctx, arg);
8316 return parse_int(ctx, token, str, len, buf, size);
8320 buf = (uint8_t *)ctx->object + arg->offset;
8321 memcpy(buf, &tmp, size);
8323 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8326 push_args(ctx, arg);
8331 * Parse an IPv6 address.
8333 * Last argument (ctx->args) is retrieved to determine storage size and
8337 parse_ipv6_addr(struct context *ctx, const struct token *token,
8338 const char *str, unsigned int len,
8339 void *buf, unsigned int size)
8341 const struct arg *arg = pop_args(ctx);
8343 struct in6_addr tmp;
8347 /* Argument is expected. */
8351 /* Bit-mask fill is not supported. */
8352 if (arg->mask || size != sizeof(tmp))
8354 /* Only network endian is supported. */
8357 memcpy(str2, str, len);
8359 ret = inet_pton(AF_INET6, str2, &tmp);
8364 buf = (uint8_t *)ctx->object + arg->offset;
8365 memcpy(buf, &tmp, size);
8367 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8370 push_args(ctx, arg);
8374 /** Boolean values (even indices stand for false). */
8375 static const char *const boolean_name[] = {
8385 * Parse a boolean value.
8387 * Last argument (ctx->args) is retrieved to determine storage size and
8391 parse_boolean(struct context *ctx, const struct token *token,
8392 const char *str, unsigned int len,
8393 void *buf, unsigned int size)
8395 const struct arg *arg = pop_args(ctx);
8399 /* Argument is expected. */
8402 for (i = 0; boolean_name[i]; ++i)
8403 if (!strcmp_partial(boolean_name[i], str, len))
8405 /* Process token as integer. */
8406 if (boolean_name[i])
8407 str = i & 1 ? "1" : "0";
8408 push_args(ctx, arg);
8409 ret = parse_int(ctx, token, str, strlen(str), buf, size);
8410 return ret > 0 ? (int)len : ret;
8413 /** Parse port and update context. */
8415 parse_port(struct context *ctx, const struct token *token,
8416 const char *str, unsigned int len,
8417 void *buf, unsigned int size)
8419 struct buffer *out = &(struct buffer){ .port = 0 };
8427 ctx->objmask = NULL;
8428 size = sizeof(*out);
8430 ret = parse_int(ctx, token, str, len, out, size);
8432 ctx->port = out->port;
8439 parse_ia_id2ptr(struct context *ctx, const struct token *token,
8440 const char *str, unsigned int len,
8441 void *buf, unsigned int size)
8443 struct rte_flow_action *action = ctx->object;
8451 ctx->objmask = NULL;
8452 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
8453 ctx->object = action;
8454 if (ret != (int)len)
8456 /* set indirect action */
8458 action->conf = port_action_handle_get_by_id(ctx->port, id);
8459 ret = (action->conf) ? ret : -1;
8464 /** Parse set command, initialize output buffer for subsequent tokens. */
8466 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
8467 const char *str, unsigned int len,
8468 void *buf, unsigned int size)
8470 struct buffer *out = buf;
8472 /* Token name must match. */
8473 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8475 /* Nothing else to do if there is no buffer. */
8478 /* Make sure buffer is large enough. */
8479 if (size < sizeof(*out))
8482 ctx->objmask = NULL;
8486 out->command = ctx->curr;
8487 /* For encap/decap we need is pattern */
8488 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8493 /** Parse set command, initialize output buffer for subsequent tokens. */
8495 parse_set_sample_action(struct context *ctx, const struct token *token,
8496 const char *str, unsigned int len,
8497 void *buf, unsigned int size)
8499 struct buffer *out = buf;
8501 /* Token name must match. */
8502 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8504 /* Nothing else to do if there is no buffer. */
8507 /* Make sure buffer is large enough. */
8508 if (size < sizeof(*out))
8511 ctx->objmask = NULL;
8515 out->command = ctx->curr;
8516 /* For sampler we need is actions */
8517 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8523 * Parse set raw_encap/raw_decap command,
8524 * initialize output buffer for subsequent tokens.
8527 parse_set_init(struct context *ctx, const struct token *token,
8528 const char *str, unsigned int len,
8529 void *buf, unsigned int size)
8531 struct buffer *out = buf;
8533 /* Token name must match. */
8534 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8536 /* Nothing else to do if there is no buffer. */
8539 /* Make sure buffer is large enough. */
8540 if (size < sizeof(*out))
8542 /* Initialize buffer. */
8543 memset(out, 0x00, sizeof(*out));
8544 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8547 ctx->objmask = NULL;
8548 if (!out->command) {
8549 if (ctx->curr != SET)
8551 if (sizeof(*out) > size)
8553 out->command = ctx->curr;
8554 out->args.vc.data = (uint8_t *)out + size;
8555 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8562 * Replace testpmd handles in a flex flow item with real values.
8565 parse_flex_handle(struct context *ctx, const struct token *token,
8566 const char *str, unsigned int len,
8567 void *buf, unsigned int size)
8569 struct rte_flow_item_flex *spec, *mask;
8570 const struct rte_flow_item_flex *src_spec, *src_mask;
8571 const struct arg *arg = pop_args(ctx);
8577 printf("Bad environment\n");
8580 offset = arg->offset;
8581 push_args(ctx, arg);
8582 ret = parse_int(ctx, token, str, len, buf, size);
8583 if (ret <= 0 || !ctx->object)
8585 if (ctx->port >= RTE_MAX_ETHPORTS) {
8586 printf("Bad port\n");
8589 if (offset == offsetof(struct rte_flow_item_flex, handle)) {
8590 const struct flex_item *fp;
8591 struct rte_flow_item_flex *item_flex = ctx->object;
8592 handle = (uint16_t)(uintptr_t)item_flex->handle;
8593 if (handle >= FLEX_MAX_PARSERS_NUM) {
8594 printf("Bad flex item handle\n");
8597 fp = flex_items[ctx->port][handle];
8599 printf("Bad flex item handle\n");
8602 item_flex->handle = fp->flex_handle;
8603 } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
8604 handle = (uint16_t)(uintptr_t)
8605 ((struct rte_flow_item_flex *)ctx->object)->pattern;
8606 if (handle >= FLEX_MAX_PATTERNS_NUM) {
8607 printf("Bad pattern handle\n");
8610 src_spec = &flex_patterns[handle].spec;
8611 src_mask = &flex_patterns[handle].mask;
8613 mask = spec + 2; /* spec, last, mask */
8614 /* fill flow rule spec and mask parameters */
8615 spec->length = src_spec->length;
8616 spec->pattern = src_spec->pattern;
8617 mask->length = src_mask->length;
8618 mask->pattern = src_mask->pattern;
8620 printf("Bad arguments - unknown flex item offset\n");
8626 /** No completion. */
8628 comp_none(struct context *ctx, const struct token *token,
8629 unsigned int ent, char *buf, unsigned int size)
8639 /** Complete boolean values. */
8641 comp_boolean(struct context *ctx, const struct token *token,
8642 unsigned int ent, char *buf, unsigned int size)
8648 for (i = 0; boolean_name[i]; ++i)
8649 if (buf && i == ent)
8650 return strlcpy(buf, boolean_name[i], size);
8656 /** Complete action names. */
8658 comp_action(struct context *ctx, const struct token *token,
8659 unsigned int ent, char *buf, unsigned int size)
8665 for (i = 0; next_action[i]; ++i)
8666 if (buf && i == ent)
8667 return strlcpy(buf, token_list[next_action[i]].name,
8674 /** Complete available ports. */
8676 comp_port(struct context *ctx, const struct token *token,
8677 unsigned int ent, char *buf, unsigned int size)
8684 RTE_ETH_FOREACH_DEV(p) {
8685 if (buf && i == ent)
8686 return snprintf(buf, size, "%u", p);
8694 /** Complete available rule IDs. */
8696 comp_rule_id(struct context *ctx, const struct token *token,
8697 unsigned int ent, char *buf, unsigned int size)
8700 struct rte_port *port;
8701 struct port_flow *pf;
8704 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
8705 ctx->port == (portid_t)RTE_PORT_ALL)
8707 port = &ports[ctx->port];
8708 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
8709 if (buf && i == ent)
8710 return snprintf(buf, size, "%u", pf->id);
8718 /** Complete type field for RSS action. */
8720 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
8721 unsigned int ent, char *buf, unsigned int size)
8727 for (i = 0; rss_type_table[i].str; ++i)
8732 return strlcpy(buf, rss_type_table[ent].str, size);
8734 return snprintf(buf, size, "end");
8738 /** Complete queue field for RSS action. */
8740 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
8741 unsigned int ent, char *buf, unsigned int size)
8748 return snprintf(buf, size, "%u", ent);
8750 return snprintf(buf, size, "end");
8754 /** Complete index number for set raw_encap/raw_decap commands. */
8756 comp_set_raw_index(struct context *ctx, const struct token *token,
8757 unsigned int ent, char *buf, unsigned int size)
8763 RTE_SET_USED(token);
8764 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
8765 if (buf && idx == ent)
8766 return snprintf(buf, size, "%u", idx);
8772 /** Complete index number for set raw_encap/raw_decap commands. */
8774 comp_set_sample_index(struct context *ctx, const struct token *token,
8775 unsigned int ent, char *buf, unsigned int size)
8781 RTE_SET_USED(token);
8782 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
8783 if (buf && idx == ent)
8784 return snprintf(buf, size, "%u", idx);
8790 /** Complete operation for modify_field command. */
8792 comp_set_modify_field_op(struct context *ctx, const struct token *token,
8793 unsigned int ent, char *buf, unsigned int size)
8796 RTE_SET_USED(token);
8798 return RTE_DIM(modify_field_ops);
8799 if (ent < RTE_DIM(modify_field_ops) - 1)
8800 return strlcpy(buf, modify_field_ops[ent], size);
8804 /** Complete field id for modify_field command. */
8806 comp_set_modify_field_id(struct context *ctx, const struct token *token,
8807 unsigned int ent, char *buf, unsigned int size)
8811 RTE_SET_USED(token);
8813 return RTE_DIM(modify_field_ids);
8814 if (ent >= RTE_DIM(modify_field_ids) - 1)
8816 name = modify_field_ids[ent];
8817 if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
8818 (strcmp(name, "pointer") && strcmp(name, "value")))
8819 return strlcpy(buf, name, size);
8823 /** Internal context. */
8824 static struct context cmd_flow_context;
8826 /** Global parser instance (cmdline API). */
8827 cmdline_parse_inst_t cmd_flow;
8828 cmdline_parse_inst_t cmd_set_raw;
8830 /** Initialize context. */
8832 cmd_flow_context_init(struct context *ctx)
8834 /* A full memset() is not necessary. */
8844 ctx->objmask = NULL;
8847 /** Parse a token (cmdline API). */
8849 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
8852 struct context *ctx = &cmd_flow_context;
8853 const struct token *token;
8854 const enum index *list;
8859 token = &token_list[ctx->curr];
8860 /* Check argument length. */
8863 for (len = 0; src[len]; ++len)
8864 if (src[len] == '#' || isspace(src[len]))
8868 /* Last argument and EOL detection. */
8869 for (i = len; src[i]; ++i)
8870 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
8872 else if (!isspace(src[i])) {
8877 if (src[i] == '\r' || src[i] == '\n') {
8881 /* Initialize context if necessary. */
8882 if (!ctx->next_num) {
8885 ctx->next[ctx->next_num++] = token->next[0];
8887 /* Process argument through candidates. */
8888 ctx->prev = ctx->curr;
8889 list = ctx->next[ctx->next_num - 1];
8890 for (i = 0; list[i]; ++i) {
8891 const struct token *next = &token_list[list[i]];
8894 ctx->curr = list[i];
8896 tmp = next->call(ctx, next, src, len, result, size);
8898 tmp = parse_default(ctx, next, src, len, result, size);
8899 if (tmp == -1 || tmp != len)
8907 /* Push subsequent tokens if any. */
8909 for (i = 0; token->next[i]; ++i) {
8910 if (ctx->next_num == RTE_DIM(ctx->next))
8912 ctx->next[ctx->next_num++] = token->next[i];
8914 /* Push arguments if any. */
8916 for (i = 0; token->args[i]; ++i) {
8917 if (ctx->args_num == RTE_DIM(ctx->args))
8919 ctx->args[ctx->args_num++] = token->args[i];
8925 flow_parse(const char *src, void *result, unsigned int size,
8926 struct rte_flow_attr **attr,
8927 struct rte_flow_item **pattern, struct rte_flow_action **actions)
8930 struct context saved_flow_ctx = cmd_flow_context;
8932 cmd_flow_context_init(&cmd_flow_context);
8934 ret = cmd_flow_parse(NULL, src, result, size);
8937 while (isspace(*src))
8940 } while (ret > 0 && strlen(src));
8941 cmd_flow_context = saved_flow_ctx;
8942 *attr = &((struct buffer *)result)->args.vc.attr;
8943 *pattern = ((struct buffer *)result)->args.vc.pattern;
8944 *actions = ((struct buffer *)result)->args.vc.actions;
8945 return (ret >= 0 && !strlen(src)) ? 0 : -1;
8948 /** Return number of completion entries (cmdline API). */
8950 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
8952 struct context *ctx = &cmd_flow_context;
8953 const struct token *token = &token_list[ctx->curr];
8954 const enum index *list;
8958 /* Count number of tokens in current list. */
8960 list = ctx->next[ctx->next_num - 1];
8962 list = token->next[0];
8963 for (i = 0; list[i]; ++i)
8968 * If there is a single token, use its completion callback, otherwise
8969 * return the number of entries.
8971 token = &token_list[list[0]];
8972 if (i == 1 && token->comp) {
8973 /* Save index for cmd_flow_get_help(). */
8974 ctx->prev = list[0];
8975 return token->comp(ctx, token, 0, NULL, 0);
8980 /** Return a completion entry (cmdline API). */
8982 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
8983 char *dst, unsigned int size)
8985 struct context *ctx = &cmd_flow_context;
8986 const struct token *token = &token_list[ctx->curr];
8987 const enum index *list;
8991 /* Count number of tokens in current list. */
8993 list = ctx->next[ctx->next_num - 1];
8995 list = token->next[0];
8996 for (i = 0; list[i]; ++i)
9000 /* If there is a single token, use its completion callback. */
9001 token = &token_list[list[0]];
9002 if (i == 1 && token->comp) {
9003 /* Save index for cmd_flow_get_help(). */
9004 ctx->prev = list[0];
9005 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
9007 /* Otherwise make sure the index is valid and use defaults. */
9010 token = &token_list[list[index]];
9011 strlcpy(dst, token->name, size);
9012 /* Save index for cmd_flow_get_help(). */
9013 ctx->prev = list[index];
9017 /** Populate help strings for current token (cmdline API). */
9019 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
9021 struct context *ctx = &cmd_flow_context;
9022 const struct token *token = &token_list[ctx->prev];
9027 /* Set token type and update global help with details. */
9028 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
9030 cmd_flow.help_str = token->help;
9032 cmd_flow.help_str = token->name;
9036 /** Token definition template (cmdline API). */
9037 static struct cmdline_token_hdr cmd_flow_token_hdr = {
9038 .ops = &(struct cmdline_token_ops){
9039 .parse = cmd_flow_parse,
9040 .complete_get_nb = cmd_flow_complete_get_nb,
9041 .complete_get_elt = cmd_flow_complete_get_elt,
9042 .get_help = cmd_flow_get_help,
9047 /** Populate the next dynamic token. */
9049 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
9050 cmdline_parse_token_hdr_t **hdr_inst)
9052 struct context *ctx = &cmd_flow_context;
9054 /* Always reinitialize context before requesting the first token. */
9055 if (!(hdr_inst - cmd_flow.tokens))
9056 cmd_flow_context_init(ctx);
9057 /* Return NULL when no more tokens are expected. */
9058 if (!ctx->next_num && ctx->curr) {
9062 /* Determine if command should end here. */
9063 if (ctx->eol && ctx->last && ctx->next_num) {
9064 const enum index *list = ctx->next[ctx->next_num - 1];
9067 for (i = 0; list[i]; ++i) {
9074 *hdr = &cmd_flow_token_hdr;
9077 /** Dispatch parsed buffer to function calls. */
9079 cmd_flow_parsed(const struct buffer *in)
9081 switch (in->command) {
9083 port_flow_get_info(in->port);
9086 port_flow_configure(in->port,
9087 &in->args.configure.port_attr,
9088 in->args.configure.nb_queue,
9089 &in->args.configure.queue_attr);
9091 case INDIRECT_ACTION_CREATE:
9092 port_action_handle_create(
9093 in->port, in->args.vc.attr.group,
9094 &((const struct rte_flow_indir_action_conf) {
9095 .ingress = in->args.vc.attr.ingress,
9096 .egress = in->args.vc.attr.egress,
9097 .transfer = in->args.vc.attr.transfer,
9099 in->args.vc.actions);
9101 case INDIRECT_ACTION_DESTROY:
9102 port_action_handle_destroy(in->port,
9103 in->args.ia_destroy.action_id_n,
9104 in->args.ia_destroy.action_id);
9106 case INDIRECT_ACTION_UPDATE:
9107 port_action_handle_update(in->port, in->args.vc.attr.group,
9108 in->args.vc.actions);
9110 case INDIRECT_ACTION_QUERY:
9111 port_action_handle_query(in->port, in->args.ia.action_id);
9114 port_flow_validate(in->port, &in->args.vc.attr,
9115 in->args.vc.pattern, in->args.vc.actions,
9116 &in->args.vc.tunnel_ops);
9119 port_flow_create(in->port, &in->args.vc.attr,
9120 in->args.vc.pattern, in->args.vc.actions,
9121 &in->args.vc.tunnel_ops);
9124 port_flow_destroy(in->port, in->args.destroy.rule_n,
9125 in->args.destroy.rule);
9128 port_flow_flush(in->port);
9132 port_flow_dump(in->port, in->args.dump.mode,
9133 in->args.dump.rule, in->args.dump.file);
9136 port_flow_query(in->port, in->args.query.rule,
9137 &in->args.query.action);
9140 port_flow_list(in->port, in->args.list.group_n,
9141 in->args.list.group);
9144 port_flow_isolate(in->port, in->args.isolate.set);
9147 port_flow_aged(in->port, in->args.aged.destroy);
9150 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
9152 case TUNNEL_DESTROY:
9153 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
9156 port_flow_tunnel_list(in->port);
9159 port_meter_policy_add(in->port, in->args.policy.policy_id,
9160 in->args.vc.actions);
9162 case FLEX_ITEM_CREATE:
9163 flex_item_create(in->port, in->args.flex.token,
9164 in->args.flex.filename);
9166 case FLEX_ITEM_DESTROY:
9167 flex_item_destroy(in->port, in->args.flex.token);
9174 /** Token generator and output processing callback (cmdline API). */
9176 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
9179 cmd_flow_tok(arg0, arg2);
9181 cmd_flow_parsed(arg0);
9184 /** Global parser instance (cmdline API). */
9185 cmdline_parse_inst_t cmd_flow = {
9187 .data = NULL, /**< Unused. */
9188 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
9191 }, /**< Tokens are returned by cmd_flow_tok(). */
9194 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
9197 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
9199 struct rte_ipv4_hdr *ipv4;
9200 struct rte_ether_hdr *eth;
9201 struct rte_ipv6_hdr *ipv6;
9202 struct rte_vxlan_hdr *vxlan;
9203 struct rte_vxlan_gpe_hdr *gpe;
9204 struct rte_flow_item_nvgre *nvgre;
9205 uint32_t ipv6_vtc_flow;
9207 switch (item->type) {
9208 case RTE_FLOW_ITEM_TYPE_ETH:
9209 eth = (struct rte_ether_hdr *)buf;
9211 eth->ether_type = rte_cpu_to_be_16(next_proto);
9213 case RTE_FLOW_ITEM_TYPE_IPV4:
9214 ipv4 = (struct rte_ipv4_hdr *)buf;
9215 if (!ipv4->version_ihl)
9216 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
9217 if (next_proto && ipv4->next_proto_id == 0)
9218 ipv4->next_proto_id = (uint8_t)next_proto;
9220 case RTE_FLOW_ITEM_TYPE_IPV6:
9221 ipv6 = (struct rte_ipv6_hdr *)buf;
9222 if (next_proto && ipv6->proto == 0)
9223 ipv6->proto = (uint8_t)next_proto;
9224 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
9225 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
9226 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
9227 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
9229 case RTE_FLOW_ITEM_TYPE_VXLAN:
9230 vxlan = (struct rte_vxlan_hdr *)buf;
9231 vxlan->vx_flags = 0x08;
9233 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9234 gpe = (struct rte_vxlan_gpe_hdr *)buf;
9235 gpe->vx_flags = 0x0C;
9237 case RTE_FLOW_ITEM_TYPE_NVGRE:
9238 nvgre = (struct rte_flow_item_nvgre *)buf;
9239 nvgre->protocol = rte_cpu_to_be_16(0x6558);
9240 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
9247 /** Helper of get item's default mask. */
9249 flow_item_default_mask(const struct rte_flow_item *item)
9251 const void *mask = NULL;
9252 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
9254 switch (item->type) {
9255 case RTE_FLOW_ITEM_TYPE_ANY:
9256 mask = &rte_flow_item_any_mask;
9258 case RTE_FLOW_ITEM_TYPE_VF:
9259 mask = &rte_flow_item_vf_mask;
9261 case RTE_FLOW_ITEM_TYPE_PORT_ID:
9262 mask = &rte_flow_item_port_id_mask;
9264 case RTE_FLOW_ITEM_TYPE_RAW:
9265 mask = &rte_flow_item_raw_mask;
9267 case RTE_FLOW_ITEM_TYPE_ETH:
9268 mask = &rte_flow_item_eth_mask;
9270 case RTE_FLOW_ITEM_TYPE_VLAN:
9271 mask = &rte_flow_item_vlan_mask;
9273 case RTE_FLOW_ITEM_TYPE_IPV4:
9274 mask = &rte_flow_item_ipv4_mask;
9276 case RTE_FLOW_ITEM_TYPE_IPV6:
9277 mask = &rte_flow_item_ipv6_mask;
9279 case RTE_FLOW_ITEM_TYPE_ICMP:
9280 mask = &rte_flow_item_icmp_mask;
9282 case RTE_FLOW_ITEM_TYPE_UDP:
9283 mask = &rte_flow_item_udp_mask;
9285 case RTE_FLOW_ITEM_TYPE_TCP:
9286 mask = &rte_flow_item_tcp_mask;
9288 case RTE_FLOW_ITEM_TYPE_SCTP:
9289 mask = &rte_flow_item_sctp_mask;
9291 case RTE_FLOW_ITEM_TYPE_VXLAN:
9292 mask = &rte_flow_item_vxlan_mask;
9294 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9295 mask = &rte_flow_item_vxlan_gpe_mask;
9297 case RTE_FLOW_ITEM_TYPE_E_TAG:
9298 mask = &rte_flow_item_e_tag_mask;
9300 case RTE_FLOW_ITEM_TYPE_NVGRE:
9301 mask = &rte_flow_item_nvgre_mask;
9303 case RTE_FLOW_ITEM_TYPE_MPLS:
9304 mask = &rte_flow_item_mpls_mask;
9306 case RTE_FLOW_ITEM_TYPE_GRE:
9307 mask = &rte_flow_item_gre_mask;
9309 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
9310 mask = &gre_key_default_mask;
9312 case RTE_FLOW_ITEM_TYPE_META:
9313 mask = &rte_flow_item_meta_mask;
9315 case RTE_FLOW_ITEM_TYPE_FUZZY:
9316 mask = &rte_flow_item_fuzzy_mask;
9318 case RTE_FLOW_ITEM_TYPE_GTP:
9319 mask = &rte_flow_item_gtp_mask;
9321 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
9322 mask = &rte_flow_item_gtp_psc_mask;
9324 case RTE_FLOW_ITEM_TYPE_GENEVE:
9325 mask = &rte_flow_item_geneve_mask;
9327 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
9328 mask = &rte_flow_item_geneve_opt_mask;
9330 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
9331 mask = &rte_flow_item_pppoe_proto_id_mask;
9333 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
9334 mask = &rte_flow_item_l2tpv3oip_mask;
9336 case RTE_FLOW_ITEM_TYPE_ESP:
9337 mask = &rte_flow_item_esp_mask;
9339 case RTE_FLOW_ITEM_TYPE_AH:
9340 mask = &rte_flow_item_ah_mask;
9342 case RTE_FLOW_ITEM_TYPE_PFCP:
9343 mask = &rte_flow_item_pfcp_mask;
9345 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
9346 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
9347 mask = &rte_flow_item_ethdev_mask;
9349 case RTE_FLOW_ITEM_TYPE_L2TPV2:
9350 mask = &rte_flow_item_l2tpv2_mask;
9352 case RTE_FLOW_ITEM_TYPE_PPP:
9353 mask = &rte_flow_item_ppp_mask;
9361 /** Dispatch parsed buffer to function calls. */
9363 cmd_set_raw_parsed_sample(const struct buffer *in)
9365 uint32_t n = in->args.vc.actions_n;
9367 struct rte_flow_action *action = NULL;
9368 struct rte_flow_action *data = NULL;
9369 const struct rte_flow_action_rss *rss = NULL;
9371 uint16_t idx = in->port; /* We borrow port field as index */
9372 uint32_t max_size = sizeof(struct rte_flow_action) *
9373 ACTION_SAMPLE_ACTIONS_NUM;
9375 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
9376 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
9377 memset(data, 0x00, max_size);
9378 for (; i <= n - 1; i++) {
9379 action = in->args.vc.actions + i;
9380 if (action->type == RTE_FLOW_ACTION_TYPE_END)
9382 switch (action->type) {
9383 case RTE_FLOW_ACTION_TYPE_MARK:
9384 size = sizeof(struct rte_flow_action_mark);
9385 rte_memcpy(&sample_mark[idx],
9386 (const void *)action->conf, size);
9387 action->conf = &sample_mark[idx];
9389 case RTE_FLOW_ACTION_TYPE_COUNT:
9390 size = sizeof(struct rte_flow_action_count);
9391 rte_memcpy(&sample_count[idx],
9392 (const void *)action->conf, size);
9393 action->conf = &sample_count[idx];
9395 case RTE_FLOW_ACTION_TYPE_QUEUE:
9396 size = sizeof(struct rte_flow_action_queue);
9397 rte_memcpy(&sample_queue[idx],
9398 (const void *)action->conf, size);
9399 action->conf = &sample_queue[idx];
9401 case RTE_FLOW_ACTION_TYPE_RSS:
9402 size = sizeof(struct rte_flow_action_rss);
9404 rte_memcpy(&sample_rss_data[idx].conf,
9405 (const void *)rss, size);
9406 if (rss->key_len && rss->key) {
9407 sample_rss_data[idx].conf.key =
9408 sample_rss_data[idx].key;
9409 rte_memcpy((void *)((uintptr_t)
9410 sample_rss_data[idx].conf.key),
9411 (const void *)rss->key,
9412 sizeof(uint8_t) * rss->key_len);
9414 if (rss->queue_num && rss->queue) {
9415 sample_rss_data[idx].conf.queue =
9416 sample_rss_data[idx].queue;
9417 rte_memcpy((void *)((uintptr_t)
9418 sample_rss_data[idx].conf.queue),
9419 (const void *)rss->queue,
9420 sizeof(uint16_t) * rss->queue_num);
9422 action->conf = &sample_rss_data[idx].conf;
9424 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
9425 size = sizeof(struct rte_flow_action_raw_encap);
9426 rte_memcpy(&sample_encap[idx],
9427 (const void *)action->conf, size);
9428 action->conf = &sample_encap[idx];
9430 case RTE_FLOW_ACTION_TYPE_PORT_ID:
9431 size = sizeof(struct rte_flow_action_port_id);
9432 rte_memcpy(&sample_port_id[idx],
9433 (const void *)action->conf, size);
9434 action->conf = &sample_port_id[idx];
9436 case RTE_FLOW_ACTION_TYPE_PF:
9438 case RTE_FLOW_ACTION_TYPE_VF:
9439 size = sizeof(struct rte_flow_action_vf);
9440 rte_memcpy(&sample_vf[idx],
9441 (const void *)action->conf, size);
9442 action->conf = &sample_vf[idx];
9444 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
9445 size = sizeof(struct rte_flow_action_vxlan_encap);
9446 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
9447 action->conf = &sample_vxlan_encap[idx].conf;
9449 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
9450 size = sizeof(struct rte_flow_action_nvgre_encap);
9451 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
9452 action->conf = &sample_nvgre_encap[idx];
9455 fprintf(stderr, "Error - Not supported action\n");
9458 rte_memcpy(data, action, sizeof(struct rte_flow_action));
9463 /** Dispatch parsed buffer to function calls. */
9465 cmd_set_raw_parsed(const struct buffer *in)
9467 uint32_t n = in->args.vc.pattern_n;
9469 struct rte_flow_item *item = NULL;
9471 uint8_t *data = NULL;
9472 uint8_t *data_tail = NULL;
9473 size_t *total_size = NULL;
9474 uint16_t upper_layer = 0;
9476 uint16_t idx = in->port; /* We borrow port field as index */
9477 int gtp_psc = -1; /* GTP PSC option index. */
9479 if (in->command == SET_SAMPLE_ACTIONS)
9480 return cmd_set_raw_parsed_sample(in);
9481 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
9482 in->command == SET_RAW_DECAP);
9483 if (in->command == SET_RAW_ENCAP) {
9484 total_size = &raw_encap_confs[idx].size;
9485 data = (uint8_t *)&raw_encap_confs[idx].data;
9487 total_size = &raw_decap_confs[idx].size;
9488 data = (uint8_t *)&raw_decap_confs[idx].data;
9491 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
9492 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
9493 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
9494 for (i = n - 1 ; i >= 0; --i) {
9495 const struct rte_flow_item_gtp *gtp;
9496 const struct rte_flow_item_geneve_opt *opt;
9498 item = in->args.vc.pattern + i;
9499 if (item->spec == NULL)
9500 item->spec = flow_item_default_mask(item);
9501 switch (item->type) {
9502 case RTE_FLOW_ITEM_TYPE_ETH:
9503 size = sizeof(struct rte_ether_hdr);
9505 case RTE_FLOW_ITEM_TYPE_VLAN:
9506 size = sizeof(struct rte_vlan_hdr);
9507 proto = RTE_ETHER_TYPE_VLAN;
9509 case RTE_FLOW_ITEM_TYPE_IPV4:
9510 size = sizeof(struct rte_ipv4_hdr);
9511 proto = RTE_ETHER_TYPE_IPV4;
9513 case RTE_FLOW_ITEM_TYPE_IPV6:
9514 size = sizeof(struct rte_ipv6_hdr);
9515 proto = RTE_ETHER_TYPE_IPV6;
9517 case RTE_FLOW_ITEM_TYPE_UDP:
9518 size = sizeof(struct rte_udp_hdr);
9521 case RTE_FLOW_ITEM_TYPE_TCP:
9522 size = sizeof(struct rte_tcp_hdr);
9525 case RTE_FLOW_ITEM_TYPE_VXLAN:
9526 size = sizeof(struct rte_vxlan_hdr);
9528 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
9529 size = sizeof(struct rte_vxlan_gpe_hdr);
9531 case RTE_FLOW_ITEM_TYPE_GRE:
9532 size = sizeof(struct rte_gre_hdr);
9535 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
9536 size = sizeof(rte_be32_t);
9539 case RTE_FLOW_ITEM_TYPE_MPLS:
9540 size = sizeof(struct rte_mpls_hdr);
9543 case RTE_FLOW_ITEM_TYPE_NVGRE:
9544 size = sizeof(struct rte_flow_item_nvgre);
9547 case RTE_FLOW_ITEM_TYPE_GENEVE:
9548 size = sizeof(struct rte_geneve_hdr);
9550 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
9551 opt = (const struct rte_flow_item_geneve_opt *)
9553 size = offsetof(struct rte_flow_item_geneve_opt, data);
9554 if (opt->option_len && opt->data) {
9555 *total_size += opt->option_len *
9557 rte_memcpy(data_tail - (*total_size),
9559 opt->option_len * sizeof(uint32_t));
9562 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
9563 size = sizeof(rte_be32_t);
9566 case RTE_FLOW_ITEM_TYPE_ESP:
9567 size = sizeof(struct rte_esp_hdr);
9570 case RTE_FLOW_ITEM_TYPE_AH:
9571 size = sizeof(struct rte_flow_item_ah);
9574 case RTE_FLOW_ITEM_TYPE_GTP:
9576 size = sizeof(struct rte_gtp_hdr);
9579 if (gtp_psc != i + 1) {
9581 "Error - GTP PSC does not follow GTP\n");
9585 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
9586 /* Only E flag should be set. */
9588 "Error - GTP unsupported flags\n");
9591 struct rte_gtp_hdr_ext_word ext_word = {
9595 /* We have to add GTP header extra word. */
9596 *total_size += sizeof(ext_word);
9597 rte_memcpy(data_tail - (*total_size),
9598 &ext_word, sizeof(ext_word));
9600 size = sizeof(struct rte_gtp_hdr);
9602 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
9605 "Error - Multiple GTP PSC items\n");
9608 const struct rte_flow_item_gtp_psc
9616 psc.len = sizeof(psc) / 4;
9617 psc.pdu_type = opt->hdr.type;
9618 psc.qfi = opt->hdr.qfi;
9620 *total_size += sizeof(psc);
9621 rte_memcpy(data_tail - (*total_size),
9627 case RTE_FLOW_ITEM_TYPE_PFCP:
9628 size = sizeof(struct rte_flow_item_pfcp);
9630 case RTE_FLOW_ITEM_TYPE_FLEX:
9632 ((const struct rte_flow_item_flex *)
9633 item->spec)->length : 0;
9635 case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
9638 const struct rte_flow_item_gre_opt
9640 if (opt->checksum_rsvd.checksum) {
9642 sizeof(opt->checksum_rsvd);
9643 rte_memcpy(data_tail - (*total_size),
9644 &opt->checksum_rsvd,
9645 sizeof(opt->checksum_rsvd));
9648 *total_size += sizeof(opt->key.key);
9649 rte_memcpy(data_tail - (*total_size),
9651 sizeof(opt->key.key));
9653 if (opt->sequence.sequence) {
9654 *total_size += sizeof(opt->sequence.sequence);
9655 rte_memcpy(data_tail - (*total_size),
9656 &opt->sequence.sequence,
9657 sizeof(opt->sequence.sequence));
9663 fprintf(stderr, "Error - Not supported item\n");
9666 *total_size += size;
9667 rte_memcpy(data_tail - (*total_size), item->spec, size);
9668 /* update some fields which cannot be set by cmdline */
9669 update_fields((data_tail - (*total_size)), item,
9671 upper_layer = proto;
9673 if (verbose_level & 0x1)
9674 printf("total data size is %zu\n", (*total_size));
9675 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
9676 memmove(data, (data_tail - (*total_size)), *total_size);
9681 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
9684 /** Populate help strings for current token (cmdline API). */
9686 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
9689 struct context *ctx = &cmd_flow_context;
9690 const struct token *token = &token_list[ctx->prev];
9695 /* Set token type and update global help with details. */
9696 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
9698 cmd_set_raw.help_str = token->help;
9700 cmd_set_raw.help_str = token->name;
9704 /** Token definition template (cmdline API). */
9705 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
9706 .ops = &(struct cmdline_token_ops){
9707 .parse = cmd_flow_parse,
9708 .complete_get_nb = cmd_flow_complete_get_nb,
9709 .complete_get_elt = cmd_flow_complete_get_elt,
9710 .get_help = cmd_set_raw_get_help,
9715 /** Populate the next dynamic token. */
9717 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
9718 cmdline_parse_token_hdr_t **hdr_inst)
9720 struct context *ctx = &cmd_flow_context;
9722 /* Always reinitialize context before requesting the first token. */
9723 if (!(hdr_inst - cmd_set_raw.tokens)) {
9724 cmd_flow_context_init(ctx);
9725 ctx->curr = START_SET;
9727 /* Return NULL when no more tokens are expected. */
9728 if (!ctx->next_num && (ctx->curr != START_SET)) {
9732 /* Determine if command should end here. */
9733 if (ctx->eol && ctx->last && ctx->next_num) {
9734 const enum index *list = ctx->next[ctx->next_num - 1];
9737 for (i = 0; list[i]; ++i) {
9744 *hdr = &cmd_set_raw_token_hdr;
9747 /** Token generator and output processing callback (cmdline API). */
9749 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
9752 cmd_set_raw_tok(arg0, arg2);
9754 cmd_set_raw_parsed(arg0);
9757 /** Global parser instance (cmdline API). */
9758 cmdline_parse_inst_t cmd_set_raw = {
9759 .f = cmd_set_raw_cb,
9760 .data = NULL, /**< Unused. */
9761 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
9764 }, /**< Tokens are returned by cmd_flow_tok(). */
9767 /* *** display raw_encap/raw_decap buf */
9768 struct cmd_show_set_raw_result {
9769 cmdline_fixed_string_t cmd_show;
9770 cmdline_fixed_string_t cmd_what;
9771 cmdline_fixed_string_t cmd_all;
9776 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
9778 struct cmd_show_set_raw_result *res = parsed_result;
9779 uint16_t index = res->cmd_index;
9781 uint8_t *raw_data = NULL;
9782 size_t raw_size = 0;
9783 char title[16] = {0};
9787 if (!strcmp(res->cmd_all, "all")) {
9790 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
9791 fprintf(stderr, "index should be 0-%u\n",
9792 RAW_ENCAP_CONFS_MAX_NUM - 1);
9796 if (!strcmp(res->cmd_what, "raw_encap")) {
9797 raw_data = (uint8_t *)&raw_encap_confs[index].data;
9798 raw_size = raw_encap_confs[index].size;
9799 snprintf(title, 16, "\nindex: %u", index);
9800 rte_hexdump(stdout, title, raw_data, raw_size);
9802 raw_data = (uint8_t *)&raw_decap_confs[index].data;
9803 raw_size = raw_decap_confs[index].size;
9804 snprintf(title, 16, "\nindex: %u", index);
9805 rte_hexdump(stdout, title, raw_data, raw_size);
9807 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
9810 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
9811 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9813 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
9814 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9815 cmd_what, "raw_encap#raw_decap");
9816 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
9817 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
9818 cmd_index, RTE_UINT16);
9819 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
9820 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
9822 cmdline_parse_inst_t cmd_show_set_raw = {
9823 .f = cmd_show_set_raw_parsed,
9825 .help_str = "show <raw_encap|raw_decap> <index>",
9827 (void *)&cmd_show_set_raw_cmd_show,
9828 (void *)&cmd_show_set_raw_cmd_what,
9829 (void *)&cmd_show_set_raw_cmd_index,
9833 cmdline_parse_inst_t cmd_show_set_raw_all = {
9834 .f = cmd_show_set_raw_parsed,
9836 .help_str = "show <raw_encap|raw_decap> all",
9838 (void *)&cmd_show_set_raw_cmd_show,
9839 (void *)&cmd_show_set_raw_cmd_what,
9840 (void *)&cmd_show_set_raw_cmd_all,