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,
58 /* TOP-level command. */
61 /* Top-level command. */
63 /* Sub-leve commands. */
70 /* Top-level command. */
72 /* Sub-level commands. */
85 /* Tunnel arguments. */
92 /* Destroy arguments. */
95 /* Query arguments. */
101 /* Destroy aged flow arguments. */
104 /* Validate/create arguments. */
117 /* Indirect action arguments */
118 INDIRECT_ACTION_CREATE,
119 INDIRECT_ACTION_UPDATE,
120 INDIRECT_ACTION_DESTROY,
121 INDIRECT_ACTION_QUERY,
123 /* Indirect action create arguments */
124 INDIRECT_ACTION_CREATE_ID,
125 INDIRECT_ACTION_INGRESS,
126 INDIRECT_ACTION_EGRESS,
127 INDIRECT_ACTION_TRANSFER,
128 INDIRECT_ACTION_SPEC,
130 /* Indirect action destroy arguments */
131 INDIRECT_ACTION_DESTROY_ID,
133 /* Validate/create pattern. */
171 ITEM_VLAN_INNER_TYPE,
172 ITEM_VLAN_HAS_MORE_VLAN,
176 ITEM_IPV4_FRAGMENT_OFFSET,
188 ITEM_IPV6_HAS_FRAG_EXT,
209 ITEM_E_TAG_GRP_ECID_B,
218 ITEM_GRE_C_RSVD0_VER,
237 ITEM_ARP_ETH_IPV4_SHA,
238 ITEM_ARP_ETH_IPV4_SPA,
239 ITEM_ARP_ETH_IPV4_THA,
240 ITEM_ARP_ETH_IPV4_TPA,
242 ITEM_IPV6_EXT_NEXT_HDR,
244 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
245 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
246 ITEM_IPV6_FRAG_EXT_ID,
251 ITEM_ICMP6_ND_NS_TARGET_ADDR,
253 ITEM_ICMP6_ND_NA_TARGET_ADDR,
255 ITEM_ICMP6_ND_OPT_TYPE,
256 ITEM_ICMP6_ND_OPT_SLA_ETH,
257 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
258 ITEM_ICMP6_ND_OPT_TLA_ETH,
259 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
272 ITEM_HIGIG2_CLASSIFICATION,
278 ITEM_L2TPV3OIP_SESSION_ID,
288 ITEM_ECPRI_COMMON_TYPE,
289 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
290 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
291 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
292 ITEM_ECPRI_MSG_IQ_DATA_PCID,
293 ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
294 ITEM_ECPRI_MSG_DLY_MSR_MSRID,
296 ITEM_GENEVE_OPT_CLASS,
297 ITEM_GENEVE_OPT_TYPE,
298 ITEM_GENEVE_OPT_LENGTH,
299 ITEM_GENEVE_OPT_DATA,
301 ITEM_INTEGRITY_LEVEL,
302 ITEM_INTEGRITY_VALUE,
308 /* Validate/create actions. */
328 ACTION_RSS_FUNC_DEFAULT,
329 ACTION_RSS_FUNC_TOEPLITZ,
330 ACTION_RSS_FUNC_SIMPLE_XOR,
331 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
343 ACTION_PHY_PORT_ORIGINAL,
344 ACTION_PHY_PORT_INDEX,
346 ACTION_PORT_ID_ORIGINAL,
350 ACTION_METER_COLOR_TYPE,
351 ACTION_METER_COLOR_GREEN,
352 ACTION_METER_COLOR_YELLOW,
353 ACTION_METER_COLOR_RED,
355 ACTION_OF_SET_MPLS_TTL,
356 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
357 ACTION_OF_DEC_MPLS_TTL,
358 ACTION_OF_SET_NW_TTL,
359 ACTION_OF_SET_NW_TTL_NW_TTL,
360 ACTION_OF_DEC_NW_TTL,
361 ACTION_OF_COPY_TTL_OUT,
362 ACTION_OF_COPY_TTL_IN,
365 ACTION_OF_PUSH_VLAN_ETHERTYPE,
366 ACTION_OF_SET_VLAN_VID,
367 ACTION_OF_SET_VLAN_VID_VLAN_VID,
368 ACTION_OF_SET_VLAN_PCP,
369 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
371 ACTION_OF_POP_MPLS_ETHERTYPE,
373 ACTION_OF_PUSH_MPLS_ETHERTYPE,
380 ACTION_MPLSOGRE_ENCAP,
381 ACTION_MPLSOGRE_DECAP,
382 ACTION_MPLSOUDP_ENCAP,
383 ACTION_MPLSOUDP_DECAP,
385 ACTION_SET_IPV4_SRC_IPV4_SRC,
387 ACTION_SET_IPV4_DST_IPV4_DST,
389 ACTION_SET_IPV6_SRC_IPV6_SRC,
391 ACTION_SET_IPV6_DST_IPV6_DST,
393 ACTION_SET_TP_SRC_TP_SRC,
395 ACTION_SET_TP_DST_TP_DST,
401 ACTION_SET_MAC_SRC_MAC_SRC,
403 ACTION_SET_MAC_DST_MAC_DST,
405 ACTION_INC_TCP_SEQ_VALUE,
407 ACTION_DEC_TCP_SEQ_VALUE,
409 ACTION_INC_TCP_ACK_VALUE,
411 ACTION_DEC_TCP_ACK_VALUE,
414 ACTION_RAW_ENCAP_INDEX,
415 ACTION_RAW_ENCAP_INDEX_VALUE,
416 ACTION_RAW_DECAP_INDEX,
417 ACTION_RAW_DECAP_INDEX_VALUE,
420 ACTION_SET_TAG_INDEX,
423 ACTION_SET_META_DATA,
424 ACTION_SET_META_MASK,
425 ACTION_SET_IPV4_DSCP,
426 ACTION_SET_IPV4_DSCP_VALUE,
427 ACTION_SET_IPV6_DSCP,
428 ACTION_SET_IPV6_DSCP_VALUE,
434 ACTION_SAMPLE_INDEX_VALUE,
436 INDIRECT_ACTION_ID2PTR,
438 ACTION_MODIFY_FIELD_OP,
439 ACTION_MODIFY_FIELD_OP_VALUE,
440 ACTION_MODIFY_FIELD_DST_TYPE,
441 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
442 ACTION_MODIFY_FIELD_DST_LEVEL,
443 ACTION_MODIFY_FIELD_DST_OFFSET,
444 ACTION_MODIFY_FIELD_SRC_TYPE,
445 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
446 ACTION_MODIFY_FIELD_SRC_LEVEL,
447 ACTION_MODIFY_FIELD_SRC_OFFSET,
448 ACTION_MODIFY_FIELD_SRC_VALUE,
449 ACTION_MODIFY_FIELD_WIDTH,
451 ACTION_CONNTRACK_UPDATE,
452 ACTION_CONNTRACK_UPDATE_DIR,
453 ACTION_CONNTRACK_UPDATE_CTX,
459 /** Maximum size for pattern in struct rte_flow_item_raw. */
460 #define ITEM_RAW_PATTERN_SIZE 40
462 /** Maximum size for GENEVE option data pattern in bytes. */
463 #define ITEM_GENEVE_OPT_DATA_SIZE 124
465 /** Storage size for struct rte_flow_item_raw including pattern. */
466 #define ITEM_RAW_SIZE \
467 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
469 /** Maximum number of queue indices in struct rte_flow_action_rss. */
470 #define ACTION_RSS_QUEUE_NUM 128
472 /** Storage for struct rte_flow_action_rss including external data. */
473 struct action_rss_data {
474 struct rte_flow_action_rss conf;
475 uint8_t key[RSS_HASH_KEY_LENGTH];
476 uint16_t queue[ACTION_RSS_QUEUE_NUM];
479 /** Maximum data size in struct rte_flow_action_raw_encap. */
480 #define ACTION_RAW_ENCAP_MAX_DATA 512
481 #define RAW_ENCAP_CONFS_MAX_NUM 8
483 /** Storage for struct rte_flow_action_raw_encap. */
484 struct raw_encap_conf {
485 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
486 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
490 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
492 /** Storage for struct rte_flow_action_raw_encap including external data. */
493 struct action_raw_encap_data {
494 struct rte_flow_action_raw_encap conf;
495 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
496 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
500 /** Storage for struct rte_flow_action_raw_decap. */
501 struct raw_decap_conf {
502 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
506 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
508 /** Storage for struct rte_flow_action_raw_decap including external data. */
509 struct action_raw_decap_data {
510 struct rte_flow_action_raw_decap conf;
511 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
515 struct vxlan_encap_conf vxlan_encap_conf = {
519 .vni = "\x00\x00\x00",
521 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
522 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
523 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
524 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
525 "\x00\x00\x00\x00\x00\x00\x00\x01",
526 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
527 "\x00\x00\x00\x00\x00\x00\x11\x11",
531 .eth_src = "\x00\x00\x00\x00\x00\x00",
532 .eth_dst = "\xff\xff\xff\xff\xff\xff",
535 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
536 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
538 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
539 struct action_vxlan_encap_data {
540 struct rte_flow_action_vxlan_encap conf;
541 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
542 struct rte_flow_item_eth item_eth;
543 struct rte_flow_item_vlan item_vlan;
545 struct rte_flow_item_ipv4 item_ipv4;
546 struct rte_flow_item_ipv6 item_ipv6;
548 struct rte_flow_item_udp item_udp;
549 struct rte_flow_item_vxlan item_vxlan;
552 struct nvgre_encap_conf nvgre_encap_conf = {
555 .tni = "\x00\x00\x00",
556 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
557 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
558 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
559 "\x00\x00\x00\x00\x00\x00\x00\x01",
560 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
561 "\x00\x00\x00\x00\x00\x00\x11\x11",
563 .eth_src = "\x00\x00\x00\x00\x00\x00",
564 .eth_dst = "\xff\xff\xff\xff\xff\xff",
567 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
568 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
570 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
571 struct action_nvgre_encap_data {
572 struct rte_flow_action_nvgre_encap conf;
573 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
574 struct rte_flow_item_eth item_eth;
575 struct rte_flow_item_vlan item_vlan;
577 struct rte_flow_item_ipv4 item_ipv4;
578 struct rte_flow_item_ipv6 item_ipv6;
580 struct rte_flow_item_nvgre item_nvgre;
583 struct l2_encap_conf l2_encap_conf;
585 struct l2_decap_conf l2_decap_conf;
587 struct mplsogre_encap_conf mplsogre_encap_conf;
589 struct mplsogre_decap_conf mplsogre_decap_conf;
591 struct mplsoudp_encap_conf mplsoudp_encap_conf;
593 struct mplsoudp_decap_conf mplsoudp_decap_conf;
595 struct rte_flow_action_conntrack conntrack_context;
597 #define ACTION_SAMPLE_ACTIONS_NUM 10
598 #define RAW_SAMPLE_CONFS_MAX_NUM 8
599 /** Storage for struct rte_flow_action_sample including external data. */
600 struct action_sample_data {
601 struct rte_flow_action_sample conf;
604 /** Storage for struct rte_flow_action_sample. */
605 struct raw_sample_conf {
606 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
608 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
609 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
610 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
611 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
612 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
613 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
614 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
615 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
616 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
617 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
619 static const char *const modify_field_ops[] = {
620 "set", "add", "sub", NULL
623 static const char *const modify_field_ids[] = {
624 "start", "mac_dst", "mac_src",
625 "vlan_type", "vlan_id", "mac_type",
626 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
627 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
628 "tcp_port_src", "tcp_port_dst",
629 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
630 "udp_port_src", "udp_port_dst",
631 "vxlan_vni", "geneve_vni", "gtp_teid",
632 "tag", "mark", "meta", "pointer", "value", NULL
635 /** Maximum number of subsequent tokens and arguments on the stack. */
636 #define CTX_STACK_SIZE 16
638 /** Parser context. */
640 /** Stack of subsequent token lists to process. */
641 const enum index *next[CTX_STACK_SIZE];
642 /** Arguments for stacked tokens. */
643 const void *args[CTX_STACK_SIZE];
644 enum index curr; /**< Current token index. */
645 enum index prev; /**< Index of the last token seen. */
646 int next_num; /**< Number of entries in next[]. */
647 int args_num; /**< Number of entries in args[]. */
648 uint32_t eol:1; /**< EOL has been detected. */
649 uint32_t last:1; /**< No more arguments. */
650 portid_t port; /**< Current port ID (for completions). */
651 uint32_t objdata; /**< Object-specific data. */
652 void *object; /**< Address of current object for relative offsets. */
653 void *objmask; /**< Object a full mask must be written to. */
656 /** Token argument. */
658 uint32_t hton:1; /**< Use network byte ordering. */
659 uint32_t sign:1; /**< Value is signed. */
660 uint32_t bounded:1; /**< Value is bounded. */
661 uintmax_t min; /**< Minimum value if bounded. */
662 uintmax_t max; /**< Maximum value if bounded. */
663 uint32_t offset; /**< Relative offset from ctx->object. */
664 uint32_t size; /**< Field size. */
665 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
668 /** Parser token definition. */
670 /** Type displayed during completion (defaults to "TOKEN"). */
672 /** Help displayed during completion (defaults to token name). */
674 /** Private data used by parser functions. */
677 * Lists of subsequent tokens to push on the stack. Each call to the
678 * parser consumes the last entry of that stack.
680 const enum index *const *next;
681 /** Arguments stack for subsequent tokens that need them. */
682 const struct arg *const *args;
684 * Token-processing callback, returns -1 in case of error, the
685 * length of the matched string otherwise. If NULL, attempts to
686 * match the token name.
688 * If buf is not NULL, the result should be stored in it according
689 * to context. An error is returned if not large enough.
691 int (*call)(struct context *ctx, const struct token *token,
692 const char *str, unsigned int len,
693 void *buf, unsigned int size);
695 * Callback that provides possible values for this token, used for
696 * completion. Returns -1 in case of error, the number of possible
697 * values otherwise. If NULL, the token name is used.
699 * If buf is not NULL, entry index ent is written to buf and the
700 * full length of the entry is returned (same behavior as
703 int (*comp)(struct context *ctx, const struct token *token,
704 unsigned int ent, char *buf, unsigned int size);
705 /** Mandatory token name, no default value. */
709 /** Static initializer for the next field. */
710 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
712 /** Static initializer for a NEXT() entry. */
713 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
715 /** Static initializer for the args field. */
716 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
718 /** Static initializer for ARGS() to target a field. */
719 #define ARGS_ENTRY(s, f) \
720 (&(const struct arg){ \
721 .offset = offsetof(s, f), \
722 .size = sizeof(((s *)0)->f), \
725 /** Static initializer for ARGS() to target a bit-field. */
726 #define ARGS_ENTRY_BF(s, f, b) \
727 (&(const struct arg){ \
729 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
732 /** Static initializer for ARGS() to target a field with limits. */
733 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
734 (&(const struct arg){ \
738 .offset = offsetof(s, f), \
739 .size = sizeof(((s *)0)->f), \
742 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
743 #define ARGS_ENTRY_MASK(s, f, m) \
744 (&(const struct arg){ \
745 .offset = offsetof(s, f), \
746 .size = sizeof(((s *)0)->f), \
747 .mask = (const void *)(m), \
750 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
751 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
752 (&(const struct arg){ \
754 .offset = offsetof(s, f), \
755 .size = sizeof(((s *)0)->f), \
756 .mask = (const void *)(m), \
759 /** Static initializer for ARGS() to target a pointer. */
760 #define ARGS_ENTRY_PTR(s, f) \
761 (&(const struct arg){ \
762 .size = sizeof(*((s *)0)->f), \
765 /** Static initializer for ARGS() with arbitrary offset and size. */
766 #define ARGS_ENTRY_ARB(o, s) \
767 (&(const struct arg){ \
772 /** Same as ARGS_ENTRY_ARB() with bounded values. */
773 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
774 (&(const struct arg){ \
782 /** Same as ARGS_ENTRY() using network byte ordering. */
783 #define ARGS_ENTRY_HTON(s, f) \
784 (&(const struct arg){ \
786 .offset = offsetof(s, f), \
787 .size = sizeof(((s *)0)->f), \
790 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
791 #define ARG_ENTRY_HTON(s) \
792 (&(const struct arg){ \
798 /** Parser output buffer layout expected by cmd_flow_parsed(). */
800 enum index command; /**< Flow command. */
801 portid_t port; /**< Affected port ID. */
805 uint32_t action_id_n;
806 } ia_destroy; /**< Indirect action destroy arguments. */
809 } ia; /* Indirect action query arguments */
811 struct rte_flow_attr attr;
812 struct tunnel_ops tunnel_ops;
813 struct rte_flow_item *pattern;
814 struct rte_flow_action *actions;
818 } vc; /**< Validate/create arguments. */
822 } destroy; /**< Destroy arguments. */
827 } dump; /**< Dump arguments. */
830 struct rte_flow_action action;
831 } query; /**< Query arguments. */
835 } list; /**< List arguments. */
838 } isolate; /**< Isolated mode arguments. */
841 } aged; /**< Aged arguments. */
844 } policy;/**< Policy arguments. */
845 } args; /**< Command arguments. */
848 /** Private data for pattern items. */
849 struct parse_item_priv {
850 enum rte_flow_item_type type; /**< Item type. */
851 uint32_t size; /**< Size of item specification structure. */
854 #define PRIV_ITEM(t, s) \
855 (&(const struct parse_item_priv){ \
856 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
860 /** Private data for actions. */
861 struct parse_action_priv {
862 enum rte_flow_action_type type; /**< Action type. */
863 uint32_t size; /**< Size of action configuration structure. */
866 #define PRIV_ACTION(t, s) \
867 (&(const struct parse_action_priv){ \
868 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
872 static const enum index next_ia_create_attr[] = {
873 INDIRECT_ACTION_CREATE_ID,
874 INDIRECT_ACTION_INGRESS,
875 INDIRECT_ACTION_EGRESS,
876 INDIRECT_ACTION_TRANSFER,
877 INDIRECT_ACTION_SPEC,
881 static const enum index next_dump_subcmd[] = {
887 static const enum index next_ia_subcmd[] = {
888 INDIRECT_ACTION_CREATE,
889 INDIRECT_ACTION_UPDATE,
890 INDIRECT_ACTION_DESTROY,
891 INDIRECT_ACTION_QUERY,
895 static const enum index next_vc_attr[] = {
907 static const enum index next_destroy_attr[] = {
913 static const enum index next_dump_attr[] = {
919 static const enum index next_list_attr[] = {
925 static const enum index next_aged_attr[] = {
931 static const enum index next_ia_destroy_attr[] = {
932 INDIRECT_ACTION_DESTROY_ID,
937 static const enum index item_param[] = {
946 static const enum index next_item[] = {
983 ITEM_ICMP6_ND_OPT_SLA_ETH,
984 ITEM_ICMP6_ND_OPT_TLA_ETH,
1005 static const enum index item_fuzzy[] = {
1011 static const enum index item_any[] = {
1017 static const enum index item_vf[] = {
1023 static const enum index item_phy_port[] = {
1024 ITEM_PHY_PORT_INDEX,
1029 static const enum index item_port_id[] = {
1035 static const enum index item_mark[] = {
1041 static const enum index item_raw[] = {
1051 static const enum index item_eth[] = {
1060 static const enum index item_vlan[] = {
1065 ITEM_VLAN_INNER_TYPE,
1066 ITEM_VLAN_HAS_MORE_VLAN,
1071 static const enum index item_ipv4[] = {
1074 ITEM_IPV4_FRAGMENT_OFFSET,
1083 static const enum index item_ipv6[] = {
1090 ITEM_IPV6_HAS_FRAG_EXT,
1095 static const enum index item_icmp[] = {
1104 static const enum index item_udp[] = {
1111 static const enum index item_tcp[] = {
1119 static const enum index item_sctp[] = {
1128 static const enum index item_vxlan[] = {
1134 static const enum index item_e_tag[] = {
1135 ITEM_E_TAG_GRP_ECID_B,
1140 static const enum index item_nvgre[] = {
1146 static const enum index item_mpls[] = {
1154 static const enum index item_gre[] = {
1156 ITEM_GRE_C_RSVD0_VER,
1164 static const enum index item_gre_key[] = {
1170 static const enum index item_gtp[] = {
1178 static const enum index item_geneve[] = {
1186 static const enum index item_vxlan_gpe[] = {
1192 static const enum index item_arp_eth_ipv4[] = {
1193 ITEM_ARP_ETH_IPV4_SHA,
1194 ITEM_ARP_ETH_IPV4_SPA,
1195 ITEM_ARP_ETH_IPV4_THA,
1196 ITEM_ARP_ETH_IPV4_TPA,
1201 static const enum index item_ipv6_ext[] = {
1202 ITEM_IPV6_EXT_NEXT_HDR,
1207 static const enum index item_ipv6_frag_ext[] = {
1208 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1209 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1210 ITEM_IPV6_FRAG_EXT_ID,
1215 static const enum index item_icmp6[] = {
1222 static const enum index item_icmp6_nd_ns[] = {
1223 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1228 static const enum index item_icmp6_nd_na[] = {
1229 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1234 static const enum index item_icmp6_nd_opt[] = {
1235 ITEM_ICMP6_ND_OPT_TYPE,
1240 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1241 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1246 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1247 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1252 static const enum index item_meta[] = {
1258 static const enum index item_gtp_psc[] = {
1265 static const enum index item_pppoed[] = {
1271 static const enum index item_pppoes[] = {
1277 static const enum index item_pppoe_proto_id[] = {
1282 static const enum index item_higig2[] = {
1283 ITEM_HIGIG2_CLASSIFICATION,
1289 static const enum index item_esp[] = {
1295 static const enum index item_ah[] = {
1301 static const enum index item_pfcp[] = {
1308 static const enum index next_set_raw[] = {
1314 static const enum index item_tag[] = {
1321 static const enum index item_l2tpv3oip[] = {
1322 ITEM_L2TPV3OIP_SESSION_ID,
1327 static const enum index item_ecpri[] = {
1333 static const enum index item_ecpri_common[] = {
1334 ITEM_ECPRI_COMMON_TYPE,
1338 static const enum index item_ecpri_common_type[] = {
1339 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1340 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1341 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1345 static const enum index item_geneve_opt[] = {
1346 ITEM_GENEVE_OPT_CLASS,
1347 ITEM_GENEVE_OPT_TYPE,
1348 ITEM_GENEVE_OPT_LENGTH,
1349 ITEM_GENEVE_OPT_DATA,
1354 static const enum index item_integrity[] = {
1355 ITEM_INTEGRITY_LEVEL,
1356 ITEM_INTEGRITY_VALUE,
1360 static const enum index item_integrity_lv[] = {
1361 ITEM_INTEGRITY_LEVEL,
1362 ITEM_INTEGRITY_VALUE,
1367 static const enum index next_action[] = {
1384 ACTION_OF_SET_MPLS_TTL,
1385 ACTION_OF_DEC_MPLS_TTL,
1386 ACTION_OF_SET_NW_TTL,
1387 ACTION_OF_DEC_NW_TTL,
1388 ACTION_OF_COPY_TTL_OUT,
1389 ACTION_OF_COPY_TTL_IN,
1391 ACTION_OF_PUSH_VLAN,
1392 ACTION_OF_SET_VLAN_VID,
1393 ACTION_OF_SET_VLAN_PCP,
1395 ACTION_OF_PUSH_MPLS,
1402 ACTION_MPLSOGRE_ENCAP,
1403 ACTION_MPLSOGRE_DECAP,
1404 ACTION_MPLSOUDP_ENCAP,
1405 ACTION_MPLSOUDP_DECAP,
1406 ACTION_SET_IPV4_SRC,
1407 ACTION_SET_IPV4_DST,
1408 ACTION_SET_IPV6_SRC,
1409 ACTION_SET_IPV6_DST,
1425 ACTION_SET_IPV4_DSCP,
1426 ACTION_SET_IPV6_DSCP,
1430 ACTION_MODIFY_FIELD,
1432 ACTION_CONNTRACK_UPDATE,
1436 static const enum index action_mark[] = {
1442 static const enum index action_queue[] = {
1448 static const enum index action_count[] = {
1450 ACTION_COUNT_SHARED,
1455 static const enum index action_rss[] = {
1466 static const enum index action_vf[] = {
1473 static const enum index action_phy_port[] = {
1474 ACTION_PHY_PORT_ORIGINAL,
1475 ACTION_PHY_PORT_INDEX,
1480 static const enum index action_port_id[] = {
1481 ACTION_PORT_ID_ORIGINAL,
1487 static const enum index action_meter[] = {
1493 static const enum index action_meter_color[] = {
1494 ACTION_METER_COLOR_TYPE,
1499 static const enum index action_of_set_mpls_ttl[] = {
1500 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1505 static const enum index action_of_set_nw_ttl[] = {
1506 ACTION_OF_SET_NW_TTL_NW_TTL,
1511 static const enum index action_of_push_vlan[] = {
1512 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1517 static const enum index action_of_set_vlan_vid[] = {
1518 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1523 static const enum index action_of_set_vlan_pcp[] = {
1524 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1529 static const enum index action_of_pop_mpls[] = {
1530 ACTION_OF_POP_MPLS_ETHERTYPE,
1535 static const enum index action_of_push_mpls[] = {
1536 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1541 static const enum index action_set_ipv4_src[] = {
1542 ACTION_SET_IPV4_SRC_IPV4_SRC,
1547 static const enum index action_set_mac_src[] = {
1548 ACTION_SET_MAC_SRC_MAC_SRC,
1553 static const enum index action_set_ipv4_dst[] = {
1554 ACTION_SET_IPV4_DST_IPV4_DST,
1559 static const enum index action_set_ipv6_src[] = {
1560 ACTION_SET_IPV6_SRC_IPV6_SRC,
1565 static const enum index action_set_ipv6_dst[] = {
1566 ACTION_SET_IPV6_DST_IPV6_DST,
1571 static const enum index action_set_tp_src[] = {
1572 ACTION_SET_TP_SRC_TP_SRC,
1577 static const enum index action_set_tp_dst[] = {
1578 ACTION_SET_TP_DST_TP_DST,
1583 static const enum index action_set_ttl[] = {
1589 static const enum index action_jump[] = {
1595 static const enum index action_set_mac_dst[] = {
1596 ACTION_SET_MAC_DST_MAC_DST,
1601 static const enum index action_inc_tcp_seq[] = {
1602 ACTION_INC_TCP_SEQ_VALUE,
1607 static const enum index action_dec_tcp_seq[] = {
1608 ACTION_DEC_TCP_SEQ_VALUE,
1613 static const enum index action_inc_tcp_ack[] = {
1614 ACTION_INC_TCP_ACK_VALUE,
1619 static const enum index action_dec_tcp_ack[] = {
1620 ACTION_DEC_TCP_ACK_VALUE,
1625 static const enum index action_raw_encap[] = {
1626 ACTION_RAW_ENCAP_INDEX,
1631 static const enum index action_raw_decap[] = {
1632 ACTION_RAW_DECAP_INDEX,
1637 static const enum index action_set_tag[] = {
1638 ACTION_SET_TAG_DATA,
1639 ACTION_SET_TAG_INDEX,
1640 ACTION_SET_TAG_MASK,
1645 static const enum index action_set_meta[] = {
1646 ACTION_SET_META_DATA,
1647 ACTION_SET_META_MASK,
1652 static const enum index action_set_ipv4_dscp[] = {
1653 ACTION_SET_IPV4_DSCP_VALUE,
1658 static const enum index action_set_ipv6_dscp[] = {
1659 ACTION_SET_IPV6_DSCP_VALUE,
1664 static const enum index action_age[] = {
1671 static const enum index action_sample[] = {
1673 ACTION_SAMPLE_RATIO,
1674 ACTION_SAMPLE_INDEX,
1679 static const enum index next_action_sample[] = {
1692 static const enum index action_modify_field_dst[] = {
1693 ACTION_MODIFY_FIELD_DST_LEVEL,
1694 ACTION_MODIFY_FIELD_DST_OFFSET,
1695 ACTION_MODIFY_FIELD_SRC_TYPE,
1699 static const enum index action_modify_field_src[] = {
1700 ACTION_MODIFY_FIELD_SRC_LEVEL,
1701 ACTION_MODIFY_FIELD_SRC_OFFSET,
1702 ACTION_MODIFY_FIELD_SRC_VALUE,
1703 ACTION_MODIFY_FIELD_WIDTH,
1707 static const enum index action_update_conntrack[] = {
1708 ACTION_CONNTRACK_UPDATE_DIR,
1709 ACTION_CONNTRACK_UPDATE_CTX,
1714 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1715 const char *, unsigned int,
1716 void *, unsigned int);
1717 static int parse_set_sample_action(struct context *, const struct token *,
1718 const char *, unsigned int,
1719 void *, unsigned int);
1720 static int parse_set_init(struct context *, const struct token *,
1721 const char *, unsigned int,
1722 void *, unsigned int);
1723 static int parse_init(struct context *, const struct token *,
1724 const char *, unsigned int,
1725 void *, unsigned int);
1726 static int parse_vc(struct context *, const struct token *,
1727 const char *, unsigned int,
1728 void *, unsigned int);
1729 static int parse_vc_spec(struct context *, const struct token *,
1730 const char *, unsigned int, void *, unsigned int);
1731 static int parse_vc_conf(struct context *, const struct token *,
1732 const char *, unsigned int, void *, unsigned int);
1733 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1734 const char *, unsigned int,
1735 void *, unsigned int);
1736 static int parse_vc_action_meter_color_type(struct context *,
1737 const struct token *,
1738 const char *, unsigned int, void *,
1740 static int parse_vc_action_rss(struct context *, const struct token *,
1741 const char *, unsigned int, void *,
1743 static int parse_vc_action_rss_func(struct context *, const struct token *,
1744 const char *, unsigned int, void *,
1746 static int parse_vc_action_rss_type(struct context *, const struct token *,
1747 const char *, unsigned int, void *,
1749 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1750 const char *, unsigned int, void *,
1752 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1753 const char *, unsigned int, void *,
1755 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1756 const char *, unsigned int, void *,
1758 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1759 const char *, unsigned int, void *,
1761 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1762 const char *, unsigned int, void *,
1764 static int parse_vc_action_mplsogre_encap(struct context *,
1765 const struct token *, const char *,
1766 unsigned int, void *, unsigned int);
1767 static int parse_vc_action_mplsogre_decap(struct context *,
1768 const struct token *, const char *,
1769 unsigned int, void *, unsigned int);
1770 static int parse_vc_action_mplsoudp_encap(struct context *,
1771 const struct token *, const char *,
1772 unsigned int, void *, unsigned int);
1773 static int parse_vc_action_mplsoudp_decap(struct context *,
1774 const struct token *, const char *,
1775 unsigned int, void *, unsigned int);
1776 static int parse_vc_action_raw_encap(struct context *,
1777 const struct token *, const char *,
1778 unsigned int, void *, unsigned int);
1779 static int parse_vc_action_raw_decap(struct context *,
1780 const struct token *, const char *,
1781 unsigned int, void *, unsigned int);
1782 static int parse_vc_action_raw_encap_index(struct context *,
1783 const struct token *, const char *,
1784 unsigned int, void *, unsigned int);
1785 static int parse_vc_action_raw_decap_index(struct context *,
1786 const struct token *, const char *,
1787 unsigned int, void *, unsigned int);
1788 static int parse_vc_action_set_meta(struct context *ctx,
1789 const struct token *token, const char *str,
1790 unsigned int len, void *buf,
1792 static int parse_vc_action_sample(struct context *ctx,
1793 const struct token *token, const char *str,
1794 unsigned int len, void *buf,
1797 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
1798 const char *str, unsigned int len, void *buf,
1801 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
1802 const char *str, unsigned int len, void *buf,
1805 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
1806 const char *str, unsigned int len, void *buf,
1809 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
1810 const char *str, unsigned int len, void *buf,
1812 static int parse_destroy(struct context *, const struct token *,
1813 const char *, unsigned int,
1814 void *, unsigned int);
1815 static int parse_flush(struct context *, const struct token *,
1816 const char *, unsigned int,
1817 void *, unsigned int);
1818 static int parse_dump(struct context *, const struct token *,
1819 const char *, unsigned int,
1820 void *, unsigned int);
1821 static int parse_query(struct context *, const struct token *,
1822 const char *, unsigned int,
1823 void *, unsigned int);
1824 static int parse_action(struct context *, const struct token *,
1825 const char *, unsigned int,
1826 void *, unsigned int);
1827 static int parse_list(struct context *, const struct token *,
1828 const char *, unsigned int,
1829 void *, unsigned int);
1830 static int parse_aged(struct context *, const struct token *,
1831 const char *, unsigned int,
1832 void *, unsigned int);
1833 static int parse_isolate(struct context *, const struct token *,
1834 const char *, unsigned int,
1835 void *, unsigned int);
1836 static int parse_tunnel(struct context *, const struct token *,
1837 const char *, unsigned int,
1838 void *, unsigned int);
1839 static int parse_int(struct context *, const struct token *,
1840 const char *, unsigned int,
1841 void *, unsigned int);
1842 static int parse_prefix(struct context *, const struct token *,
1843 const char *, unsigned int,
1844 void *, unsigned int);
1845 static int parse_boolean(struct context *, const struct token *,
1846 const char *, unsigned int,
1847 void *, unsigned int);
1848 static int parse_string(struct context *, const struct token *,
1849 const char *, unsigned int,
1850 void *, unsigned int);
1851 static int parse_hex(struct context *ctx, const struct token *token,
1852 const char *str, unsigned int len,
1853 void *buf, unsigned int size);
1854 static int parse_string0(struct context *, const struct token *,
1855 const char *, unsigned int,
1856 void *, unsigned int);
1857 static int parse_mac_addr(struct context *, const struct token *,
1858 const char *, unsigned int,
1859 void *, unsigned int);
1860 static int parse_ipv4_addr(struct context *, const struct token *,
1861 const char *, unsigned int,
1862 void *, unsigned int);
1863 static int parse_ipv6_addr(struct context *, const struct token *,
1864 const char *, unsigned int,
1865 void *, unsigned int);
1866 static int parse_port(struct context *, const struct token *,
1867 const char *, unsigned int,
1868 void *, unsigned int);
1869 static int parse_ia(struct context *, const struct token *,
1870 const char *, unsigned int,
1871 void *, unsigned int);
1872 static int parse_ia_destroy(struct context *ctx, const struct token *token,
1873 const char *str, unsigned int len,
1874 void *buf, unsigned int size);
1875 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
1876 const char *str, unsigned int len, void *buf,
1878 static int parse_mp(struct context *, const struct token *,
1879 const char *, unsigned int,
1880 void *, unsigned int);
1881 static int comp_none(struct context *, const struct token *,
1882 unsigned int, char *, unsigned int);
1883 static int comp_boolean(struct context *, const struct token *,
1884 unsigned int, char *, unsigned int);
1885 static int comp_action(struct context *, const struct token *,
1886 unsigned int, char *, unsigned int);
1887 static int comp_port(struct context *, const struct token *,
1888 unsigned int, char *, unsigned int);
1889 static int comp_rule_id(struct context *, const struct token *,
1890 unsigned int, char *, unsigned int);
1891 static int comp_vc_action_rss_type(struct context *, const struct token *,
1892 unsigned int, char *, unsigned int);
1893 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1894 unsigned int, char *, unsigned int);
1895 static int comp_set_raw_index(struct context *, const struct token *,
1896 unsigned int, char *, unsigned int);
1897 static int comp_set_sample_index(struct context *, const struct token *,
1898 unsigned int, char *, unsigned int);
1899 static int comp_set_modify_field_op(struct context *, const struct token *,
1900 unsigned int, char *, unsigned int);
1901 static int comp_set_modify_field_id(struct context *, const struct token *,
1902 unsigned int, char *, unsigned int);
1904 /** Token definitions. */
1905 static const struct token token_list[] = {
1906 /* Special tokens. */
1909 .help = "null entry, abused as the entry point",
1910 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
1915 .help = "command may end here",
1918 .name = "START_SET",
1919 .help = "null entry, abused as the entry point for set",
1920 .next = NEXT(NEXT_ENTRY(SET)),
1925 .help = "set command may end here",
1927 /* Common tokens. */
1928 [COMMON_INTEGER] = {
1931 .help = "integer value",
1935 [COMMON_UNSIGNED] = {
1936 .name = "{unsigned}",
1938 .help = "unsigned integer value",
1945 .help = "prefix length for bit-mask",
1946 .call = parse_prefix,
1949 [COMMON_BOOLEAN] = {
1950 .name = "{boolean}",
1952 .help = "any boolean value",
1953 .call = parse_boolean,
1954 .comp = comp_boolean,
1959 .help = "fixed string",
1960 .call = parse_string,
1966 .help = "fixed string",
1969 [COMMON_FILE_PATH] = {
1970 .name = "{file path}",
1972 .help = "file path",
1973 .call = parse_string0,
1976 [COMMON_MAC_ADDR] = {
1977 .name = "{MAC address}",
1979 .help = "standard MAC address notation",
1980 .call = parse_mac_addr,
1983 [COMMON_IPV4_ADDR] = {
1984 .name = "{IPv4 address}",
1985 .type = "IPV4 ADDRESS",
1986 .help = "standard IPv4 address notation",
1987 .call = parse_ipv4_addr,
1990 [COMMON_IPV6_ADDR] = {
1991 .name = "{IPv6 address}",
1992 .type = "IPV6 ADDRESS",
1993 .help = "standard IPv6 address notation",
1994 .call = parse_ipv6_addr,
1997 [COMMON_RULE_ID] = {
1998 .name = "{rule id}",
2000 .help = "rule identifier",
2002 .comp = comp_rule_id,
2004 [COMMON_PORT_ID] = {
2005 .name = "{port_id}",
2007 .help = "port identifier",
2011 [COMMON_GROUP_ID] = {
2012 .name = "{group_id}",
2014 .help = "group identifier",
2018 [COMMON_PRIORITY_LEVEL] = {
2021 .help = "priority level",
2025 [COMMON_INDIRECT_ACTION_ID] = {
2026 .name = "{indirect_action_id}",
2027 .type = "INDIRECT_ACTION_ID",
2028 .help = "indirect action id",
2032 [COMMON_POLICY_ID] = {
2033 .name = "{policy_id}",
2034 .type = "POLCIY_ID",
2035 .help = "policy id",
2039 /* Top-level command. */
2042 .type = "{command} {port_id} [{arg} [...]]",
2043 .help = "manage ingress/egress flow rules",
2044 .next = NEXT(NEXT_ENTRY
2058 /* Top-level command. */
2059 [INDIRECT_ACTION] = {
2060 .name = "indirect_action",
2061 .type = "{command} {port_id} [{arg} [...]]",
2062 .help = "manage indirect actions",
2063 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2064 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2067 /* Sub-level commands. */
2068 [INDIRECT_ACTION_CREATE] = {
2070 .help = "create indirect action",
2071 .next = NEXT(next_ia_create_attr),
2074 [INDIRECT_ACTION_UPDATE] = {
2076 .help = "update indirect action",
2077 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2078 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2079 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2082 [INDIRECT_ACTION_DESTROY] = {
2084 .help = "destroy indirect action",
2085 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2086 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2087 .call = parse_ia_destroy,
2089 [INDIRECT_ACTION_QUERY] = {
2091 .help = "query indirect action",
2092 .next = NEXT(NEXT_ENTRY(END),
2093 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2094 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2099 .help = "check whether a flow rule can be created",
2100 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2101 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2106 .help = "create a flow rule",
2107 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2108 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2113 .help = "destroy specific flow rules",
2114 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2115 NEXT_ENTRY(COMMON_PORT_ID)),
2116 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2117 .call = parse_destroy,
2121 .help = "destroy all flow rules",
2122 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2123 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2124 .call = parse_flush,
2128 .help = "dump single/all flow rules to file",
2129 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2130 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2135 .help = "query an existing flow rule",
2136 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
2137 NEXT_ENTRY(COMMON_RULE_ID),
2138 NEXT_ENTRY(COMMON_PORT_ID)),
2139 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
2140 ARGS_ENTRY(struct buffer, args.query.rule),
2141 ARGS_ENTRY(struct buffer, port)),
2142 .call = parse_query,
2146 .help = "list existing flow rules",
2147 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2148 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2153 .help = "list and destroy aged flows",
2154 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2155 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2160 .help = "restrict ingress traffic to the defined flow rules",
2161 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
2162 NEXT_ENTRY(COMMON_PORT_ID)),
2163 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
2164 ARGS_ENTRY(struct buffer, port)),
2165 .call = parse_isolate,
2169 .help = "new tunnel API",
2170 .next = NEXT(NEXT_ENTRY
2171 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
2172 .call = parse_tunnel,
2174 /* Tunnel arguments. */
2177 .help = "create new tunnel object",
2178 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
2179 NEXT_ENTRY(COMMON_PORT_ID)),
2180 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2181 .call = parse_tunnel,
2183 [TUNNEL_CREATE_TYPE] = {
2185 .help = "create new tunnel",
2186 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
2187 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
2188 .call = parse_tunnel,
2190 [TUNNEL_DESTROY] = {
2192 .help = "destroy tunel",
2193 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
2194 NEXT_ENTRY(COMMON_PORT_ID)),
2195 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2196 .call = parse_tunnel,
2198 [TUNNEL_DESTROY_ID] = {
2200 .help = "tunnel identifier to testroy",
2201 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
2202 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2203 .call = parse_tunnel,
2207 .help = "list existing tunnels",
2208 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2209 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2210 .call = parse_tunnel,
2212 /* Destroy arguments. */
2215 .help = "specify a rule identifier",
2216 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2217 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
2218 .call = parse_destroy,
2220 /* Dump arguments. */
2224 .next = NEXT(next_dump_attr),
2225 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
2230 .help = "dump one rule",
2231 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2232 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
2233 ARGS_ENTRY(struct buffer, args.dump.rule)),
2236 /* Query arguments. */
2240 .help = "action to query, must be part of the rule",
2241 .call = parse_action,
2242 .comp = comp_action,
2244 /* List arguments. */
2247 .help = "specify a group",
2248 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2249 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
2254 .help = "specify aged flows need be destroyed",
2258 /* Validate/create attributes. */
2261 .help = "specify a group",
2262 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2263 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
2268 .help = "specify a priority level",
2269 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2270 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
2275 .help = "affect rule to ingress",
2276 .next = NEXT(next_vc_attr),
2281 .help = "affect rule to egress",
2282 .next = NEXT(next_vc_attr),
2287 .help = "apply rule directly to endpoints found in pattern",
2288 .next = NEXT(next_vc_attr),
2292 .name = "tunnel_set",
2293 .help = "tunnel steer rule",
2294 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2295 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2298 [VC_TUNNEL_MATCH] = {
2299 .name = "tunnel_match",
2300 .help = "tunnel match rule",
2301 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2302 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2305 /* Validate/create pattern. */
2308 .help = "submit a list of pattern items",
2309 .next = NEXT(next_item),
2314 .help = "match value perfectly (with full bit-mask)",
2315 .call = parse_vc_spec,
2317 [ITEM_PARAM_SPEC] = {
2319 .help = "match value according to configured bit-mask",
2320 .call = parse_vc_spec,
2322 [ITEM_PARAM_LAST] = {
2324 .help = "specify upper bound to establish a range",
2325 .call = parse_vc_spec,
2327 [ITEM_PARAM_MASK] = {
2329 .help = "specify bit-mask with relevant bits set to one",
2330 .call = parse_vc_spec,
2332 [ITEM_PARAM_PREFIX] = {
2334 .help = "generate bit-mask from a prefix length",
2335 .call = parse_vc_spec,
2339 .help = "specify next pattern item",
2340 .next = NEXT(next_item),
2344 .help = "end list of pattern items",
2345 .priv = PRIV_ITEM(END, 0),
2346 .next = NEXT(NEXT_ENTRY(ACTIONS)),
2351 .help = "no-op pattern item",
2352 .priv = PRIV_ITEM(VOID, 0),
2353 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2358 .help = "perform actions when pattern does not match",
2359 .priv = PRIV_ITEM(INVERT, 0),
2360 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2365 .help = "match any protocol for the current layer",
2366 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
2367 .next = NEXT(item_any),
2372 .help = "number of layers covered",
2373 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2374 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
2378 .help = "match traffic from/to the physical function",
2379 .priv = PRIV_ITEM(PF, 0),
2380 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2385 .help = "match traffic from/to a virtual function ID",
2386 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
2387 .next = NEXT(item_vf),
2393 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2394 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
2398 .help = "match traffic from/to a specific physical port",
2399 .priv = PRIV_ITEM(PHY_PORT,
2400 sizeof(struct rte_flow_item_phy_port)),
2401 .next = NEXT(item_phy_port),
2404 [ITEM_PHY_PORT_INDEX] = {
2406 .help = "physical port index",
2407 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
2409 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
2413 .help = "match traffic from/to a given DPDK port ID",
2414 .priv = PRIV_ITEM(PORT_ID,
2415 sizeof(struct rte_flow_item_port_id)),
2416 .next = NEXT(item_port_id),
2419 [ITEM_PORT_ID_ID] = {
2421 .help = "DPDK port ID",
2422 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
2424 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
2428 .help = "match traffic against value set in previously matched rule",
2429 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
2430 .next = NEXT(item_mark),
2435 .help = "Integer value to match against",
2436 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
2438 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
2442 .help = "match an arbitrary byte string",
2443 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
2444 .next = NEXT(item_raw),
2447 [ITEM_RAW_RELATIVE] = {
2449 .help = "look for pattern after the previous item",
2450 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2451 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2454 [ITEM_RAW_SEARCH] = {
2456 .help = "search pattern from offset (see also limit)",
2457 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2458 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2461 [ITEM_RAW_OFFSET] = {
2463 .help = "absolute or relative offset for pattern",
2464 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
2465 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
2467 [ITEM_RAW_LIMIT] = {
2469 .help = "search area limit for start of pattern",
2470 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2471 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
2473 [ITEM_RAW_PATTERN] = {
2475 .help = "byte string to look for",
2476 .next = NEXT(item_raw,
2477 NEXT_ENTRY(COMMON_STRING),
2478 NEXT_ENTRY(ITEM_PARAM_IS,
2481 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2482 ARGS_ENTRY(struct rte_flow_item_raw, length),
2483 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2484 ITEM_RAW_PATTERN_SIZE)),
2488 .help = "match Ethernet header",
2489 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
2490 .next = NEXT(item_eth),
2495 .help = "destination MAC",
2496 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2497 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
2501 .help = "source MAC",
2502 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2503 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
2507 .help = "EtherType",
2508 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2509 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
2511 [ITEM_ETH_HAS_VLAN] = {
2513 .help = "packet header contains VLAN",
2514 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2515 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
2520 .help = "match 802.1Q/ad VLAN tag",
2521 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
2522 .next = NEXT(item_vlan),
2527 .help = "tag control information",
2528 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2530 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
2534 .help = "priority code point",
2535 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2537 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2542 .help = "drop eligible indicator",
2543 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2545 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2550 .help = "VLAN identifier",
2551 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2553 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2556 [ITEM_VLAN_INNER_TYPE] = {
2557 .name = "inner_type",
2558 .help = "inner EtherType",
2559 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2561 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2564 [ITEM_VLAN_HAS_MORE_VLAN] = {
2565 .name = "has_more_vlan",
2566 .help = "packet header contains another VLAN",
2567 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2569 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
2574 .help = "match IPv4 header",
2575 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
2576 .next = NEXT(item_ipv4),
2581 .help = "type of service",
2582 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2584 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2585 hdr.type_of_service)),
2588 .name = "packet_id",
2589 .help = "fragment packet id",
2590 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2592 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2595 [ITEM_IPV4_FRAGMENT_OFFSET] = {
2596 .name = "fragment_offset",
2597 .help = "fragmentation flags and fragment offset",
2598 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2600 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2601 hdr.fragment_offset)),
2605 .help = "time to live",
2606 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2608 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2611 [ITEM_IPV4_PROTO] = {
2613 .help = "next protocol ID",
2614 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2616 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2617 hdr.next_proto_id)),
2621 .help = "source address",
2622 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2624 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2629 .help = "destination address",
2630 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2632 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2637 .help = "match IPv6 header",
2638 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
2639 .next = NEXT(item_ipv6),
2644 .help = "traffic class",
2645 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2647 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2649 "\x0f\xf0\x00\x00")),
2651 [ITEM_IPV6_FLOW] = {
2653 .help = "flow label",
2654 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2656 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2658 "\x00\x0f\xff\xff")),
2660 [ITEM_IPV6_PROTO] = {
2662 .help = "protocol (next header)",
2663 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2665 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2670 .help = "hop limit",
2671 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2673 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2678 .help = "source address",
2679 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2681 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2686 .help = "destination address",
2687 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2689 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2692 [ITEM_IPV6_HAS_FRAG_EXT] = {
2693 .name = "has_frag_ext",
2694 .help = "fragment packet attribute",
2695 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2697 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
2702 .help = "match ICMP header",
2703 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
2704 .next = NEXT(item_icmp),
2707 [ITEM_ICMP_TYPE] = {
2709 .help = "ICMP packet type",
2710 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2712 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2715 [ITEM_ICMP_CODE] = {
2717 .help = "ICMP packet code",
2718 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2720 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2723 [ITEM_ICMP_IDENT] = {
2725 .help = "ICMP packet identifier",
2726 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2728 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2733 .help = "ICMP packet sequence number",
2734 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2736 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2741 .help = "match UDP header",
2742 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
2743 .next = NEXT(item_udp),
2748 .help = "UDP source port",
2749 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
2751 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2756 .help = "UDP destination port",
2757 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2758 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2763 .help = "match TCP header",
2764 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
2765 .next = NEXT(item_tcp),
2770 .help = "TCP source port",
2771 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2772 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2777 .help = "TCP destination port",
2778 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2779 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2782 [ITEM_TCP_FLAGS] = {
2784 .help = "TCP flags",
2785 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2786 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2791 .help = "match SCTP header",
2792 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
2793 .next = NEXT(item_sctp),
2798 .help = "SCTP source port",
2799 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2801 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2806 .help = "SCTP destination port",
2807 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2809 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2814 .help = "validation tag",
2815 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2817 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2820 [ITEM_SCTP_CKSUM] = {
2823 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2825 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2830 .help = "match VXLAN header",
2831 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
2832 .next = NEXT(item_vxlan),
2835 [ITEM_VXLAN_VNI] = {
2837 .help = "VXLAN identifier",
2838 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
2840 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
2844 .help = "match E-Tag header",
2845 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
2846 .next = NEXT(item_e_tag),
2849 [ITEM_E_TAG_GRP_ECID_B] = {
2850 .name = "grp_ecid_b",
2851 .help = "GRP and E-CID base",
2852 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
2854 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
2860 .help = "match NVGRE header",
2861 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
2862 .next = NEXT(item_nvgre),
2865 [ITEM_NVGRE_TNI] = {
2867 .help = "virtual subnet ID",
2868 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
2870 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
2874 .help = "match MPLS header",
2875 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
2876 .next = NEXT(item_mpls),
2879 [ITEM_MPLS_LABEL] = {
2881 .help = "MPLS label",
2882 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2884 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2890 .help = "MPLS Traffic Class",
2891 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2893 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2899 .help = "MPLS Bottom-of-Stack",
2900 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2902 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2908 .help = "match GRE header",
2909 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
2910 .next = NEXT(item_gre),
2913 [ITEM_GRE_PROTO] = {
2915 .help = "GRE protocol type",
2916 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
2918 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2921 [ITEM_GRE_C_RSVD0_VER] = {
2922 .name = "c_rsvd0_ver",
2924 "checksum (1b), undefined (1b), key bit (1b),"
2925 " sequence number (1b), reserved 0 (9b),"
2927 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
2929 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2932 [ITEM_GRE_C_BIT] = {
2934 .help = "checksum bit (C)",
2935 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
2937 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2939 "\x80\x00\x00\x00")),
2941 [ITEM_GRE_S_BIT] = {
2943 .help = "sequence number bit (S)",
2944 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2945 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2947 "\x10\x00\x00\x00")),
2949 [ITEM_GRE_K_BIT] = {
2951 .help = "key bit (K)",
2952 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2953 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2955 "\x20\x00\x00\x00")),
2959 .help = "fuzzy pattern match, expect faster than default",
2960 .priv = PRIV_ITEM(FUZZY,
2961 sizeof(struct rte_flow_item_fuzzy)),
2962 .next = NEXT(item_fuzzy),
2965 [ITEM_FUZZY_THRESH] = {
2967 .help = "match accuracy threshold",
2968 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
2970 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
2975 .help = "match GTP header",
2976 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
2977 .next = NEXT(item_gtp),
2980 [ITEM_GTP_FLAGS] = {
2981 .name = "v_pt_rsv_flags",
2982 .help = "GTP flags",
2983 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2984 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
2987 [ITEM_GTP_MSG_TYPE] = {
2989 .help = "GTP message type",
2990 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2991 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
2995 .help = "tunnel endpoint identifier",
2996 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2997 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3001 .help = "match GTP header",
3002 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3003 .next = NEXT(item_gtp),
3008 .help = "match GTP header",
3009 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3010 .next = NEXT(item_gtp),
3015 .help = "match GENEVE header",
3016 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3017 .next = NEXT(item_geneve),
3020 [ITEM_GENEVE_VNI] = {
3022 .help = "virtual network identifier",
3023 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3025 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3027 [ITEM_GENEVE_PROTO] = {
3029 .help = "GENEVE protocol type",
3030 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3032 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3035 [ITEM_GENEVE_OPTLEN] = {
3037 .help = "GENEVE options length in dwords",
3038 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3040 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3041 ver_opt_len_o_c_rsvd0,
3044 [ITEM_VXLAN_GPE] = {
3045 .name = "vxlan-gpe",
3046 .help = "match VXLAN-GPE header",
3047 .priv = PRIV_ITEM(VXLAN_GPE,
3048 sizeof(struct rte_flow_item_vxlan_gpe)),
3049 .next = NEXT(item_vxlan_gpe),
3052 [ITEM_VXLAN_GPE_VNI] = {
3054 .help = "VXLAN-GPE identifier",
3055 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3057 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
3060 [ITEM_ARP_ETH_IPV4] = {
3061 .name = "arp_eth_ipv4",
3062 .help = "match ARP header for Ethernet/IPv4",
3063 .priv = PRIV_ITEM(ARP_ETH_IPV4,
3064 sizeof(struct rte_flow_item_arp_eth_ipv4)),
3065 .next = NEXT(item_arp_eth_ipv4),
3068 [ITEM_ARP_ETH_IPV4_SHA] = {
3070 .help = "sender hardware address",
3071 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3073 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3076 [ITEM_ARP_ETH_IPV4_SPA] = {
3078 .help = "sender IPv4 address",
3079 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3081 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3084 [ITEM_ARP_ETH_IPV4_THA] = {
3086 .help = "target hardware address",
3087 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3089 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3092 [ITEM_ARP_ETH_IPV4_TPA] = {
3094 .help = "target IPv4 address",
3095 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3097 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3102 .help = "match presence of any IPv6 extension header",
3103 .priv = PRIV_ITEM(IPV6_EXT,
3104 sizeof(struct rte_flow_item_ipv6_ext)),
3105 .next = NEXT(item_ipv6_ext),
3108 [ITEM_IPV6_EXT_NEXT_HDR] = {
3110 .help = "next header",
3111 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3113 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
3116 [ITEM_IPV6_FRAG_EXT] = {
3117 .name = "ipv6_frag_ext",
3118 .help = "match presence of IPv6 fragment extension header",
3119 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
3120 sizeof(struct rte_flow_item_ipv6_frag_ext)),
3121 .next = NEXT(item_ipv6_frag_ext),
3124 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
3126 .help = "next header",
3127 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3129 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
3132 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
3133 .name = "frag_data",
3134 .help = "fragment flags and offset",
3135 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3137 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3140 [ITEM_IPV6_FRAG_EXT_ID] = {
3141 .name = "packet_id",
3142 .help = "fragment packet id",
3143 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3145 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3150 .help = "match any ICMPv6 header",
3151 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
3152 .next = NEXT(item_icmp6),
3155 [ITEM_ICMP6_TYPE] = {
3157 .help = "ICMPv6 type",
3158 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3160 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3163 [ITEM_ICMP6_CODE] = {
3165 .help = "ICMPv6 code",
3166 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3168 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3171 [ITEM_ICMP6_ND_NS] = {
3172 .name = "icmp6_nd_ns",
3173 .help = "match ICMPv6 neighbor discovery solicitation",
3174 .priv = PRIV_ITEM(ICMP6_ND_NS,
3175 sizeof(struct rte_flow_item_icmp6_nd_ns)),
3176 .next = NEXT(item_icmp6_nd_ns),
3179 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
3180 .name = "target_addr",
3181 .help = "target address",
3182 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
3184 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
3187 [ITEM_ICMP6_ND_NA] = {
3188 .name = "icmp6_nd_na",
3189 .help = "match ICMPv6 neighbor discovery advertisement",
3190 .priv = PRIV_ITEM(ICMP6_ND_NA,
3191 sizeof(struct rte_flow_item_icmp6_nd_na)),
3192 .next = NEXT(item_icmp6_nd_na),
3195 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
3196 .name = "target_addr",
3197 .help = "target address",
3198 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
3200 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
3203 [ITEM_ICMP6_ND_OPT] = {
3204 .name = "icmp6_nd_opt",
3205 .help = "match presence of any ICMPv6 neighbor discovery"
3207 .priv = PRIV_ITEM(ICMP6_ND_OPT,
3208 sizeof(struct rte_flow_item_icmp6_nd_opt)),
3209 .next = NEXT(item_icmp6_nd_opt),
3212 [ITEM_ICMP6_ND_OPT_TYPE] = {
3214 .help = "ND option type",
3215 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3217 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
3220 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
3221 .name = "icmp6_nd_opt_sla_eth",
3222 .help = "match ICMPv6 neighbor discovery source Ethernet"
3223 " link-layer address option",
3225 (ICMP6_ND_OPT_SLA_ETH,
3226 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
3227 .next = NEXT(item_icmp6_nd_opt_sla_eth),
3230 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
3232 .help = "source Ethernet LLA",
3233 .next = NEXT(item_icmp6_nd_opt_sla_eth,
3234 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3235 .args = ARGS(ARGS_ENTRY_HTON
3236 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
3238 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
3239 .name = "icmp6_nd_opt_tla_eth",
3240 .help = "match ICMPv6 neighbor discovery target Ethernet"
3241 " link-layer address option",
3243 (ICMP6_ND_OPT_TLA_ETH,
3244 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
3245 .next = NEXT(item_icmp6_nd_opt_tla_eth),
3248 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
3250 .help = "target Ethernet LLA",
3251 .next = NEXT(item_icmp6_nd_opt_tla_eth,
3252 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3253 .args = ARGS(ARGS_ENTRY_HTON
3254 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
3258 .help = "match metadata header",
3259 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
3260 .next = NEXT(item_meta),
3263 [ITEM_META_DATA] = {
3265 .help = "metadata value",
3266 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
3268 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
3269 data, "\xff\xff\xff\xff")),
3273 .help = "match GRE key",
3274 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
3275 .next = NEXT(item_gre_key),
3278 [ITEM_GRE_KEY_VALUE] = {
3280 .help = "key value",
3281 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
3283 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3287 .help = "match GTP extension header with type 0x85",
3288 .priv = PRIV_ITEM(GTP_PSC,
3289 sizeof(struct rte_flow_item_gtp_psc)),
3290 .next = NEXT(item_gtp_psc),
3293 [ITEM_GTP_PSC_QFI] = {
3295 .help = "QoS flow identifier",
3296 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3298 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
3301 [ITEM_GTP_PSC_PDU_T] = {
3304 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3306 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
3311 .help = "match PPPoE session header",
3312 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
3313 .next = NEXT(item_pppoes),
3318 .help = "match PPPoE discovery header",
3319 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
3320 .next = NEXT(item_pppoed),
3323 [ITEM_PPPOE_SEID] = {
3325 .help = "session identifier",
3326 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
3328 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
3331 [ITEM_PPPOE_PROTO_ID] = {
3332 .name = "pppoe_proto_id",
3333 .help = "match PPPoE session protocol identifier",
3334 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
3335 sizeof(struct rte_flow_item_pppoe_proto_id)),
3336 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
3338 .args = ARGS(ARGS_ENTRY_HTON
3339 (struct rte_flow_item_pppoe_proto_id, proto_id)),
3344 .help = "matches higig2 header",
3345 .priv = PRIV_ITEM(HIGIG2,
3346 sizeof(struct rte_flow_item_higig2_hdr)),
3347 .next = NEXT(item_higig2),
3350 [ITEM_HIGIG2_CLASSIFICATION] = {
3351 .name = "classification",
3352 .help = "matches classification of higig2 header",
3353 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3355 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3356 hdr.ppt1.classification)),
3358 [ITEM_HIGIG2_VID] = {
3360 .help = "matches vid of higig2 header",
3361 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3363 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3368 .help = "match tag value",
3369 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
3370 .next = NEXT(item_tag),
3375 .help = "tag value to match",
3376 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3377 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
3379 [ITEM_TAG_INDEX] = {
3381 .help = "index of tag array to match",
3382 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3383 NEXT_ENTRY(ITEM_PARAM_IS)),
3384 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
3386 [ITEM_L2TPV3OIP] = {
3387 .name = "l2tpv3oip",
3388 .help = "match L2TPv3 over IP header",
3389 .priv = PRIV_ITEM(L2TPV3OIP,
3390 sizeof(struct rte_flow_item_l2tpv3oip)),
3391 .next = NEXT(item_l2tpv3oip),
3394 [ITEM_L2TPV3OIP_SESSION_ID] = {
3395 .name = "session_id",
3396 .help = "session identifier",
3397 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
3399 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
3404 .help = "match ESP header",
3405 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
3406 .next = NEXT(item_esp),
3411 .help = "security policy index",
3412 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3413 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
3418 .help = "match AH header",
3419 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
3420 .next = NEXT(item_ah),
3425 .help = "security parameters index",
3426 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3427 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
3431 .help = "match pfcp header",
3432 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
3433 .next = NEXT(item_pfcp),
3436 [ITEM_PFCP_S_FIELD] = {
3439 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3441 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
3444 [ITEM_PFCP_SEID] = {
3446 .help = "session endpoint identifier",
3447 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3449 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
3453 .help = "match eCPRI header",
3454 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
3455 .next = NEXT(item_ecpri),
3458 [ITEM_ECPRI_COMMON] = {
3460 .help = "eCPRI common header",
3461 .next = NEXT(item_ecpri_common),
3463 [ITEM_ECPRI_COMMON_TYPE] = {
3465 .help = "type of common header",
3466 .next = NEXT(item_ecpri_common_type),
3467 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
3469 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
3471 .help = "Type #0: IQ Data",
3472 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3474 .call = parse_vc_item_ecpri_type,
3476 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
3478 .help = "Physical Channel ID",
3479 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3480 ITEM_ECPRI_COMMON, ITEM_NEXT),
3481 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3482 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3485 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
3487 .help = "Type #2: Real-Time Control Data",
3488 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3490 .call = parse_vc_item_ecpri_type,
3492 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
3494 .help = "Real-Time Control Data ID",
3495 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3496 ITEM_ECPRI_COMMON, ITEM_NEXT),
3497 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3498 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3501 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
3502 .name = "delay_measure",
3503 .help = "Type #5: One-Way Delay Measurement",
3504 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3506 .call = parse_vc_item_ecpri_type,
3508 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
3510 .help = "Measurement ID",
3511 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3512 ITEM_ECPRI_COMMON, ITEM_NEXT),
3513 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3514 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3517 [ITEM_GENEVE_OPT] = {
3518 .name = "geneve-opt",
3519 .help = "GENEVE header option",
3520 .priv = PRIV_ITEM(GENEVE_OPT,
3521 sizeof(struct rte_flow_item_geneve_opt) +
3522 ITEM_GENEVE_OPT_DATA_SIZE),
3523 .next = NEXT(item_geneve_opt),
3526 [ITEM_GENEVE_OPT_CLASS] = {
3528 .help = "GENEVE option class",
3529 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3531 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
3534 [ITEM_GENEVE_OPT_TYPE] = {
3536 .help = "GENEVE option type",
3537 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3539 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
3542 [ITEM_GENEVE_OPT_LENGTH] = {
3544 .help = "GENEVE option data length (in 32b words)",
3545 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3547 .args = ARGS(ARGS_ENTRY_BOUNDED(
3548 struct rte_flow_item_geneve_opt, option_len,
3551 [ITEM_GENEVE_OPT_DATA] = {
3553 .help = "GENEVE option data pattern",
3554 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
3556 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
3557 ARGS_ENTRY_ARB(0, 0),
3559 (sizeof(struct rte_flow_item_geneve_opt),
3560 ITEM_GENEVE_OPT_DATA_SIZE)),
3562 [ITEM_INTEGRITY] = {
3563 .name = "integrity",
3564 .help = "match packet integrity",
3565 .priv = PRIV_ITEM(INTEGRITY,
3566 sizeof(struct rte_flow_item_integrity)),
3567 .next = NEXT(item_integrity),
3570 [ITEM_INTEGRITY_LEVEL] = {
3572 .help = "integrity level",
3573 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3575 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
3577 [ITEM_INTEGRITY_VALUE] = {
3579 .help = "integrity value",
3580 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3582 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
3584 [ITEM_CONNTRACK] = {
3585 .name = "conntrack",
3586 .help = "conntrack state",
3587 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
3589 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
3591 /* Validate/create actions. */
3594 .help = "submit a list of associated actions",
3595 .next = NEXT(next_action),
3600 .help = "specify next action",
3601 .next = NEXT(next_action),
3605 .help = "end list of actions",
3606 .priv = PRIV_ACTION(END, 0),
3611 .help = "no-op action",
3612 .priv = PRIV_ACTION(VOID, 0),
3613 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3616 [ACTION_PASSTHRU] = {
3618 .help = "let subsequent rule process matched packets",
3619 .priv = PRIV_ACTION(PASSTHRU, 0),
3620 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3625 .help = "redirect traffic to a given group",
3626 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
3627 .next = NEXT(action_jump),
3630 [ACTION_JUMP_GROUP] = {
3632 .help = "group to redirect traffic to",
3633 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
3634 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
3635 .call = parse_vc_conf,
3639 .help = "attach 32 bit value to packets",
3640 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
3641 .next = NEXT(action_mark),
3644 [ACTION_MARK_ID] = {
3646 .help = "32 bit value to return with packets",
3647 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
3648 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
3649 .call = parse_vc_conf,
3653 .help = "flag packets",
3654 .priv = PRIV_ACTION(FLAG, 0),
3655 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3660 .help = "assign packets to a given queue index",
3661 .priv = PRIV_ACTION(QUEUE,
3662 sizeof(struct rte_flow_action_queue)),
3663 .next = NEXT(action_queue),
3666 [ACTION_QUEUE_INDEX] = {
3668 .help = "queue index to use",
3669 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
3670 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
3671 .call = parse_vc_conf,
3675 .help = "drop packets (note: passthru has priority)",
3676 .priv = PRIV_ACTION(DROP, 0),
3677 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3682 .help = "enable counters for this rule",
3683 .priv = PRIV_ACTION(COUNT,
3684 sizeof(struct rte_flow_action_count)),
3685 .next = NEXT(action_count),
3688 [ACTION_COUNT_ID] = {
3689 .name = "identifier",
3690 .help = "counter identifier to use",
3691 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
3692 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
3693 .call = parse_vc_conf,
3695 [ACTION_COUNT_SHARED] = {
3697 .help = "shared counter",
3698 .next = NEXT(action_count, NEXT_ENTRY(COMMON_BOOLEAN)),
3699 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
3701 .call = parse_vc_conf,
3705 .help = "spread packets among several queues",
3706 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
3707 .next = NEXT(action_rss),
3708 .call = parse_vc_action_rss,
3710 [ACTION_RSS_FUNC] = {
3712 .help = "RSS hash function to apply",
3713 .next = NEXT(action_rss,
3714 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
3715 ACTION_RSS_FUNC_TOEPLITZ,
3716 ACTION_RSS_FUNC_SIMPLE_XOR,
3717 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
3719 [ACTION_RSS_FUNC_DEFAULT] = {
3721 .help = "default hash function",
3722 .call = parse_vc_action_rss_func,
3724 [ACTION_RSS_FUNC_TOEPLITZ] = {
3726 .help = "Toeplitz hash function",
3727 .call = parse_vc_action_rss_func,
3729 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
3730 .name = "simple_xor",
3731 .help = "simple XOR hash function",
3732 .call = parse_vc_action_rss_func,
3734 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
3735 .name = "symmetric_toeplitz",
3736 .help = "Symmetric Toeplitz hash function",
3737 .call = parse_vc_action_rss_func,
3739 [ACTION_RSS_LEVEL] = {
3741 .help = "encapsulation level for \"types\"",
3742 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
3743 .args = ARGS(ARGS_ENTRY_ARB
3744 (offsetof(struct action_rss_data, conf) +
3745 offsetof(struct rte_flow_action_rss, level),
3746 sizeof(((struct rte_flow_action_rss *)0)->
3749 [ACTION_RSS_TYPES] = {
3751 .help = "specific RSS hash types",
3752 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
3754 [ACTION_RSS_TYPE] = {
3756 .help = "RSS hash type",
3757 .call = parse_vc_action_rss_type,
3758 .comp = comp_vc_action_rss_type,
3760 [ACTION_RSS_KEY] = {
3762 .help = "RSS hash key",
3763 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
3764 .args = ARGS(ARGS_ENTRY_ARB
3765 (offsetof(struct action_rss_data, conf) +
3766 offsetof(struct rte_flow_action_rss, key),
3767 sizeof(((struct rte_flow_action_rss *)0)->key)),
3769 (offsetof(struct action_rss_data, conf) +
3770 offsetof(struct rte_flow_action_rss, key_len),
3771 sizeof(((struct rte_flow_action_rss *)0)->
3773 ARGS_ENTRY(struct action_rss_data, key)),
3775 [ACTION_RSS_KEY_LEN] = {
3777 .help = "RSS hash key length in bytes",
3778 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
3779 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3780 (offsetof(struct action_rss_data, conf) +
3781 offsetof(struct rte_flow_action_rss, key_len),
3782 sizeof(((struct rte_flow_action_rss *)0)->
3785 RSS_HASH_KEY_LENGTH)),
3787 [ACTION_RSS_QUEUES] = {
3789 .help = "queue indices to use",
3790 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
3791 .call = parse_vc_conf,
3793 [ACTION_RSS_QUEUE] = {
3795 .help = "queue index",
3796 .call = parse_vc_action_rss_queue,
3797 .comp = comp_vc_action_rss_queue,
3801 .help = "direct traffic to physical function",
3802 .priv = PRIV_ACTION(PF, 0),
3803 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3808 .help = "direct traffic to a virtual function ID",
3809 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
3810 .next = NEXT(action_vf),
3813 [ACTION_VF_ORIGINAL] = {
3815 .help = "use original VF ID if possible",
3816 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
3817 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
3819 .call = parse_vc_conf,
3824 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
3825 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
3826 .call = parse_vc_conf,
3828 [ACTION_PHY_PORT] = {
3830 .help = "direct packets to physical port index",
3831 .priv = PRIV_ACTION(PHY_PORT,
3832 sizeof(struct rte_flow_action_phy_port)),
3833 .next = NEXT(action_phy_port),
3836 [ACTION_PHY_PORT_ORIGINAL] = {
3838 .help = "use original port index if possible",
3839 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
3840 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
3842 .call = parse_vc_conf,
3844 [ACTION_PHY_PORT_INDEX] = {
3846 .help = "physical port index",
3847 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
3848 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
3850 .call = parse_vc_conf,
3852 [ACTION_PORT_ID] = {
3854 .help = "direct matching traffic to a given DPDK port ID",
3855 .priv = PRIV_ACTION(PORT_ID,
3856 sizeof(struct rte_flow_action_port_id)),
3857 .next = NEXT(action_port_id),
3860 [ACTION_PORT_ID_ORIGINAL] = {
3862 .help = "use original DPDK port ID if possible",
3863 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
3864 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
3866 .call = parse_vc_conf,
3868 [ACTION_PORT_ID_ID] = {
3870 .help = "DPDK port ID",
3871 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
3872 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
3873 .call = parse_vc_conf,
3877 .help = "meter the directed packets at given id",
3878 .priv = PRIV_ACTION(METER,
3879 sizeof(struct rte_flow_action_meter)),
3880 .next = NEXT(action_meter),
3883 [ACTION_METER_COLOR] = {
3885 .help = "meter color for the packets",
3886 .priv = PRIV_ACTION(METER_COLOR,
3887 sizeof(struct rte_flow_action_meter_color)),
3888 .next = NEXT(action_meter_color),
3891 [ACTION_METER_COLOR_TYPE] = {
3893 .help = "specific meter color",
3894 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
3895 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
3896 ACTION_METER_COLOR_YELLOW,
3897 ACTION_METER_COLOR_RED)),
3899 [ACTION_METER_COLOR_GREEN] = {
3901 .help = "meter color green",
3902 .call = parse_vc_action_meter_color_type,
3904 [ACTION_METER_COLOR_YELLOW] = {
3906 .help = "meter color yellow",
3907 .call = parse_vc_action_meter_color_type,
3909 [ACTION_METER_COLOR_RED] = {
3911 .help = "meter color red",
3912 .call = parse_vc_action_meter_color_type,
3914 [ACTION_METER_ID] = {
3916 .help = "meter id to use",
3917 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
3918 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
3919 .call = parse_vc_conf,
3921 [ACTION_OF_SET_MPLS_TTL] = {
3922 .name = "of_set_mpls_ttl",
3923 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
3926 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
3927 .next = NEXT(action_of_set_mpls_ttl),
3930 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
3933 .next = NEXT(action_of_set_mpls_ttl,
3934 NEXT_ENTRY(COMMON_UNSIGNED)),
3935 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
3937 .call = parse_vc_conf,
3939 [ACTION_OF_DEC_MPLS_TTL] = {
3940 .name = "of_dec_mpls_ttl",
3941 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
3942 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
3943 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3946 [ACTION_OF_SET_NW_TTL] = {
3947 .name = "of_set_nw_ttl",
3948 .help = "OpenFlow's OFPAT_SET_NW_TTL",
3951 sizeof(struct rte_flow_action_of_set_nw_ttl)),
3952 .next = NEXT(action_of_set_nw_ttl),
3955 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
3958 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
3959 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
3961 .call = parse_vc_conf,
3963 [ACTION_OF_DEC_NW_TTL] = {
3964 .name = "of_dec_nw_ttl",
3965 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
3966 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
3967 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3970 [ACTION_OF_COPY_TTL_OUT] = {
3971 .name = "of_copy_ttl_out",
3972 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
3973 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
3974 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3977 [ACTION_OF_COPY_TTL_IN] = {
3978 .name = "of_copy_ttl_in",
3979 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
3980 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
3981 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3984 [ACTION_OF_POP_VLAN] = {
3985 .name = "of_pop_vlan",
3986 .help = "OpenFlow's OFPAT_POP_VLAN",
3987 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
3988 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3991 [ACTION_OF_PUSH_VLAN] = {
3992 .name = "of_push_vlan",
3993 .help = "OpenFlow's OFPAT_PUSH_VLAN",
3996 sizeof(struct rte_flow_action_of_push_vlan)),
3997 .next = NEXT(action_of_push_vlan),
4000 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
4001 .name = "ethertype",
4002 .help = "EtherType",
4003 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
4004 .args = ARGS(ARGS_ENTRY_HTON
4005 (struct rte_flow_action_of_push_vlan,
4007 .call = parse_vc_conf,
4009 [ACTION_OF_SET_VLAN_VID] = {
4010 .name = "of_set_vlan_vid",
4011 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
4014 sizeof(struct rte_flow_action_of_set_vlan_vid)),
4015 .next = NEXT(action_of_set_vlan_vid),
4018 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
4021 .next = NEXT(action_of_set_vlan_vid,
4022 NEXT_ENTRY(COMMON_UNSIGNED)),
4023 .args = ARGS(ARGS_ENTRY_HTON
4024 (struct rte_flow_action_of_set_vlan_vid,
4026 .call = parse_vc_conf,
4028 [ACTION_OF_SET_VLAN_PCP] = {
4029 .name = "of_set_vlan_pcp",
4030 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
4033 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
4034 .next = NEXT(action_of_set_vlan_pcp),
4037 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
4039 .help = "VLAN priority",
4040 .next = NEXT(action_of_set_vlan_pcp,
4041 NEXT_ENTRY(COMMON_UNSIGNED)),
4042 .args = ARGS(ARGS_ENTRY_HTON
4043 (struct rte_flow_action_of_set_vlan_pcp,
4045 .call = parse_vc_conf,
4047 [ACTION_OF_POP_MPLS] = {
4048 .name = "of_pop_mpls",
4049 .help = "OpenFlow's OFPAT_POP_MPLS",
4050 .priv = PRIV_ACTION(OF_POP_MPLS,
4051 sizeof(struct rte_flow_action_of_pop_mpls)),
4052 .next = NEXT(action_of_pop_mpls),
4055 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
4056 .name = "ethertype",
4057 .help = "EtherType",
4058 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4059 .args = ARGS(ARGS_ENTRY_HTON
4060 (struct rte_flow_action_of_pop_mpls,
4062 .call = parse_vc_conf,
4064 [ACTION_OF_PUSH_MPLS] = {
4065 .name = "of_push_mpls",
4066 .help = "OpenFlow's OFPAT_PUSH_MPLS",
4069 sizeof(struct rte_flow_action_of_push_mpls)),
4070 .next = NEXT(action_of_push_mpls),
4073 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
4074 .name = "ethertype",
4075 .help = "EtherType",
4076 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4077 .args = ARGS(ARGS_ENTRY_HTON
4078 (struct rte_flow_action_of_push_mpls,
4080 .call = parse_vc_conf,
4082 [ACTION_VXLAN_ENCAP] = {
4083 .name = "vxlan_encap",
4084 .help = "VXLAN encapsulation, uses configuration set by \"set"
4086 .priv = PRIV_ACTION(VXLAN_ENCAP,
4087 sizeof(struct action_vxlan_encap_data)),
4088 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4089 .call = parse_vc_action_vxlan_encap,
4091 [ACTION_VXLAN_DECAP] = {
4092 .name = "vxlan_decap",
4093 .help = "Performs a decapsulation action by stripping all"
4094 " headers of the VXLAN tunnel network overlay from the"
4096 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
4097 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4100 [ACTION_NVGRE_ENCAP] = {
4101 .name = "nvgre_encap",
4102 .help = "NVGRE encapsulation, uses configuration set by \"set"
4104 .priv = PRIV_ACTION(NVGRE_ENCAP,
4105 sizeof(struct action_nvgre_encap_data)),
4106 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4107 .call = parse_vc_action_nvgre_encap,
4109 [ACTION_NVGRE_DECAP] = {
4110 .name = "nvgre_decap",
4111 .help = "Performs a decapsulation action by stripping all"
4112 " headers of the NVGRE tunnel network overlay from the"
4114 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
4115 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4118 [ACTION_L2_ENCAP] = {
4120 .help = "l2 encap, uses configuration set by"
4121 " \"set l2_encap\"",
4122 .priv = PRIV_ACTION(RAW_ENCAP,
4123 sizeof(struct action_raw_encap_data)),
4124 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4125 .call = parse_vc_action_l2_encap,
4127 [ACTION_L2_DECAP] = {
4129 .help = "l2 decap, uses configuration set by"
4130 " \"set l2_decap\"",
4131 .priv = PRIV_ACTION(RAW_DECAP,
4132 sizeof(struct action_raw_decap_data)),
4133 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4134 .call = parse_vc_action_l2_decap,
4136 [ACTION_MPLSOGRE_ENCAP] = {
4137 .name = "mplsogre_encap",
4138 .help = "mplsogre encapsulation, uses configuration set by"
4139 " \"set mplsogre_encap\"",
4140 .priv = PRIV_ACTION(RAW_ENCAP,
4141 sizeof(struct action_raw_encap_data)),
4142 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4143 .call = parse_vc_action_mplsogre_encap,
4145 [ACTION_MPLSOGRE_DECAP] = {
4146 .name = "mplsogre_decap",
4147 .help = "mplsogre decapsulation, uses configuration set by"
4148 " \"set mplsogre_decap\"",
4149 .priv = PRIV_ACTION(RAW_DECAP,
4150 sizeof(struct action_raw_decap_data)),
4151 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4152 .call = parse_vc_action_mplsogre_decap,
4154 [ACTION_MPLSOUDP_ENCAP] = {
4155 .name = "mplsoudp_encap",
4156 .help = "mplsoudp encapsulation, uses configuration set by"
4157 " \"set mplsoudp_encap\"",
4158 .priv = PRIV_ACTION(RAW_ENCAP,
4159 sizeof(struct action_raw_encap_data)),
4160 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4161 .call = parse_vc_action_mplsoudp_encap,
4163 [ACTION_MPLSOUDP_DECAP] = {
4164 .name = "mplsoudp_decap",
4165 .help = "mplsoudp decapsulation, uses configuration set by"
4166 " \"set mplsoudp_decap\"",
4167 .priv = PRIV_ACTION(RAW_DECAP,
4168 sizeof(struct action_raw_decap_data)),
4169 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4170 .call = parse_vc_action_mplsoudp_decap,
4172 [ACTION_SET_IPV4_SRC] = {
4173 .name = "set_ipv4_src",
4174 .help = "Set a new IPv4 source address in the outermost"
4176 .priv = PRIV_ACTION(SET_IPV4_SRC,
4177 sizeof(struct rte_flow_action_set_ipv4)),
4178 .next = NEXT(action_set_ipv4_src),
4181 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
4182 .name = "ipv4_addr",
4183 .help = "new IPv4 source address to set",
4184 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4185 .args = ARGS(ARGS_ENTRY_HTON
4186 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4187 .call = parse_vc_conf,
4189 [ACTION_SET_IPV4_DST] = {
4190 .name = "set_ipv4_dst",
4191 .help = "Set a new IPv4 destination address in the outermost"
4193 .priv = PRIV_ACTION(SET_IPV4_DST,
4194 sizeof(struct rte_flow_action_set_ipv4)),
4195 .next = NEXT(action_set_ipv4_dst),
4198 [ACTION_SET_IPV4_DST_IPV4_DST] = {
4199 .name = "ipv4_addr",
4200 .help = "new IPv4 destination address to set",
4201 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4202 .args = ARGS(ARGS_ENTRY_HTON
4203 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4204 .call = parse_vc_conf,
4206 [ACTION_SET_IPV6_SRC] = {
4207 .name = "set_ipv6_src",
4208 .help = "Set a new IPv6 source address in the outermost"
4210 .priv = PRIV_ACTION(SET_IPV6_SRC,
4211 sizeof(struct rte_flow_action_set_ipv6)),
4212 .next = NEXT(action_set_ipv6_src),
4215 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
4216 .name = "ipv6_addr",
4217 .help = "new IPv6 source address to set",
4218 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4219 .args = ARGS(ARGS_ENTRY_HTON
4220 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4221 .call = parse_vc_conf,
4223 [ACTION_SET_IPV6_DST] = {
4224 .name = "set_ipv6_dst",
4225 .help = "Set a new IPv6 destination address in the outermost"
4227 .priv = PRIV_ACTION(SET_IPV6_DST,
4228 sizeof(struct rte_flow_action_set_ipv6)),
4229 .next = NEXT(action_set_ipv6_dst),
4232 [ACTION_SET_IPV6_DST_IPV6_DST] = {
4233 .name = "ipv6_addr",
4234 .help = "new IPv6 destination address to set",
4235 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4236 .args = ARGS(ARGS_ENTRY_HTON
4237 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4238 .call = parse_vc_conf,
4240 [ACTION_SET_TP_SRC] = {
4241 .name = "set_tp_src",
4242 .help = "set a new source port number in the outermost"
4244 .priv = PRIV_ACTION(SET_TP_SRC,
4245 sizeof(struct rte_flow_action_set_tp)),
4246 .next = NEXT(action_set_tp_src),
4249 [ACTION_SET_TP_SRC_TP_SRC] = {
4251 .help = "new source port number to set",
4252 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
4253 .args = ARGS(ARGS_ENTRY_HTON
4254 (struct rte_flow_action_set_tp, port)),
4255 .call = parse_vc_conf,
4257 [ACTION_SET_TP_DST] = {
4258 .name = "set_tp_dst",
4259 .help = "set a new destination port number in the outermost"
4261 .priv = PRIV_ACTION(SET_TP_DST,
4262 sizeof(struct rte_flow_action_set_tp)),
4263 .next = NEXT(action_set_tp_dst),
4266 [ACTION_SET_TP_DST_TP_DST] = {
4268 .help = "new destination port number to set",
4269 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
4270 .args = ARGS(ARGS_ENTRY_HTON
4271 (struct rte_flow_action_set_tp, port)),
4272 .call = parse_vc_conf,
4274 [ACTION_MAC_SWAP] = {
4276 .help = "Swap the source and destination MAC addresses"
4277 " in the outermost Ethernet header",
4278 .priv = PRIV_ACTION(MAC_SWAP, 0),
4279 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4282 [ACTION_DEC_TTL] = {
4284 .help = "decrease network TTL if available",
4285 .priv = PRIV_ACTION(DEC_TTL, 0),
4286 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4289 [ACTION_SET_TTL] = {
4291 .help = "set ttl value",
4292 .priv = PRIV_ACTION(SET_TTL,
4293 sizeof(struct rte_flow_action_set_ttl)),
4294 .next = NEXT(action_set_ttl),
4297 [ACTION_SET_TTL_TTL] = {
4298 .name = "ttl_value",
4299 .help = "new ttl value to set",
4300 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4301 .args = ARGS(ARGS_ENTRY_HTON
4302 (struct rte_flow_action_set_ttl, ttl_value)),
4303 .call = parse_vc_conf,
4305 [ACTION_SET_MAC_SRC] = {
4306 .name = "set_mac_src",
4307 .help = "set source mac address",
4308 .priv = PRIV_ACTION(SET_MAC_SRC,
4309 sizeof(struct rte_flow_action_set_mac)),
4310 .next = NEXT(action_set_mac_src),
4313 [ACTION_SET_MAC_SRC_MAC_SRC] = {
4315 .help = "new source mac address",
4316 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
4317 .args = ARGS(ARGS_ENTRY_HTON
4318 (struct rte_flow_action_set_mac, mac_addr)),
4319 .call = parse_vc_conf,
4321 [ACTION_SET_MAC_DST] = {
4322 .name = "set_mac_dst",
4323 .help = "set destination mac address",
4324 .priv = PRIV_ACTION(SET_MAC_DST,
4325 sizeof(struct rte_flow_action_set_mac)),
4326 .next = NEXT(action_set_mac_dst),
4329 [ACTION_SET_MAC_DST_MAC_DST] = {
4331 .help = "new destination mac address to set",
4332 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
4333 .args = ARGS(ARGS_ENTRY_HTON
4334 (struct rte_flow_action_set_mac, mac_addr)),
4335 .call = parse_vc_conf,
4337 [ACTION_INC_TCP_SEQ] = {
4338 .name = "inc_tcp_seq",
4339 .help = "increase TCP sequence number",
4340 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
4341 .next = NEXT(action_inc_tcp_seq),
4344 [ACTION_INC_TCP_SEQ_VALUE] = {
4346 .help = "the value to increase TCP sequence number by",
4347 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4348 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4349 .call = parse_vc_conf,
4351 [ACTION_DEC_TCP_SEQ] = {
4352 .name = "dec_tcp_seq",
4353 .help = "decrease TCP sequence number",
4354 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
4355 .next = NEXT(action_dec_tcp_seq),
4358 [ACTION_DEC_TCP_SEQ_VALUE] = {
4360 .help = "the value to decrease TCP sequence number by",
4361 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4362 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4363 .call = parse_vc_conf,
4365 [ACTION_INC_TCP_ACK] = {
4366 .name = "inc_tcp_ack",
4367 .help = "increase TCP acknowledgment number",
4368 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
4369 .next = NEXT(action_inc_tcp_ack),
4372 [ACTION_INC_TCP_ACK_VALUE] = {
4374 .help = "the value to increase TCP acknowledgment number by",
4375 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4376 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4377 .call = parse_vc_conf,
4379 [ACTION_DEC_TCP_ACK] = {
4380 .name = "dec_tcp_ack",
4381 .help = "decrease TCP acknowledgment number",
4382 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
4383 .next = NEXT(action_dec_tcp_ack),
4386 [ACTION_DEC_TCP_ACK_VALUE] = {
4388 .help = "the value to decrease TCP acknowledgment number by",
4389 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4390 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4391 .call = parse_vc_conf,
4393 [ACTION_RAW_ENCAP] = {
4394 .name = "raw_encap",
4395 .help = "encapsulation data, defined by set raw_encap",
4396 .priv = PRIV_ACTION(RAW_ENCAP,
4397 sizeof(struct action_raw_encap_data)),
4398 .next = NEXT(action_raw_encap),
4399 .call = parse_vc_action_raw_encap,
4401 [ACTION_RAW_ENCAP_INDEX] = {
4403 .help = "the index of raw_encap_confs",
4404 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
4406 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
4409 .help = "unsigned integer value",
4410 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4411 .call = parse_vc_action_raw_encap_index,
4412 .comp = comp_set_raw_index,
4414 [ACTION_RAW_DECAP] = {
4415 .name = "raw_decap",
4416 .help = "decapsulation data, defined by set raw_encap",
4417 .priv = PRIV_ACTION(RAW_DECAP,
4418 sizeof(struct action_raw_decap_data)),
4419 .next = NEXT(action_raw_decap),
4420 .call = parse_vc_action_raw_decap,
4422 [ACTION_RAW_DECAP_INDEX] = {
4424 .help = "the index of raw_encap_confs",
4425 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
4427 [ACTION_RAW_DECAP_INDEX_VALUE] = {
4430 .help = "unsigned integer value",
4431 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4432 .call = parse_vc_action_raw_decap_index,
4433 .comp = comp_set_raw_index,
4435 [ACTION_MODIFY_FIELD] = {
4436 .name = "modify_field",
4437 .help = "modify destination field with data from source field",
4438 .priv = PRIV_ACTION(MODIFY_FIELD,
4439 sizeof(struct rte_flow_action_modify_field)),
4440 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
4443 [ACTION_MODIFY_FIELD_OP] = {
4445 .help = "operation type",
4446 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
4447 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
4448 .call = parse_vc_conf,
4450 [ACTION_MODIFY_FIELD_OP_VALUE] = {
4451 .name = "{operation}",
4452 .help = "operation type value",
4453 .call = parse_vc_modify_field_op,
4454 .comp = comp_set_modify_field_op,
4456 [ACTION_MODIFY_FIELD_DST_TYPE] = {
4458 .help = "destination field type",
4459 .next = NEXT(action_modify_field_dst,
4460 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
4461 .call = parse_vc_conf,
4463 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
4464 .name = "{dst_type}",
4465 .help = "destination field type value",
4466 .call = parse_vc_modify_field_id,
4467 .comp = comp_set_modify_field_id,
4469 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
4470 .name = "dst_level",
4471 .help = "destination field level",
4472 .next = NEXT(action_modify_field_dst,
4473 NEXT_ENTRY(COMMON_UNSIGNED)),
4474 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4476 .call = parse_vc_conf,
4478 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
4479 .name = "dst_offset",
4480 .help = "destination field bit offset",
4481 .next = NEXT(action_modify_field_dst,
4482 NEXT_ENTRY(COMMON_UNSIGNED)),
4483 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4485 .call = parse_vc_conf,
4487 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
4489 .help = "source field type",
4490 .next = NEXT(action_modify_field_src,
4491 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
4492 .call = parse_vc_conf,
4494 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
4495 .name = "{src_type}",
4496 .help = "source field type value",
4497 .call = parse_vc_modify_field_id,
4498 .comp = comp_set_modify_field_id,
4500 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
4501 .name = "src_level",
4502 .help = "source field level",
4503 .next = NEXT(action_modify_field_src,
4504 NEXT_ENTRY(COMMON_UNSIGNED)),
4505 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4507 .call = parse_vc_conf,
4509 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
4510 .name = "src_offset",
4511 .help = "source field bit offset",
4512 .next = NEXT(action_modify_field_src,
4513 NEXT_ENTRY(COMMON_UNSIGNED)),
4514 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4516 .call = parse_vc_conf,
4518 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
4519 .name = "src_value",
4520 .help = "source immediate value",
4521 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
4522 NEXT_ENTRY(COMMON_UNSIGNED)),
4523 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4525 .call = parse_vc_conf,
4527 [ACTION_MODIFY_FIELD_WIDTH] = {
4529 .help = "number of bits to copy",
4530 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
4531 NEXT_ENTRY(COMMON_UNSIGNED)),
4532 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4534 .call = parse_vc_conf,
4536 /* Top level command. */
4539 .help = "set raw encap/decap/sample data",
4540 .type = "set raw_encap|raw_decap <index> <pattern>"
4541 " or set sample_actions <index> <action>",
4542 .next = NEXT(NEXT_ENTRY
4545 SET_SAMPLE_ACTIONS)),
4546 .call = parse_set_init,
4548 /* Sub-level commands. */
4550 .name = "raw_encap",
4551 .help = "set raw encap data",
4552 .next = NEXT(next_set_raw),
4553 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4554 (offsetof(struct buffer, port),
4555 sizeof(((struct buffer *)0)->port),
4556 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
4557 .call = parse_set_raw_encap_decap,
4560 .name = "raw_decap",
4561 .help = "set raw decap data",
4562 .next = NEXT(next_set_raw),
4563 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4564 (offsetof(struct buffer, port),
4565 sizeof(((struct buffer *)0)->port),
4566 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
4567 .call = parse_set_raw_encap_decap,
4571 .type = "COMMON_UNSIGNED",
4572 .help = "index of raw_encap/raw_decap data",
4573 .next = NEXT(next_item),
4576 [SET_SAMPLE_INDEX] = {
4579 .help = "index of sample actions",
4580 .next = NEXT(next_action_sample),
4583 [SET_SAMPLE_ACTIONS] = {
4584 .name = "sample_actions",
4585 .help = "set sample actions list",
4586 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
4587 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4588 (offsetof(struct buffer, port),
4589 sizeof(((struct buffer *)0)->port),
4590 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
4591 .call = parse_set_sample_action,
4593 [ACTION_SET_TAG] = {
4596 .priv = PRIV_ACTION(SET_TAG,
4597 sizeof(struct rte_flow_action_set_tag)),
4598 .next = NEXT(action_set_tag),
4601 [ACTION_SET_TAG_INDEX] = {
4603 .help = "index of tag array",
4604 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4605 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
4606 .call = parse_vc_conf,
4608 [ACTION_SET_TAG_DATA] = {
4610 .help = "tag value",
4611 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4612 .args = ARGS(ARGS_ENTRY
4613 (struct rte_flow_action_set_tag, data)),
4614 .call = parse_vc_conf,
4616 [ACTION_SET_TAG_MASK] = {
4618 .help = "mask for tag value",
4619 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4620 .args = ARGS(ARGS_ENTRY
4621 (struct rte_flow_action_set_tag, mask)),
4622 .call = parse_vc_conf,
4624 [ACTION_SET_META] = {
4626 .help = "set metadata",
4627 .priv = PRIV_ACTION(SET_META,
4628 sizeof(struct rte_flow_action_set_meta)),
4629 .next = NEXT(action_set_meta),
4630 .call = parse_vc_action_set_meta,
4632 [ACTION_SET_META_DATA] = {
4634 .help = "metadata value",
4635 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
4636 .args = ARGS(ARGS_ENTRY
4637 (struct rte_flow_action_set_meta, data)),
4638 .call = parse_vc_conf,
4640 [ACTION_SET_META_MASK] = {
4642 .help = "mask for metadata value",
4643 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
4644 .args = ARGS(ARGS_ENTRY
4645 (struct rte_flow_action_set_meta, mask)),
4646 .call = parse_vc_conf,
4648 [ACTION_SET_IPV4_DSCP] = {
4649 .name = "set_ipv4_dscp",
4650 .help = "set DSCP value",
4651 .priv = PRIV_ACTION(SET_IPV4_DSCP,
4652 sizeof(struct rte_flow_action_set_dscp)),
4653 .next = NEXT(action_set_ipv4_dscp),
4656 [ACTION_SET_IPV4_DSCP_VALUE] = {
4657 .name = "dscp_value",
4658 .help = "new IPv4 DSCP value to set",
4659 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
4660 .args = ARGS(ARGS_ENTRY
4661 (struct rte_flow_action_set_dscp, dscp)),
4662 .call = parse_vc_conf,
4664 [ACTION_SET_IPV6_DSCP] = {
4665 .name = "set_ipv6_dscp",
4666 .help = "set DSCP value",
4667 .priv = PRIV_ACTION(SET_IPV6_DSCP,
4668 sizeof(struct rte_flow_action_set_dscp)),
4669 .next = NEXT(action_set_ipv6_dscp),
4672 [ACTION_SET_IPV6_DSCP_VALUE] = {
4673 .name = "dscp_value",
4674 .help = "new IPv6 DSCP value to set",
4675 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
4676 .args = ARGS(ARGS_ENTRY
4677 (struct rte_flow_action_set_dscp, dscp)),
4678 .call = parse_vc_conf,
4682 .help = "set a specific metadata header",
4683 .next = NEXT(action_age),
4684 .priv = PRIV_ACTION(AGE,
4685 sizeof(struct rte_flow_action_age)),
4688 [ACTION_AGE_TIMEOUT] = {
4690 .help = "flow age timeout value",
4691 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
4693 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
4694 .call = parse_vc_conf,
4698 .help = "set a sample action",
4699 .next = NEXT(action_sample),
4700 .priv = PRIV_ACTION(SAMPLE,
4701 sizeof(struct action_sample_data)),
4702 .call = parse_vc_action_sample,
4704 [ACTION_SAMPLE_RATIO] = {
4706 .help = "flow sample ratio value",
4707 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
4708 .args = ARGS(ARGS_ENTRY_ARB
4709 (offsetof(struct action_sample_data, conf) +
4710 offsetof(struct rte_flow_action_sample, ratio),
4711 sizeof(((struct rte_flow_action_sample *)0)->
4714 [ACTION_SAMPLE_INDEX] = {
4716 .help = "the index of sample actions list",
4717 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
4719 [ACTION_SAMPLE_INDEX_VALUE] = {
4721 .type = "COMMON_UNSIGNED",
4722 .help = "unsigned integer value",
4723 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4724 .call = parse_vc_action_sample_index,
4725 .comp = comp_set_sample_index,
4727 [ACTION_CONNTRACK] = {
4728 .name = "conntrack",
4729 .help = "create a conntrack object",
4730 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4731 .priv = PRIV_ACTION(CONNTRACK,
4732 sizeof(struct rte_flow_action_conntrack)),
4735 [ACTION_CONNTRACK_UPDATE] = {
4736 .name = "conntrack_update",
4737 .help = "update a conntrack object",
4738 .next = NEXT(action_update_conntrack),
4739 .priv = PRIV_ACTION(CONNTRACK,
4740 sizeof(struct rte_flow_modify_conntrack)),
4743 [ACTION_CONNTRACK_UPDATE_DIR] = {
4745 .help = "update a conntrack object direction",
4746 .next = NEXT(action_update_conntrack),
4747 .call = parse_vc_action_conntrack_update,
4749 [ACTION_CONNTRACK_UPDATE_CTX] = {
4751 .help = "update a conntrack object context",
4752 .next = NEXT(action_update_conntrack),
4753 .call = parse_vc_action_conntrack_update,
4755 /* Indirect action destroy arguments. */
4756 [INDIRECT_ACTION_DESTROY_ID] = {
4757 .name = "action_id",
4758 .help = "specify a indirect action id to destroy",
4759 .next = NEXT(next_ia_destroy_attr,
4760 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4761 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
4762 args.ia_destroy.action_id)),
4763 .call = parse_ia_destroy,
4765 /* Indirect action create arguments. */
4766 [INDIRECT_ACTION_CREATE_ID] = {
4767 .name = "action_id",
4768 .help = "specify a indirect action id to create",
4769 .next = NEXT(next_ia_create_attr,
4770 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4771 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4773 [ACTION_INDIRECT] = {
4775 .help = "apply indirect action by id",
4776 .priv = PRIV_ACTION(INDIRECT, 0),
4777 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
4778 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
4781 [INDIRECT_ACTION_ID2PTR] = {
4782 .name = "{action_id}",
4783 .type = "INDIRECT_ACTION_ID",
4784 .help = "indirect action id",
4785 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4786 .call = parse_ia_id2ptr,
4789 [INDIRECT_ACTION_INGRESS] = {
4791 .help = "affect rule to ingress",
4792 .next = NEXT(next_ia_create_attr),
4795 [INDIRECT_ACTION_EGRESS] = {
4797 .help = "affect rule to egress",
4798 .next = NEXT(next_ia_create_attr),
4801 [INDIRECT_ACTION_TRANSFER] = {
4803 .help = "affect rule to transfer",
4804 .next = NEXT(next_ia_create_attr),
4807 [INDIRECT_ACTION_SPEC] = {
4809 .help = "specify action to create indirect handle",
4810 .next = NEXT(next_action),
4813 .name = "g_actions",
4814 .help = "submit a list of associated actions for green",
4815 .next = NEXT(next_action),
4819 .name = "y_actions",
4820 .help = "submit a list of associated actions for yellow",
4821 .next = NEXT(next_action),
4824 .name = "r_actions",
4825 .help = "submit a list of associated actions for red",
4826 .next = NEXT(next_action),
4829 /* Top-level command. */
4832 .type = "port meter policy {port_id} {arg}",
4833 .help = "add port meter policy",
4834 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
4837 /* Sub-level commands. */
4840 .help = "add port meter policy",
4841 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
4843 [ITEM_POL_METER] = {
4845 .help = "add port meter policy",
4846 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
4848 [ITEM_POL_POLICY] = {
4850 .help = "add port meter policy",
4851 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
4852 NEXT_ENTRY(ACTION_POL_Y),
4853 NEXT_ENTRY(ACTION_POL_G),
4854 NEXT_ENTRY(COMMON_POLICY_ID),
4855 NEXT_ENTRY(COMMON_PORT_ID)),
4856 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
4857 ARGS_ENTRY(struct buffer, port)),
4862 /** Remove and return last entry from argument stack. */
4863 static const struct arg *
4864 pop_args(struct context *ctx)
4866 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
4869 /** Add entry on top of the argument stack. */
4871 push_args(struct context *ctx, const struct arg *arg)
4873 if (ctx->args_num == CTX_STACK_SIZE)
4875 ctx->args[ctx->args_num++] = arg;
4879 /** Spread value into buffer according to bit-mask. */
4881 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
4883 uint32_t i = arg->size;
4891 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4900 unsigned int shift = 0;
4901 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
4903 for (shift = 0; arg->mask[i] >> shift; ++shift) {
4904 if (!(arg->mask[i] & (1 << shift)))
4909 *buf &= ~(1 << shift);
4910 *buf |= (val & 1) << shift;
4918 /** Compare a string with a partial one of a given length. */
4920 strcmp_partial(const char *full, const char *partial, size_t partial_len)
4922 int r = strncmp(full, partial, partial_len);
4926 if (strlen(full) <= partial_len)
4928 return full[partial_len];
4932 * Parse a prefix length and generate a bit-mask.
4934 * Last argument (ctx->args) is retrieved to determine mask size, storage
4935 * location and whether the result must use network byte ordering.
4938 parse_prefix(struct context *ctx, const struct token *token,
4939 const char *str, unsigned int len,
4940 void *buf, unsigned int size)
4942 const struct arg *arg = pop_args(ctx);
4943 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
4950 /* Argument is expected. */
4954 u = strtoumax(str, &end, 0);
4955 if (errno || (size_t)(end - str) != len)
4960 extra = arg_entry_bf_fill(NULL, 0, arg);
4969 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
4970 !arg_entry_bf_fill(ctx->objmask, -1, arg))
4977 if (bytes > size || bytes + !!extra > size)
4981 buf = (uint8_t *)ctx->object + arg->offset;
4982 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4984 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
4985 memset(buf, 0x00, size - bytes);
4987 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
4991 memset(buf, 0xff, bytes);
4992 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
4994 ((uint8_t *)buf)[bytes] = conv[extra];
4997 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5000 push_args(ctx, arg);
5004 /** Default parsing function for token name matching. */
5006 parse_default(struct context *ctx, const struct token *token,
5007 const char *str, unsigned int len,
5008 void *buf, unsigned int size)
5013 if (strcmp_partial(token->name, str, len))
5018 /** Parse flow command, initialize output buffer for subsequent tokens. */
5020 parse_init(struct context *ctx, const struct token *token,
5021 const char *str, unsigned int len,
5022 void *buf, unsigned int size)
5024 struct buffer *out = buf;
5026 /* Token name must match. */
5027 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5029 /* Nothing else to do if there is no buffer. */
5032 /* Make sure buffer is large enough. */
5033 if (size < sizeof(*out))
5035 /* Initialize buffer. */
5036 memset(out, 0x00, sizeof(*out));
5037 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5040 ctx->objmask = NULL;
5044 /** Parse tokens for indirect action commands. */
5046 parse_ia(struct context *ctx, const struct token *token,
5047 const char *str, unsigned int len,
5048 void *buf, unsigned int size)
5050 struct buffer *out = buf;
5052 /* Token name must match. */
5053 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5055 /* Nothing else to do if there is no buffer. */
5058 if (!out->command) {
5059 if (ctx->curr != INDIRECT_ACTION)
5061 if (sizeof(*out) > size)
5063 out->command = ctx->curr;
5066 ctx->objmask = NULL;
5067 out->args.vc.data = (uint8_t *)out + size;
5070 switch (ctx->curr) {
5071 case INDIRECT_ACTION_CREATE:
5072 case INDIRECT_ACTION_UPDATE:
5073 out->args.vc.actions =
5074 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5076 out->args.vc.attr.group = UINT32_MAX;
5078 case INDIRECT_ACTION_QUERY:
5079 out->command = ctx->curr;
5082 ctx->objmask = NULL;
5084 case INDIRECT_ACTION_EGRESS:
5085 out->args.vc.attr.egress = 1;
5087 case INDIRECT_ACTION_INGRESS:
5088 out->args.vc.attr.ingress = 1;
5090 case INDIRECT_ACTION_TRANSFER:
5091 out->args.vc.attr.transfer = 1;
5099 /** Parse tokens for indirect action destroy command. */
5101 parse_ia_destroy(struct context *ctx, const struct token *token,
5102 const char *str, unsigned int len,
5103 void *buf, unsigned int size)
5105 struct buffer *out = buf;
5106 uint32_t *action_id;
5108 /* Token name must match. */
5109 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5111 /* Nothing else to do if there is no buffer. */
5114 if (!out->command || out->command == INDIRECT_ACTION) {
5115 if (ctx->curr != INDIRECT_ACTION_DESTROY)
5117 if (sizeof(*out) > size)
5119 out->command = ctx->curr;
5122 ctx->objmask = NULL;
5123 out->args.ia_destroy.action_id =
5124 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5128 action_id = out->args.ia_destroy.action_id
5129 + out->args.ia_destroy.action_id_n++;
5130 if ((uint8_t *)action_id > (uint8_t *)out + size)
5133 ctx->object = action_id;
5134 ctx->objmask = NULL;
5138 /** Parse tokens for meter policy action commands. */
5140 parse_mp(struct context *ctx, const struct token *token,
5141 const char *str, unsigned int len,
5142 void *buf, unsigned int size)
5144 struct buffer *out = buf;
5146 /* Token name must match. */
5147 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5149 /* Nothing else to do if there is no buffer. */
5152 if (!out->command) {
5153 if (ctx->curr != ITEM_POL_POLICY)
5155 if (sizeof(*out) > size)
5157 out->command = ctx->curr;
5160 ctx->objmask = NULL;
5161 out->args.vc.data = (uint8_t *)out + size;
5164 switch (ctx->curr) {
5166 out->args.vc.actions =
5167 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5169 out->command = ctx->curr;
5172 ctx->objmask = NULL;
5179 /** Parse tokens for validate/create commands. */
5181 parse_vc(struct context *ctx, const struct token *token,
5182 const char *str, unsigned int len,
5183 void *buf, unsigned int size)
5185 struct buffer *out = buf;
5189 /* Token name must match. */
5190 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5192 /* Nothing else to do if there is no buffer. */
5195 if (!out->command) {
5196 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
5198 if (sizeof(*out) > size)
5200 out->command = ctx->curr;
5203 ctx->objmask = NULL;
5204 out->args.vc.data = (uint8_t *)out + size;
5208 switch (ctx->curr) {
5210 ctx->object = &out->args.vc.attr;
5213 case VC_TUNNEL_MATCH:
5214 ctx->object = &out->args.vc.tunnel_ops;
5217 ctx->objmask = NULL;
5218 switch (ctx->curr) {
5223 out->args.vc.tunnel_ops.enabled = 1;
5224 out->args.vc.tunnel_ops.actions = 1;
5226 case VC_TUNNEL_MATCH:
5227 out->args.vc.tunnel_ops.enabled = 1;
5228 out->args.vc.tunnel_ops.items = 1;
5231 out->args.vc.attr.ingress = 1;
5234 out->args.vc.attr.egress = 1;
5237 out->args.vc.attr.transfer = 1;
5240 out->args.vc.pattern =
5241 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5243 ctx->object = out->args.vc.pattern;
5244 ctx->objmask = NULL;
5247 out->args.vc.actions =
5248 (void *)RTE_ALIGN_CEIL((uintptr_t)
5249 (out->args.vc.pattern +
5250 out->args.vc.pattern_n),
5252 ctx->object = out->args.vc.actions;
5253 ctx->objmask = NULL;
5260 if (!out->args.vc.actions) {
5261 const struct parse_item_priv *priv = token->priv;
5262 struct rte_flow_item *item =
5263 out->args.vc.pattern + out->args.vc.pattern_n;
5265 data_size = priv->size * 3; /* spec, last, mask */
5266 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5267 (out->args.vc.data - data_size),
5269 if ((uint8_t *)item + sizeof(*item) > data)
5271 *item = (struct rte_flow_item){
5274 ++out->args.vc.pattern_n;
5276 ctx->objmask = NULL;
5278 const struct parse_action_priv *priv = token->priv;
5279 struct rte_flow_action *action =
5280 out->args.vc.actions + out->args.vc.actions_n;
5282 data_size = priv->size; /* configuration */
5283 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5284 (out->args.vc.data - data_size),
5286 if ((uint8_t *)action + sizeof(*action) > data)
5288 *action = (struct rte_flow_action){
5290 .conf = data_size ? data : NULL,
5292 ++out->args.vc.actions_n;
5293 ctx->object = action;
5294 ctx->objmask = NULL;
5296 memset(data, 0, data_size);
5297 out->args.vc.data = data;
5298 ctx->objdata = data_size;
5302 /** Parse pattern item parameter type. */
5304 parse_vc_spec(struct context *ctx, const struct token *token,
5305 const char *str, unsigned int len,
5306 void *buf, unsigned int size)
5308 struct buffer *out = buf;
5309 struct rte_flow_item *item;
5315 /* Token name must match. */
5316 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5318 /* Parse parameter types. */
5319 switch (ctx->curr) {
5320 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
5326 case ITEM_PARAM_SPEC:
5329 case ITEM_PARAM_LAST:
5332 case ITEM_PARAM_PREFIX:
5333 /* Modify next token to expect a prefix. */
5334 if (ctx->next_num < 2)
5336 ctx->next[ctx->next_num - 2] = prefix;
5338 case ITEM_PARAM_MASK:
5344 /* Nothing else to do if there is no buffer. */
5347 if (!out->args.vc.pattern_n)
5349 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
5350 data_size = ctx->objdata / 3; /* spec, last, mask */
5351 /* Point to selected object. */
5352 ctx->object = out->args.vc.data + (data_size * index);
5354 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
5355 item->mask = ctx->objmask;
5357 ctx->objmask = NULL;
5358 /* Update relevant item pointer. */
5359 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
5364 /** Parse action configuration field. */
5366 parse_vc_conf(struct context *ctx, const struct token *token,
5367 const char *str, unsigned int len,
5368 void *buf, unsigned int size)
5370 struct buffer *out = buf;
5373 /* Token name must match. */
5374 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5376 /* Nothing else to do if there is no buffer. */
5379 /* Point to selected object. */
5380 ctx->object = out->args.vc.data;
5381 ctx->objmask = NULL;
5385 /** Parse eCPRI common header type field. */
5387 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
5388 const char *str, unsigned int len,
5389 void *buf, unsigned int size)
5391 struct rte_flow_item_ecpri *ecpri;
5392 struct rte_flow_item_ecpri *ecpri_mask;
5393 struct rte_flow_item *item;
5396 struct buffer *out = buf;
5397 const struct arg *arg;
5400 /* Token name must match. */
5401 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5403 switch (ctx->curr) {
5404 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
5405 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
5407 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
5408 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
5410 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
5411 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
5418 arg = pop_args(ctx);
5421 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
5422 ecpri->hdr.common.type = msg_type;
5423 data_size = ctx->objdata / 3; /* spec, last, mask */
5424 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
5426 ecpri_mask->hdr.common.type = 0xFF;
5428 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
5429 ecpri_mask->hdr.common.u32 =
5430 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
5432 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
5434 item->mask = ecpri_mask;
5438 /** Parse meter color action type. */
5440 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
5441 const char *str, unsigned int len,
5442 void *buf, unsigned int size)
5444 struct rte_flow_action *action_data;
5445 struct rte_flow_action_meter_color *conf;
5446 enum rte_color color;
5450 /* Token name must match. */
5451 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5453 switch (ctx->curr) {
5454 case ACTION_METER_COLOR_GREEN:
5455 color = RTE_COLOR_GREEN;
5457 case ACTION_METER_COLOR_YELLOW:
5458 color = RTE_COLOR_YELLOW;
5460 case ACTION_METER_COLOR_RED:
5461 color = RTE_COLOR_RED;
5469 action_data = ctx->object;
5470 conf = (struct rte_flow_action_meter_color *)
5471 (uintptr_t)(action_data->conf);
5472 conf->color = color;
5476 /** Parse RSS action. */
5478 parse_vc_action_rss(struct context *ctx, const struct token *token,
5479 const char *str, unsigned int len,
5480 void *buf, unsigned int size)
5482 struct buffer *out = buf;
5483 struct rte_flow_action *action;
5484 struct action_rss_data *action_rss_data;
5488 ret = parse_vc(ctx, token, str, len, buf, size);
5491 /* Nothing else to do if there is no buffer. */
5494 if (!out->args.vc.actions_n)
5496 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5497 /* Point to selected object. */
5498 ctx->object = out->args.vc.data;
5499 ctx->objmask = NULL;
5500 /* Set up default configuration. */
5501 action_rss_data = ctx->object;
5502 *action_rss_data = (struct action_rss_data){
5503 .conf = (struct rte_flow_action_rss){
5504 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
5508 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
5510 .queue = action_rss_data->queue,
5514 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
5515 action_rss_data->queue[i] = i;
5516 action->conf = &action_rss_data->conf;
5521 * Parse func field for RSS action.
5523 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
5524 * ACTION_RSS_FUNC_* index that called this function.
5527 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
5528 const char *str, unsigned int len,
5529 void *buf, unsigned int size)
5531 struct action_rss_data *action_rss_data;
5532 enum rte_eth_hash_function func;
5536 /* Token name must match. */
5537 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5539 switch (ctx->curr) {
5540 case ACTION_RSS_FUNC_DEFAULT:
5541 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
5543 case ACTION_RSS_FUNC_TOEPLITZ:
5544 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
5546 case ACTION_RSS_FUNC_SIMPLE_XOR:
5547 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
5549 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
5550 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
5557 action_rss_data = ctx->object;
5558 action_rss_data->conf.func = func;
5563 * Parse type field for RSS action.
5565 * Valid tokens are type field names and the "end" token.
5568 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
5569 const char *str, unsigned int len,
5570 void *buf, unsigned int size)
5572 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
5573 struct action_rss_data *action_rss_data;
5579 if (ctx->curr != ACTION_RSS_TYPE)
5581 if (!(ctx->objdata >> 16) && ctx->object) {
5582 action_rss_data = ctx->object;
5583 action_rss_data->conf.types = 0;
5585 if (!strcmp_partial("end", str, len)) {
5586 ctx->objdata &= 0xffff;
5589 for (i = 0; rss_type_table[i].str; ++i)
5590 if (!strcmp_partial(rss_type_table[i].str, str, len))
5592 if (!rss_type_table[i].str)
5594 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
5596 if (ctx->next_num == RTE_DIM(ctx->next))
5598 ctx->next[ctx->next_num++] = next;
5601 action_rss_data = ctx->object;
5602 action_rss_data->conf.types |= rss_type_table[i].rss_type;
5607 * Parse queue field for RSS action.
5609 * Valid tokens are queue indices and the "end" token.
5612 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
5613 const char *str, unsigned int len,
5614 void *buf, unsigned int size)
5616 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
5617 struct action_rss_data *action_rss_data;
5618 const struct arg *arg;
5625 if (ctx->curr != ACTION_RSS_QUEUE)
5627 i = ctx->objdata >> 16;
5628 if (!strcmp_partial("end", str, len)) {
5629 ctx->objdata &= 0xffff;
5632 if (i >= ACTION_RSS_QUEUE_NUM)
5634 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
5635 i * sizeof(action_rss_data->queue[i]),
5636 sizeof(action_rss_data->queue[i]));
5637 if (push_args(ctx, arg))
5639 ret = parse_int(ctx, token, str, len, NULL, 0);
5645 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
5647 if (ctx->next_num == RTE_DIM(ctx->next))
5649 ctx->next[ctx->next_num++] = next;
5653 action_rss_data = ctx->object;
5654 action_rss_data->conf.queue_num = i;
5655 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
5659 /** Setup VXLAN encap configuration. */
5661 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
5663 /* Set up default configuration. */
5664 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
5665 .conf = (struct rte_flow_action_vxlan_encap){
5666 .definition = action_vxlan_encap_data->items,
5670 .type = RTE_FLOW_ITEM_TYPE_ETH,
5671 .spec = &action_vxlan_encap_data->item_eth,
5672 .mask = &rte_flow_item_eth_mask,
5675 .type = RTE_FLOW_ITEM_TYPE_VLAN,
5676 .spec = &action_vxlan_encap_data->item_vlan,
5677 .mask = &rte_flow_item_vlan_mask,
5680 .type = RTE_FLOW_ITEM_TYPE_IPV4,
5681 .spec = &action_vxlan_encap_data->item_ipv4,
5682 .mask = &rte_flow_item_ipv4_mask,
5685 .type = RTE_FLOW_ITEM_TYPE_UDP,
5686 .spec = &action_vxlan_encap_data->item_udp,
5687 .mask = &rte_flow_item_udp_mask,
5690 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
5691 .spec = &action_vxlan_encap_data->item_vxlan,
5692 .mask = &rte_flow_item_vxlan_mask,
5695 .type = RTE_FLOW_ITEM_TYPE_END,
5700 .tci = vxlan_encap_conf.vlan_tci,
5704 .src_addr = vxlan_encap_conf.ipv4_src,
5705 .dst_addr = vxlan_encap_conf.ipv4_dst,
5708 .src_port = vxlan_encap_conf.udp_src,
5709 .dst_port = vxlan_encap_conf.udp_dst,
5711 .item_vxlan.flags = 0,
5713 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
5714 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5715 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
5716 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5717 if (!vxlan_encap_conf.select_ipv4) {
5718 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
5719 &vxlan_encap_conf.ipv6_src,
5720 sizeof(vxlan_encap_conf.ipv6_src));
5721 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
5722 &vxlan_encap_conf.ipv6_dst,
5723 sizeof(vxlan_encap_conf.ipv6_dst));
5724 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
5725 .type = RTE_FLOW_ITEM_TYPE_IPV6,
5726 .spec = &action_vxlan_encap_data->item_ipv6,
5727 .mask = &rte_flow_item_ipv6_mask,
5730 if (!vxlan_encap_conf.select_vlan)
5731 action_vxlan_encap_data->items[1].type =
5732 RTE_FLOW_ITEM_TYPE_VOID;
5733 if (vxlan_encap_conf.select_tos_ttl) {
5734 if (vxlan_encap_conf.select_ipv4) {
5735 static struct rte_flow_item_ipv4 ipv4_mask_tos;
5737 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
5738 sizeof(ipv4_mask_tos));
5739 ipv4_mask_tos.hdr.type_of_service = 0xff;
5740 ipv4_mask_tos.hdr.time_to_live = 0xff;
5741 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
5742 vxlan_encap_conf.ip_tos;
5743 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
5744 vxlan_encap_conf.ip_ttl;
5745 action_vxlan_encap_data->items[2].mask =
5748 static struct rte_flow_item_ipv6 ipv6_mask_tos;
5750 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
5751 sizeof(ipv6_mask_tos));
5752 ipv6_mask_tos.hdr.vtc_flow |=
5753 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
5754 ipv6_mask_tos.hdr.hop_limits = 0xff;
5755 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
5757 ((uint32_t)vxlan_encap_conf.ip_tos <<
5758 RTE_IPV6_HDR_TC_SHIFT);
5759 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
5760 vxlan_encap_conf.ip_ttl;
5761 action_vxlan_encap_data->items[2].mask =
5765 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
5766 RTE_DIM(vxlan_encap_conf.vni));
5770 /** Parse VXLAN encap action. */
5772 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
5773 const char *str, unsigned int len,
5774 void *buf, unsigned int size)
5776 struct buffer *out = buf;
5777 struct rte_flow_action *action;
5778 struct action_vxlan_encap_data *action_vxlan_encap_data;
5781 ret = parse_vc(ctx, token, str, len, buf, size);
5784 /* Nothing else to do if there is no buffer. */
5787 if (!out->args.vc.actions_n)
5789 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5790 /* Point to selected object. */
5791 ctx->object = out->args.vc.data;
5792 ctx->objmask = NULL;
5793 action_vxlan_encap_data = ctx->object;
5794 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
5795 action->conf = &action_vxlan_encap_data->conf;
5799 /** Setup NVGRE encap configuration. */
5801 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
5803 /* Set up default configuration. */
5804 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
5805 .conf = (struct rte_flow_action_nvgre_encap){
5806 .definition = action_nvgre_encap_data->items,
5810 .type = RTE_FLOW_ITEM_TYPE_ETH,
5811 .spec = &action_nvgre_encap_data->item_eth,
5812 .mask = &rte_flow_item_eth_mask,
5815 .type = RTE_FLOW_ITEM_TYPE_VLAN,
5816 .spec = &action_nvgre_encap_data->item_vlan,
5817 .mask = &rte_flow_item_vlan_mask,
5820 .type = RTE_FLOW_ITEM_TYPE_IPV4,
5821 .spec = &action_nvgre_encap_data->item_ipv4,
5822 .mask = &rte_flow_item_ipv4_mask,
5825 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
5826 .spec = &action_nvgre_encap_data->item_nvgre,
5827 .mask = &rte_flow_item_nvgre_mask,
5830 .type = RTE_FLOW_ITEM_TYPE_END,
5835 .tci = nvgre_encap_conf.vlan_tci,
5839 .src_addr = nvgre_encap_conf.ipv4_src,
5840 .dst_addr = nvgre_encap_conf.ipv4_dst,
5842 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
5843 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
5844 .item_nvgre.flow_id = 0,
5846 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
5847 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5848 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
5849 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5850 if (!nvgre_encap_conf.select_ipv4) {
5851 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
5852 &nvgre_encap_conf.ipv6_src,
5853 sizeof(nvgre_encap_conf.ipv6_src));
5854 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
5855 &nvgre_encap_conf.ipv6_dst,
5856 sizeof(nvgre_encap_conf.ipv6_dst));
5857 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
5858 .type = RTE_FLOW_ITEM_TYPE_IPV6,
5859 .spec = &action_nvgre_encap_data->item_ipv6,
5860 .mask = &rte_flow_item_ipv6_mask,
5863 if (!nvgre_encap_conf.select_vlan)
5864 action_nvgre_encap_data->items[1].type =
5865 RTE_FLOW_ITEM_TYPE_VOID;
5866 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
5867 RTE_DIM(nvgre_encap_conf.tni));
5871 /** Parse NVGRE encap action. */
5873 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
5874 const char *str, unsigned int len,
5875 void *buf, unsigned int size)
5877 struct buffer *out = buf;
5878 struct rte_flow_action *action;
5879 struct action_nvgre_encap_data *action_nvgre_encap_data;
5882 ret = parse_vc(ctx, token, str, len, buf, size);
5885 /* Nothing else to do if there is no buffer. */
5888 if (!out->args.vc.actions_n)
5890 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5891 /* Point to selected object. */
5892 ctx->object = out->args.vc.data;
5893 ctx->objmask = NULL;
5894 action_nvgre_encap_data = ctx->object;
5895 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
5896 action->conf = &action_nvgre_encap_data->conf;
5900 /** Parse l2 encap action. */
5902 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
5903 const char *str, unsigned int len,
5904 void *buf, unsigned int size)
5906 struct buffer *out = buf;
5907 struct rte_flow_action *action;
5908 struct action_raw_encap_data *action_encap_data;
5909 struct rte_flow_item_eth eth = { .type = 0, };
5910 struct rte_flow_item_vlan vlan = {
5911 .tci = mplsoudp_encap_conf.vlan_tci,
5917 ret = parse_vc(ctx, token, str, len, buf, size);
5920 /* Nothing else to do if there is no buffer. */
5923 if (!out->args.vc.actions_n)
5925 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5926 /* Point to selected object. */
5927 ctx->object = out->args.vc.data;
5928 ctx->objmask = NULL;
5929 /* Copy the headers to the buffer. */
5930 action_encap_data = ctx->object;
5931 *action_encap_data = (struct action_raw_encap_data) {
5932 .conf = (struct rte_flow_action_raw_encap){
5933 .data = action_encap_data->data,
5937 header = action_encap_data->data;
5938 if (l2_encap_conf.select_vlan)
5939 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5940 else if (l2_encap_conf.select_ipv4)
5941 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5943 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5944 memcpy(eth.dst.addr_bytes,
5945 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5946 memcpy(eth.src.addr_bytes,
5947 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5948 memcpy(header, ð, sizeof(eth));
5949 header += sizeof(eth);
5950 if (l2_encap_conf.select_vlan) {
5951 if (l2_encap_conf.select_ipv4)
5952 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5954 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5955 memcpy(header, &vlan, sizeof(vlan));
5956 header += sizeof(vlan);
5958 action_encap_data->conf.size = header -
5959 action_encap_data->data;
5960 action->conf = &action_encap_data->conf;
5964 /** Parse l2 decap action. */
5966 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
5967 const char *str, unsigned int len,
5968 void *buf, unsigned int size)
5970 struct buffer *out = buf;
5971 struct rte_flow_action *action;
5972 struct action_raw_decap_data *action_decap_data;
5973 struct rte_flow_item_eth eth = { .type = 0, };
5974 struct rte_flow_item_vlan vlan = {
5975 .tci = mplsoudp_encap_conf.vlan_tci,
5981 ret = parse_vc(ctx, token, str, len, buf, size);
5984 /* Nothing else to do if there is no buffer. */
5987 if (!out->args.vc.actions_n)
5989 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5990 /* Point to selected object. */
5991 ctx->object = out->args.vc.data;
5992 ctx->objmask = NULL;
5993 /* Copy the headers to the buffer. */
5994 action_decap_data = ctx->object;
5995 *action_decap_data = (struct action_raw_decap_data) {
5996 .conf = (struct rte_flow_action_raw_decap){
5997 .data = action_decap_data->data,
6001 header = action_decap_data->data;
6002 if (l2_decap_conf.select_vlan)
6003 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6004 memcpy(header, ð, sizeof(eth));
6005 header += sizeof(eth);
6006 if (l2_decap_conf.select_vlan) {
6007 memcpy(header, &vlan, sizeof(vlan));
6008 header += sizeof(vlan);
6010 action_decap_data->conf.size = header -
6011 action_decap_data->data;
6012 action->conf = &action_decap_data->conf;
6016 #define ETHER_TYPE_MPLS_UNICAST 0x8847
6018 /** Parse MPLSOGRE encap action. */
6020 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
6021 const char *str, unsigned int len,
6022 void *buf, unsigned int size)
6024 struct buffer *out = buf;
6025 struct rte_flow_action *action;
6026 struct action_raw_encap_data *action_encap_data;
6027 struct rte_flow_item_eth eth = { .type = 0, };
6028 struct rte_flow_item_vlan vlan = {
6029 .tci = mplsogre_encap_conf.vlan_tci,
6032 struct rte_flow_item_ipv4 ipv4 = {
6034 .src_addr = mplsogre_encap_conf.ipv4_src,
6035 .dst_addr = mplsogre_encap_conf.ipv4_dst,
6036 .next_proto_id = IPPROTO_GRE,
6037 .version_ihl = RTE_IPV4_VHL_DEF,
6038 .time_to_live = IPDEFTTL,
6041 struct rte_flow_item_ipv6 ipv6 = {
6043 .proto = IPPROTO_GRE,
6044 .hop_limits = IPDEFTTL,
6047 struct rte_flow_item_gre gre = {
6048 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6050 struct rte_flow_item_mpls mpls = {
6056 ret = parse_vc(ctx, token, str, len, buf, size);
6059 /* Nothing else to do if there is no buffer. */
6062 if (!out->args.vc.actions_n)
6064 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6065 /* Point to selected object. */
6066 ctx->object = out->args.vc.data;
6067 ctx->objmask = NULL;
6068 /* Copy the headers to the buffer. */
6069 action_encap_data = ctx->object;
6070 *action_encap_data = (struct action_raw_encap_data) {
6071 .conf = (struct rte_flow_action_raw_encap){
6072 .data = action_encap_data->data,
6077 header = action_encap_data->data;
6078 if (mplsogre_encap_conf.select_vlan)
6079 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6080 else if (mplsogre_encap_conf.select_ipv4)
6081 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6083 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6084 memcpy(eth.dst.addr_bytes,
6085 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6086 memcpy(eth.src.addr_bytes,
6087 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6088 memcpy(header, ð, sizeof(eth));
6089 header += sizeof(eth);
6090 if (mplsogre_encap_conf.select_vlan) {
6091 if (mplsogre_encap_conf.select_ipv4)
6092 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6094 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6095 memcpy(header, &vlan, sizeof(vlan));
6096 header += sizeof(vlan);
6098 if (mplsogre_encap_conf.select_ipv4) {
6099 memcpy(header, &ipv4, sizeof(ipv4));
6100 header += sizeof(ipv4);
6102 memcpy(&ipv6.hdr.src_addr,
6103 &mplsogre_encap_conf.ipv6_src,
6104 sizeof(mplsogre_encap_conf.ipv6_src));
6105 memcpy(&ipv6.hdr.dst_addr,
6106 &mplsogre_encap_conf.ipv6_dst,
6107 sizeof(mplsogre_encap_conf.ipv6_dst));
6108 memcpy(header, &ipv6, sizeof(ipv6));
6109 header += sizeof(ipv6);
6111 memcpy(header, &gre, sizeof(gre));
6112 header += sizeof(gre);
6113 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
6114 RTE_DIM(mplsogre_encap_conf.label));
6115 mpls.label_tc_s[2] |= 0x1;
6116 memcpy(header, &mpls, sizeof(mpls));
6117 header += sizeof(mpls);
6118 action_encap_data->conf.size = header -
6119 action_encap_data->data;
6120 action->conf = &action_encap_data->conf;
6124 /** Parse MPLSOGRE decap action. */
6126 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
6127 const char *str, unsigned int len,
6128 void *buf, unsigned int size)
6130 struct buffer *out = buf;
6131 struct rte_flow_action *action;
6132 struct action_raw_decap_data *action_decap_data;
6133 struct rte_flow_item_eth eth = { .type = 0, };
6134 struct rte_flow_item_vlan vlan = {.tci = 0};
6135 struct rte_flow_item_ipv4 ipv4 = {
6137 .next_proto_id = IPPROTO_GRE,
6140 struct rte_flow_item_ipv6 ipv6 = {
6142 .proto = IPPROTO_GRE,
6145 struct rte_flow_item_gre gre = {
6146 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6148 struct rte_flow_item_mpls mpls;
6152 ret = parse_vc(ctx, token, str, len, buf, size);
6155 /* Nothing else to do if there is no buffer. */
6158 if (!out->args.vc.actions_n)
6160 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6161 /* Point to selected object. */
6162 ctx->object = out->args.vc.data;
6163 ctx->objmask = NULL;
6164 /* Copy the headers to the buffer. */
6165 action_decap_data = ctx->object;
6166 *action_decap_data = (struct action_raw_decap_data) {
6167 .conf = (struct rte_flow_action_raw_decap){
6168 .data = action_decap_data->data,
6172 header = action_decap_data->data;
6173 if (mplsogre_decap_conf.select_vlan)
6174 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6175 else if (mplsogre_encap_conf.select_ipv4)
6176 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6178 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6179 memcpy(eth.dst.addr_bytes,
6180 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6181 memcpy(eth.src.addr_bytes,
6182 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6183 memcpy(header, ð, sizeof(eth));
6184 header += sizeof(eth);
6185 if (mplsogre_encap_conf.select_vlan) {
6186 if (mplsogre_encap_conf.select_ipv4)
6187 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6189 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6190 memcpy(header, &vlan, sizeof(vlan));
6191 header += sizeof(vlan);
6193 if (mplsogre_encap_conf.select_ipv4) {
6194 memcpy(header, &ipv4, sizeof(ipv4));
6195 header += sizeof(ipv4);
6197 memcpy(header, &ipv6, sizeof(ipv6));
6198 header += sizeof(ipv6);
6200 memcpy(header, &gre, sizeof(gre));
6201 header += sizeof(gre);
6202 memset(&mpls, 0, sizeof(mpls));
6203 memcpy(header, &mpls, sizeof(mpls));
6204 header += sizeof(mpls);
6205 action_decap_data->conf.size = header -
6206 action_decap_data->data;
6207 action->conf = &action_decap_data->conf;
6211 /** Parse MPLSOUDP encap action. */
6213 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
6214 const char *str, unsigned int len,
6215 void *buf, unsigned int size)
6217 struct buffer *out = buf;
6218 struct rte_flow_action *action;
6219 struct action_raw_encap_data *action_encap_data;
6220 struct rte_flow_item_eth eth = { .type = 0, };
6221 struct rte_flow_item_vlan vlan = {
6222 .tci = mplsoudp_encap_conf.vlan_tci,
6225 struct rte_flow_item_ipv4 ipv4 = {
6227 .src_addr = mplsoudp_encap_conf.ipv4_src,
6228 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
6229 .next_proto_id = IPPROTO_UDP,
6230 .version_ihl = RTE_IPV4_VHL_DEF,
6231 .time_to_live = IPDEFTTL,
6234 struct rte_flow_item_ipv6 ipv6 = {
6236 .proto = IPPROTO_UDP,
6237 .hop_limits = IPDEFTTL,
6240 struct rte_flow_item_udp udp = {
6242 .src_port = mplsoudp_encap_conf.udp_src,
6243 .dst_port = mplsoudp_encap_conf.udp_dst,
6246 struct rte_flow_item_mpls mpls;
6250 ret = parse_vc(ctx, token, str, len, buf, size);
6253 /* Nothing else to do if there is no buffer. */
6256 if (!out->args.vc.actions_n)
6258 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6259 /* Point to selected object. */
6260 ctx->object = out->args.vc.data;
6261 ctx->objmask = NULL;
6262 /* Copy the headers to the buffer. */
6263 action_encap_data = ctx->object;
6264 *action_encap_data = (struct action_raw_encap_data) {
6265 .conf = (struct rte_flow_action_raw_encap){
6266 .data = action_encap_data->data,
6271 header = action_encap_data->data;
6272 if (mplsoudp_encap_conf.select_vlan)
6273 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6274 else if (mplsoudp_encap_conf.select_ipv4)
6275 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6277 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6278 memcpy(eth.dst.addr_bytes,
6279 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6280 memcpy(eth.src.addr_bytes,
6281 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6282 memcpy(header, ð, sizeof(eth));
6283 header += sizeof(eth);
6284 if (mplsoudp_encap_conf.select_vlan) {
6285 if (mplsoudp_encap_conf.select_ipv4)
6286 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6288 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6289 memcpy(header, &vlan, sizeof(vlan));
6290 header += sizeof(vlan);
6292 if (mplsoudp_encap_conf.select_ipv4) {
6293 memcpy(header, &ipv4, sizeof(ipv4));
6294 header += sizeof(ipv4);
6296 memcpy(&ipv6.hdr.src_addr,
6297 &mplsoudp_encap_conf.ipv6_src,
6298 sizeof(mplsoudp_encap_conf.ipv6_src));
6299 memcpy(&ipv6.hdr.dst_addr,
6300 &mplsoudp_encap_conf.ipv6_dst,
6301 sizeof(mplsoudp_encap_conf.ipv6_dst));
6302 memcpy(header, &ipv6, sizeof(ipv6));
6303 header += sizeof(ipv6);
6305 memcpy(header, &udp, sizeof(udp));
6306 header += sizeof(udp);
6307 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
6308 RTE_DIM(mplsoudp_encap_conf.label));
6309 mpls.label_tc_s[2] |= 0x1;
6310 memcpy(header, &mpls, sizeof(mpls));
6311 header += sizeof(mpls);
6312 action_encap_data->conf.size = header -
6313 action_encap_data->data;
6314 action->conf = &action_encap_data->conf;
6318 /** Parse MPLSOUDP decap action. */
6320 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
6321 const char *str, unsigned int len,
6322 void *buf, unsigned int size)
6324 struct buffer *out = buf;
6325 struct rte_flow_action *action;
6326 struct action_raw_decap_data *action_decap_data;
6327 struct rte_flow_item_eth eth = { .type = 0, };
6328 struct rte_flow_item_vlan vlan = {.tci = 0};
6329 struct rte_flow_item_ipv4 ipv4 = {
6331 .next_proto_id = IPPROTO_UDP,
6334 struct rte_flow_item_ipv6 ipv6 = {
6336 .proto = IPPROTO_UDP,
6339 struct rte_flow_item_udp udp = {
6341 .dst_port = rte_cpu_to_be_16(6635),
6344 struct rte_flow_item_mpls mpls;
6348 ret = parse_vc(ctx, token, str, len, buf, size);
6351 /* Nothing else to do if there is no buffer. */
6354 if (!out->args.vc.actions_n)
6356 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6357 /* Point to selected object. */
6358 ctx->object = out->args.vc.data;
6359 ctx->objmask = NULL;
6360 /* Copy the headers to the buffer. */
6361 action_decap_data = ctx->object;
6362 *action_decap_data = (struct action_raw_decap_data) {
6363 .conf = (struct rte_flow_action_raw_decap){
6364 .data = action_decap_data->data,
6368 header = action_decap_data->data;
6369 if (mplsoudp_decap_conf.select_vlan)
6370 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6371 else if (mplsoudp_encap_conf.select_ipv4)
6372 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6374 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6375 memcpy(eth.dst.addr_bytes,
6376 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6377 memcpy(eth.src.addr_bytes,
6378 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6379 memcpy(header, ð, sizeof(eth));
6380 header += sizeof(eth);
6381 if (mplsoudp_encap_conf.select_vlan) {
6382 if (mplsoudp_encap_conf.select_ipv4)
6383 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6385 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6386 memcpy(header, &vlan, sizeof(vlan));
6387 header += sizeof(vlan);
6389 if (mplsoudp_encap_conf.select_ipv4) {
6390 memcpy(header, &ipv4, sizeof(ipv4));
6391 header += sizeof(ipv4);
6393 memcpy(header, &ipv6, sizeof(ipv6));
6394 header += sizeof(ipv6);
6396 memcpy(header, &udp, sizeof(udp));
6397 header += sizeof(udp);
6398 memset(&mpls, 0, sizeof(mpls));
6399 memcpy(header, &mpls, sizeof(mpls));
6400 header += sizeof(mpls);
6401 action_decap_data->conf.size = header -
6402 action_decap_data->data;
6403 action->conf = &action_decap_data->conf;
6408 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
6409 const char *str, unsigned int len, void *buf,
6412 struct action_raw_decap_data *action_raw_decap_data;
6413 struct rte_flow_action *action;
6414 const struct arg *arg;
6415 struct buffer *out = buf;
6419 RTE_SET_USED(token);
6422 arg = ARGS_ENTRY_ARB_BOUNDED
6423 (offsetof(struct action_raw_decap_data, idx),
6424 sizeof(((struct action_raw_decap_data *)0)->idx),
6425 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
6426 if (push_args(ctx, arg))
6428 ret = parse_int(ctx, token, str, len, NULL, 0);
6435 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6436 action_raw_decap_data = ctx->object;
6437 idx = action_raw_decap_data->idx;
6438 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
6439 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
6440 action->conf = &action_raw_decap_data->conf;
6446 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
6447 const char *str, unsigned int len, void *buf,
6450 struct action_raw_encap_data *action_raw_encap_data;
6451 struct rte_flow_action *action;
6452 const struct arg *arg;
6453 struct buffer *out = buf;
6457 RTE_SET_USED(token);
6460 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
6462 arg = ARGS_ENTRY_ARB_BOUNDED
6463 (offsetof(struct action_raw_encap_data, idx),
6464 sizeof(((struct action_raw_encap_data *)0)->idx),
6465 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
6466 if (push_args(ctx, arg))
6468 ret = parse_int(ctx, token, str, len, NULL, 0);
6475 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6476 action_raw_encap_data = ctx->object;
6477 idx = action_raw_encap_data->idx;
6478 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
6479 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
6480 action_raw_encap_data->conf.preserve = NULL;
6481 action->conf = &action_raw_encap_data->conf;
6486 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
6487 const char *str, unsigned int len, void *buf,
6490 struct buffer *out = buf;
6491 struct rte_flow_action *action;
6492 struct action_raw_encap_data *action_raw_encap_data = NULL;
6495 ret = parse_vc(ctx, token, str, len, buf, size);
6498 /* Nothing else to do if there is no buffer. */
6501 if (!out->args.vc.actions_n)
6503 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6504 /* Point to selected object. */
6505 ctx->object = out->args.vc.data;
6506 ctx->objmask = NULL;
6507 /* Copy the headers to the buffer. */
6508 action_raw_encap_data = ctx->object;
6509 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
6510 action_raw_encap_data->conf.preserve = NULL;
6511 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
6512 action->conf = &action_raw_encap_data->conf;
6517 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
6518 const char *str, unsigned int len, void *buf,
6521 struct buffer *out = buf;
6522 struct rte_flow_action *action;
6523 struct action_raw_decap_data *action_raw_decap_data = NULL;
6526 ret = parse_vc(ctx, token, str, len, buf, size);
6529 /* Nothing else to do if there is no buffer. */
6532 if (!out->args.vc.actions_n)
6534 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6535 /* Point to selected object. */
6536 ctx->object = out->args.vc.data;
6537 ctx->objmask = NULL;
6538 /* Copy the headers to the buffer. */
6539 action_raw_decap_data = ctx->object;
6540 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
6541 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
6542 action->conf = &action_raw_decap_data->conf;
6547 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
6548 const char *str, unsigned int len, void *buf,
6553 ret = parse_vc(ctx, token, str, len, buf, size);
6556 ret = rte_flow_dynf_metadata_register();
6563 parse_vc_action_sample(struct context *ctx, const struct token *token,
6564 const char *str, unsigned int len, void *buf,
6567 struct buffer *out = buf;
6568 struct rte_flow_action *action;
6569 struct action_sample_data *action_sample_data = NULL;
6570 static struct rte_flow_action end_action = {
6571 RTE_FLOW_ACTION_TYPE_END, 0
6575 ret = parse_vc(ctx, token, str, len, buf, size);
6578 /* Nothing else to do if there is no buffer. */
6581 if (!out->args.vc.actions_n)
6583 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6584 /* Point to selected object. */
6585 ctx->object = out->args.vc.data;
6586 ctx->objmask = NULL;
6587 /* Copy the headers to the buffer. */
6588 action_sample_data = ctx->object;
6589 action_sample_data->conf.actions = &end_action;
6590 action->conf = &action_sample_data->conf;
6595 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
6596 const char *str, unsigned int len, void *buf,
6599 struct action_sample_data *action_sample_data;
6600 struct rte_flow_action *action;
6601 const struct arg *arg;
6602 struct buffer *out = buf;
6606 RTE_SET_USED(token);
6609 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
6611 arg = ARGS_ENTRY_ARB_BOUNDED
6612 (offsetof(struct action_sample_data, idx),
6613 sizeof(((struct action_sample_data *)0)->idx),
6614 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
6615 if (push_args(ctx, arg))
6617 ret = parse_int(ctx, token, str, len, NULL, 0);
6624 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6625 action_sample_data = ctx->object;
6626 idx = action_sample_data->idx;
6627 action_sample_data->conf.actions = raw_sample_confs[idx].data;
6628 action->conf = &action_sample_data->conf;
6632 /** Parse operation for modify_field command. */
6634 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
6635 const char *str, unsigned int len, void *buf,
6638 struct rte_flow_action_modify_field *action_modify_field;
6644 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
6646 for (i = 0; modify_field_ops[i]; ++i)
6647 if (!strcmp_partial(modify_field_ops[i], str, len))
6649 if (!modify_field_ops[i])
6653 action_modify_field = ctx->object;
6654 action_modify_field->operation = (enum rte_flow_modify_op)i;
6658 /** Parse id for modify_field command. */
6660 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
6661 const char *str, unsigned int len, void *buf,
6664 struct rte_flow_action_modify_field *action_modify_field;
6670 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
6671 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
6673 for (i = 0; modify_field_ids[i]; ++i)
6674 if (!strcmp_partial(modify_field_ids[i], str, len))
6676 if (!modify_field_ids[i])
6680 action_modify_field = ctx->object;
6681 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
6682 action_modify_field->dst.field = (enum rte_flow_field_id)i;
6684 action_modify_field->src.field = (enum rte_flow_field_id)i;
6688 /** Parse the conntrack update, not a rte_flow_action. */
6690 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
6691 const char *str, unsigned int len, void *buf,
6694 struct buffer *out = buf;
6695 struct rte_flow_modify_conntrack *ct_modify = NULL;
6698 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
6699 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
6701 /* Token name must match. */
6702 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6704 /* Nothing else to do if there is no buffer. */
6707 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
6708 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
6709 ct_modify->new_ct.is_original_dir =
6710 conntrack_context.is_original_dir;
6711 ct_modify->direction = 1;
6715 old_dir = ct_modify->new_ct.is_original_dir;
6716 memcpy(&ct_modify->new_ct, &conntrack_context,
6717 sizeof(conntrack_context));
6718 ct_modify->new_ct.is_original_dir = old_dir;
6719 ct_modify->state = 1;
6724 /** Parse tokens for destroy command. */
6726 parse_destroy(struct context *ctx, const struct token *token,
6727 const char *str, unsigned int len,
6728 void *buf, unsigned int size)
6730 struct buffer *out = buf;
6732 /* Token name must match. */
6733 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6735 /* Nothing else to do if there is no buffer. */
6738 if (!out->command) {
6739 if (ctx->curr != DESTROY)
6741 if (sizeof(*out) > size)
6743 out->command = ctx->curr;
6746 ctx->objmask = NULL;
6747 out->args.destroy.rule =
6748 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6752 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
6753 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
6756 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
6757 ctx->objmask = NULL;
6761 /** Parse tokens for flush command. */
6763 parse_flush(struct context *ctx, const struct token *token,
6764 const char *str, unsigned int len,
6765 void *buf, unsigned int size)
6767 struct buffer *out = buf;
6769 /* Token name must match. */
6770 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6772 /* Nothing else to do if there is no buffer. */
6775 if (!out->command) {
6776 if (ctx->curr != FLUSH)
6778 if (sizeof(*out) > size)
6780 out->command = ctx->curr;
6783 ctx->objmask = NULL;
6788 /** Parse tokens for dump command. */
6790 parse_dump(struct context *ctx, const struct token *token,
6791 const char *str, unsigned int len,
6792 void *buf, unsigned int size)
6794 struct buffer *out = buf;
6796 /* Token name must match. */
6797 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6799 /* Nothing else to do if there is no buffer. */
6802 if (!out->command) {
6803 if (ctx->curr != DUMP)
6805 if (sizeof(*out) > size)
6807 out->command = ctx->curr;
6810 ctx->objmask = NULL;
6813 switch (ctx->curr) {
6816 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
6817 out->command = ctx->curr;
6820 ctx->objmask = NULL;
6827 /** Parse tokens for query command. */
6829 parse_query(struct context *ctx, const struct token *token,
6830 const char *str, unsigned int len,
6831 void *buf, unsigned int size)
6833 struct buffer *out = buf;
6835 /* Token name must match. */
6836 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6838 /* Nothing else to do if there is no buffer. */
6841 if (!out->command) {
6842 if (ctx->curr != QUERY)
6844 if (sizeof(*out) > size)
6846 out->command = ctx->curr;
6849 ctx->objmask = NULL;
6854 /** Parse action names. */
6856 parse_action(struct context *ctx, const struct token *token,
6857 const char *str, unsigned int len,
6858 void *buf, unsigned int size)
6860 struct buffer *out = buf;
6861 const struct arg *arg = pop_args(ctx);
6865 /* Argument is expected. */
6868 /* Parse action name. */
6869 for (i = 0; next_action[i]; ++i) {
6870 const struct parse_action_priv *priv;
6872 token = &token_list[next_action[i]];
6873 if (strcmp_partial(token->name, str, len))
6879 memcpy((uint8_t *)ctx->object + arg->offset,
6885 push_args(ctx, arg);
6889 /** Parse tokens for list command. */
6891 parse_list(struct context *ctx, const struct token *token,
6892 const char *str, unsigned int len,
6893 void *buf, unsigned int size)
6895 struct buffer *out = buf;
6897 /* Token name must match. */
6898 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6900 /* Nothing else to do if there is no buffer. */
6903 if (!out->command) {
6904 if (ctx->curr != LIST)
6906 if (sizeof(*out) > size)
6908 out->command = ctx->curr;
6911 ctx->objmask = NULL;
6912 out->args.list.group =
6913 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6917 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
6918 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
6921 ctx->object = out->args.list.group + out->args.list.group_n++;
6922 ctx->objmask = NULL;
6926 /** Parse tokens for list all aged flows command. */
6928 parse_aged(struct context *ctx, const struct token *token,
6929 const char *str, unsigned int len,
6930 void *buf, unsigned int size)
6932 struct buffer *out = buf;
6934 /* Token name must match. */
6935 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6937 /* Nothing else to do if there is no buffer. */
6940 if (!out->command) {
6941 if (ctx->curr != AGED)
6943 if (sizeof(*out) > size)
6945 out->command = ctx->curr;
6948 ctx->objmask = NULL;
6950 if (ctx->curr == AGED_DESTROY)
6951 out->args.aged.destroy = 1;
6955 /** Parse tokens for isolate command. */
6957 parse_isolate(struct context *ctx, const struct token *token,
6958 const char *str, unsigned int len,
6959 void *buf, unsigned int size)
6961 struct buffer *out = buf;
6963 /* Token name must match. */
6964 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6966 /* Nothing else to do if there is no buffer. */
6969 if (!out->command) {
6970 if (ctx->curr != ISOLATE)
6972 if (sizeof(*out) > size)
6974 out->command = ctx->curr;
6977 ctx->objmask = NULL;
6983 parse_tunnel(struct context *ctx, const struct token *token,
6984 const char *str, unsigned int len,
6985 void *buf, unsigned int size)
6987 struct buffer *out = buf;
6989 /* Token name must match. */
6990 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6992 /* Nothing else to do if there is no buffer. */
6995 if (!out->command) {
6996 if (ctx->curr != TUNNEL)
6998 if (sizeof(*out) > size)
7000 out->command = ctx->curr;
7003 ctx->objmask = NULL;
7005 switch (ctx->curr) {
7009 case TUNNEL_DESTROY:
7011 out->command = ctx->curr;
7013 case TUNNEL_CREATE_TYPE:
7014 case TUNNEL_DESTROY_ID:
7015 ctx->object = &out->args.vc.tunnel_ops;
7024 * Parse signed/unsigned integers 8 to 64-bit long.
7026 * Last argument (ctx->args) is retrieved to determine integer type and
7030 parse_int(struct context *ctx, const struct token *token,
7031 const char *str, unsigned int len,
7032 void *buf, unsigned int size)
7034 const struct arg *arg = pop_args(ctx);
7039 /* Argument is expected. */
7044 (uintmax_t)strtoimax(str, &end, 0) :
7045 strtoumax(str, &end, 0);
7046 if (errno || (size_t)(end - str) != len)
7049 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
7050 (intmax_t)u > (intmax_t)arg->max)) ||
7051 (!arg->sign && (u < arg->min || u > arg->max))))
7056 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
7057 !arg_entry_bf_fill(ctx->objmask, -1, arg))
7061 buf = (uint8_t *)ctx->object + arg->offset;
7063 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
7067 case sizeof(uint8_t):
7068 *(uint8_t *)buf = u;
7070 case sizeof(uint16_t):
7071 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
7073 case sizeof(uint8_t [3]):
7074 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7076 ((uint8_t *)buf)[0] = u;
7077 ((uint8_t *)buf)[1] = u >> 8;
7078 ((uint8_t *)buf)[2] = u >> 16;
7082 ((uint8_t *)buf)[0] = u >> 16;
7083 ((uint8_t *)buf)[1] = u >> 8;
7084 ((uint8_t *)buf)[2] = u;
7086 case sizeof(uint32_t):
7087 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
7089 case sizeof(uint64_t):
7090 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
7095 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
7097 buf = (uint8_t *)ctx->objmask + arg->offset;
7102 push_args(ctx, arg);
7109 * Three arguments (ctx->args) are retrieved from the stack to store data,
7110 * its actual length and address (in that order).
7113 parse_string(struct context *ctx, const struct token *token,
7114 const char *str, unsigned int len,
7115 void *buf, unsigned int size)
7117 const struct arg *arg_data = pop_args(ctx);
7118 const struct arg *arg_len = pop_args(ctx);
7119 const struct arg *arg_addr = pop_args(ctx);
7120 char tmp[16]; /* Ought to be enough. */
7123 /* Arguments are expected. */
7127 push_args(ctx, arg_data);
7131 push_args(ctx, arg_len);
7132 push_args(ctx, arg_data);
7135 size = arg_data->size;
7136 /* Bit-mask fill is not supported. */
7137 if (arg_data->mask || size < len)
7141 /* Let parse_int() fill length information first. */
7142 ret = snprintf(tmp, sizeof(tmp), "%u", len);
7145 push_args(ctx, arg_len);
7146 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7151 buf = (uint8_t *)ctx->object + arg_data->offset;
7152 /* Output buffer is not necessarily NUL-terminated. */
7153 memcpy(buf, str, len);
7154 memset((uint8_t *)buf + len, 0x00, size - len);
7156 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7157 /* Save address if requested. */
7158 if (arg_addr->size) {
7159 memcpy((uint8_t *)ctx->object + arg_addr->offset,
7161 (uint8_t *)ctx->object + arg_data->offset
7165 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7167 (uint8_t *)ctx->objmask + arg_data->offset
7173 push_args(ctx, arg_addr);
7174 push_args(ctx, arg_len);
7175 push_args(ctx, arg_data);
7180 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
7186 /* Check input parameters */
7187 if ((src == NULL) ||
7193 /* Convert chars to bytes */
7194 for (i = 0, len = 0; i < *size; i += 2) {
7195 snprintf(tmp, 3, "%s", src + i);
7196 dst[len++] = strtoul(tmp, &c, 16);
7211 parse_hex(struct context *ctx, const struct token *token,
7212 const char *str, unsigned int len,
7213 void *buf, unsigned int size)
7215 const struct arg *arg_data = pop_args(ctx);
7216 const struct arg *arg_len = pop_args(ctx);
7217 const struct arg *arg_addr = pop_args(ctx);
7218 char tmp[16]; /* Ought to be enough. */
7220 unsigned int hexlen = len;
7221 unsigned int length = 256;
7222 uint8_t hex_tmp[length];
7224 /* Arguments are expected. */
7228 push_args(ctx, arg_data);
7232 push_args(ctx, arg_len);
7233 push_args(ctx, arg_data);
7236 size = arg_data->size;
7237 /* Bit-mask fill is not supported. */
7243 /* translate bytes string to array. */
7244 if (str[0] == '0' && ((str[1] == 'x') ||
7249 if (hexlen > length)
7251 ret = parse_hex_string(str, hex_tmp, &hexlen);
7254 /* Let parse_int() fill length information first. */
7255 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
7258 /* Save length if requested. */
7259 if (arg_len->size) {
7260 push_args(ctx, arg_len);
7261 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7267 buf = (uint8_t *)ctx->object + arg_data->offset;
7268 /* Output buffer is not necessarily NUL-terminated. */
7269 memcpy(buf, hex_tmp, hexlen);
7270 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
7272 memset((uint8_t *)ctx->objmask + arg_data->offset,
7274 /* Save address if requested. */
7275 if (arg_addr->size) {
7276 memcpy((uint8_t *)ctx->object + arg_addr->offset,
7278 (uint8_t *)ctx->object + arg_data->offset
7282 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7284 (uint8_t *)ctx->objmask + arg_data->offset
7290 push_args(ctx, arg_addr);
7291 push_args(ctx, arg_len);
7292 push_args(ctx, arg_data);
7298 * Parse a zero-ended string.
7301 parse_string0(struct context *ctx, const struct token *token __rte_unused,
7302 const char *str, unsigned int len,
7303 void *buf, unsigned int size)
7305 const struct arg *arg_data = pop_args(ctx);
7307 /* Arguments are expected. */
7310 size = arg_data->size;
7311 /* Bit-mask fill is not supported. */
7312 if (arg_data->mask || size < len + 1)
7316 buf = (uint8_t *)ctx->object + arg_data->offset;
7317 strncpy(buf, str, len);
7319 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7322 push_args(ctx, arg_data);
7327 * Parse a MAC address.
7329 * Last argument (ctx->args) is retrieved to determine storage size and
7333 parse_mac_addr(struct context *ctx, const struct token *token,
7334 const char *str, unsigned int len,
7335 void *buf, unsigned int size)
7337 const struct arg *arg = pop_args(ctx);
7338 struct rte_ether_addr tmp;
7342 /* Argument is expected. */
7346 /* Bit-mask fill is not supported. */
7347 if (arg->mask || size != sizeof(tmp))
7349 /* Only network endian is supported. */
7352 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
7353 if (ret < 0 || (unsigned int)ret != len)
7357 buf = (uint8_t *)ctx->object + arg->offset;
7358 memcpy(buf, &tmp, size);
7360 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7363 push_args(ctx, arg);
7368 * Parse an IPv4 address.
7370 * Last argument (ctx->args) is retrieved to determine storage size and
7374 parse_ipv4_addr(struct context *ctx, const struct token *token,
7375 const char *str, unsigned int len,
7376 void *buf, unsigned int size)
7378 const struct arg *arg = pop_args(ctx);
7383 /* Argument is expected. */
7387 /* Bit-mask fill is not supported. */
7388 if (arg->mask || size != sizeof(tmp))
7390 /* Only network endian is supported. */
7393 memcpy(str2, str, len);
7395 ret = inet_pton(AF_INET, str2, &tmp);
7397 /* Attempt integer parsing. */
7398 push_args(ctx, arg);
7399 return parse_int(ctx, token, str, len, buf, size);
7403 buf = (uint8_t *)ctx->object + arg->offset;
7404 memcpy(buf, &tmp, size);
7406 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7409 push_args(ctx, arg);
7414 * Parse an IPv6 address.
7416 * Last argument (ctx->args) is retrieved to determine storage size and
7420 parse_ipv6_addr(struct context *ctx, const struct token *token,
7421 const char *str, unsigned int len,
7422 void *buf, unsigned int size)
7424 const struct arg *arg = pop_args(ctx);
7426 struct in6_addr tmp;
7430 /* Argument is expected. */
7434 /* Bit-mask fill is not supported. */
7435 if (arg->mask || size != sizeof(tmp))
7437 /* Only network endian is supported. */
7440 memcpy(str2, str, len);
7442 ret = inet_pton(AF_INET6, str2, &tmp);
7447 buf = (uint8_t *)ctx->object + arg->offset;
7448 memcpy(buf, &tmp, size);
7450 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7453 push_args(ctx, arg);
7457 /** Boolean values (even indices stand for false). */
7458 static const char *const boolean_name[] = {
7468 * Parse a boolean value.
7470 * Last argument (ctx->args) is retrieved to determine storage size and
7474 parse_boolean(struct context *ctx, const struct token *token,
7475 const char *str, unsigned int len,
7476 void *buf, unsigned int size)
7478 const struct arg *arg = pop_args(ctx);
7482 /* Argument is expected. */
7485 for (i = 0; boolean_name[i]; ++i)
7486 if (!strcmp_partial(boolean_name[i], str, len))
7488 /* Process token as integer. */
7489 if (boolean_name[i])
7490 str = i & 1 ? "1" : "0";
7491 push_args(ctx, arg);
7492 ret = parse_int(ctx, token, str, strlen(str), buf, size);
7493 return ret > 0 ? (int)len : ret;
7496 /** Parse port and update context. */
7498 parse_port(struct context *ctx, const struct token *token,
7499 const char *str, unsigned int len,
7500 void *buf, unsigned int size)
7502 struct buffer *out = &(struct buffer){ .port = 0 };
7510 ctx->objmask = NULL;
7511 size = sizeof(*out);
7513 ret = parse_int(ctx, token, str, len, out, size);
7515 ctx->port = out->port;
7522 parse_ia_id2ptr(struct context *ctx, const struct token *token,
7523 const char *str, unsigned int len,
7524 void *buf, unsigned int size)
7526 struct rte_flow_action *action = ctx->object;
7534 ctx->objmask = NULL;
7535 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
7536 ctx->object = action;
7537 if (ret != (int)len)
7539 /* set indirect action */
7541 action->conf = port_action_handle_get_by_id(ctx->port, id);
7542 ret = (action->conf) ? ret : -1;
7547 /** Parse set command, initialize output buffer for subsequent tokens. */
7549 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
7550 const char *str, unsigned int len,
7551 void *buf, unsigned int size)
7553 struct buffer *out = buf;
7555 /* Token name must match. */
7556 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7558 /* Nothing else to do if there is no buffer. */
7561 /* Make sure buffer is large enough. */
7562 if (size < sizeof(*out))
7565 ctx->objmask = NULL;
7569 out->command = ctx->curr;
7570 /* For encap/decap we need is pattern */
7571 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7576 /** Parse set command, initialize output buffer for subsequent tokens. */
7578 parse_set_sample_action(struct context *ctx, const struct token *token,
7579 const char *str, unsigned int len,
7580 void *buf, unsigned int size)
7582 struct buffer *out = buf;
7584 /* Token name must match. */
7585 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7587 /* Nothing else to do if there is no buffer. */
7590 /* Make sure buffer is large enough. */
7591 if (size < sizeof(*out))
7594 ctx->objmask = NULL;
7598 out->command = ctx->curr;
7599 /* For sampler we need is actions */
7600 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7606 * Parse set raw_encap/raw_decap command,
7607 * initialize output buffer for subsequent tokens.
7610 parse_set_init(struct context *ctx, const struct token *token,
7611 const char *str, unsigned int len,
7612 void *buf, unsigned int size)
7614 struct buffer *out = buf;
7616 /* Token name must match. */
7617 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7619 /* Nothing else to do if there is no buffer. */
7622 /* Make sure buffer is large enough. */
7623 if (size < sizeof(*out))
7625 /* Initialize buffer. */
7626 memset(out, 0x00, sizeof(*out));
7627 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
7630 ctx->objmask = NULL;
7631 if (!out->command) {
7632 if (ctx->curr != SET)
7634 if (sizeof(*out) > size)
7636 out->command = ctx->curr;
7637 out->args.vc.data = (uint8_t *)out + size;
7638 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7644 /** No completion. */
7646 comp_none(struct context *ctx, const struct token *token,
7647 unsigned int ent, char *buf, unsigned int size)
7657 /** Complete boolean values. */
7659 comp_boolean(struct context *ctx, const struct token *token,
7660 unsigned int ent, char *buf, unsigned int size)
7666 for (i = 0; boolean_name[i]; ++i)
7667 if (buf && i == ent)
7668 return strlcpy(buf, boolean_name[i], size);
7674 /** Complete action names. */
7676 comp_action(struct context *ctx, const struct token *token,
7677 unsigned int ent, char *buf, unsigned int size)
7683 for (i = 0; next_action[i]; ++i)
7684 if (buf && i == ent)
7685 return strlcpy(buf, token_list[next_action[i]].name,
7692 /** Complete available ports. */
7694 comp_port(struct context *ctx, const struct token *token,
7695 unsigned int ent, char *buf, unsigned int size)
7702 RTE_ETH_FOREACH_DEV(p) {
7703 if (buf && i == ent)
7704 return snprintf(buf, size, "%u", p);
7712 /** Complete available rule IDs. */
7714 comp_rule_id(struct context *ctx, const struct token *token,
7715 unsigned int ent, char *buf, unsigned int size)
7718 struct rte_port *port;
7719 struct port_flow *pf;
7722 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
7723 ctx->port == (portid_t)RTE_PORT_ALL)
7725 port = &ports[ctx->port];
7726 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
7727 if (buf && i == ent)
7728 return snprintf(buf, size, "%u", pf->id);
7736 /** Complete type field for RSS action. */
7738 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
7739 unsigned int ent, char *buf, unsigned int size)
7745 for (i = 0; rss_type_table[i].str; ++i)
7750 return strlcpy(buf, rss_type_table[ent].str, size);
7752 return snprintf(buf, size, "end");
7756 /** Complete queue field for RSS action. */
7758 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
7759 unsigned int ent, char *buf, unsigned int size)
7766 return snprintf(buf, size, "%u", ent);
7768 return snprintf(buf, size, "end");
7772 /** Complete index number for set raw_encap/raw_decap commands. */
7774 comp_set_raw_index(struct context *ctx, const struct token *token,
7775 unsigned int ent, char *buf, unsigned int size)
7781 RTE_SET_USED(token);
7782 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
7783 if (buf && idx == ent)
7784 return snprintf(buf, size, "%u", idx);
7790 /** Complete index number for set raw_encap/raw_decap commands. */
7792 comp_set_sample_index(struct context *ctx, const struct token *token,
7793 unsigned int ent, char *buf, unsigned int size)
7799 RTE_SET_USED(token);
7800 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
7801 if (buf && idx == ent)
7802 return snprintf(buf, size, "%u", idx);
7808 /** Complete operation for modify_field command. */
7810 comp_set_modify_field_op(struct context *ctx, const struct token *token,
7811 unsigned int ent, char *buf, unsigned int size)
7816 RTE_SET_USED(token);
7817 for (idx = 0; modify_field_ops[idx]; ++idx)
7822 return strlcpy(buf, modify_field_ops[ent], size);
7826 /** Complete field id for modify_field command. */
7828 comp_set_modify_field_id(struct context *ctx, const struct token *token,
7829 unsigned int ent, char *buf, unsigned int size)
7834 RTE_SET_USED(token);
7835 for (idx = 0; modify_field_ids[idx]; ++idx)
7840 return strlcpy(buf, modify_field_ids[ent], size);
7844 /** Internal context. */
7845 static struct context cmd_flow_context;
7847 /** Global parser instance (cmdline API). */
7848 cmdline_parse_inst_t cmd_flow;
7849 cmdline_parse_inst_t cmd_set_raw;
7851 /** Initialize context. */
7853 cmd_flow_context_init(struct context *ctx)
7855 /* A full memset() is not necessary. */
7865 ctx->objmask = NULL;
7868 /** Parse a token (cmdline API). */
7870 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
7873 struct context *ctx = &cmd_flow_context;
7874 const struct token *token;
7875 const enum index *list;
7880 token = &token_list[ctx->curr];
7881 /* Check argument length. */
7884 for (len = 0; src[len]; ++len)
7885 if (src[len] == '#' || isspace(src[len]))
7889 /* Last argument and EOL detection. */
7890 for (i = len; src[i]; ++i)
7891 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
7893 else if (!isspace(src[i])) {
7898 if (src[i] == '\r' || src[i] == '\n') {
7902 /* Initialize context if necessary. */
7903 if (!ctx->next_num) {
7906 ctx->next[ctx->next_num++] = token->next[0];
7908 /* Process argument through candidates. */
7909 ctx->prev = ctx->curr;
7910 list = ctx->next[ctx->next_num - 1];
7911 for (i = 0; list[i]; ++i) {
7912 const struct token *next = &token_list[list[i]];
7915 ctx->curr = list[i];
7917 tmp = next->call(ctx, next, src, len, result, size);
7919 tmp = parse_default(ctx, next, src, len, result, size);
7920 if (tmp == -1 || tmp != len)
7928 /* Push subsequent tokens if any. */
7930 for (i = 0; token->next[i]; ++i) {
7931 if (ctx->next_num == RTE_DIM(ctx->next))
7933 ctx->next[ctx->next_num++] = token->next[i];
7935 /* Push arguments if any. */
7937 for (i = 0; token->args[i]; ++i) {
7938 if (ctx->args_num == RTE_DIM(ctx->args))
7940 ctx->args[ctx->args_num++] = token->args[i];
7945 /** Return number of completion entries (cmdline API). */
7947 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
7949 struct context *ctx = &cmd_flow_context;
7950 const struct token *token = &token_list[ctx->curr];
7951 const enum index *list;
7955 /* Count number of tokens in current list. */
7957 list = ctx->next[ctx->next_num - 1];
7959 list = token->next[0];
7960 for (i = 0; list[i]; ++i)
7965 * If there is a single token, use its completion callback, otherwise
7966 * return the number of entries.
7968 token = &token_list[list[0]];
7969 if (i == 1 && token->comp) {
7970 /* Save index for cmd_flow_get_help(). */
7971 ctx->prev = list[0];
7972 return token->comp(ctx, token, 0, NULL, 0);
7977 /** Return a completion entry (cmdline API). */
7979 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
7980 char *dst, unsigned int size)
7982 struct context *ctx = &cmd_flow_context;
7983 const struct token *token = &token_list[ctx->curr];
7984 const enum index *list;
7988 /* Count number of tokens in current list. */
7990 list = ctx->next[ctx->next_num - 1];
7992 list = token->next[0];
7993 for (i = 0; list[i]; ++i)
7997 /* If there is a single token, use its completion callback. */
7998 token = &token_list[list[0]];
7999 if (i == 1 && token->comp) {
8000 /* Save index for cmd_flow_get_help(). */
8001 ctx->prev = list[0];
8002 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
8004 /* Otherwise make sure the index is valid and use defaults. */
8007 token = &token_list[list[index]];
8008 strlcpy(dst, token->name, size);
8009 /* Save index for cmd_flow_get_help(). */
8010 ctx->prev = list[index];
8014 /** Populate help strings for current token (cmdline API). */
8016 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
8018 struct context *ctx = &cmd_flow_context;
8019 const struct token *token = &token_list[ctx->prev];
8024 /* Set token type and update global help with details. */
8025 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
8027 cmd_flow.help_str = token->help;
8029 cmd_flow.help_str = token->name;
8033 /** Token definition template (cmdline API). */
8034 static struct cmdline_token_hdr cmd_flow_token_hdr = {
8035 .ops = &(struct cmdline_token_ops){
8036 .parse = cmd_flow_parse,
8037 .complete_get_nb = cmd_flow_complete_get_nb,
8038 .complete_get_elt = cmd_flow_complete_get_elt,
8039 .get_help = cmd_flow_get_help,
8044 /** Populate the next dynamic token. */
8046 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
8047 cmdline_parse_token_hdr_t **hdr_inst)
8049 struct context *ctx = &cmd_flow_context;
8051 /* Always reinitialize context before requesting the first token. */
8052 if (!(hdr_inst - cmd_flow.tokens))
8053 cmd_flow_context_init(ctx);
8054 /* Return NULL when no more tokens are expected. */
8055 if (!ctx->next_num && ctx->curr) {
8059 /* Determine if command should end here. */
8060 if (ctx->eol && ctx->last && ctx->next_num) {
8061 const enum index *list = ctx->next[ctx->next_num - 1];
8064 for (i = 0; list[i]; ++i) {
8071 *hdr = &cmd_flow_token_hdr;
8074 /** Dispatch parsed buffer to function calls. */
8076 cmd_flow_parsed(const struct buffer *in)
8078 switch (in->command) {
8079 case INDIRECT_ACTION_CREATE:
8080 port_action_handle_create(
8081 in->port, in->args.vc.attr.group,
8082 &((const struct rte_flow_indir_action_conf) {
8083 .ingress = in->args.vc.attr.ingress,
8084 .egress = in->args.vc.attr.egress,
8085 .transfer = in->args.vc.attr.transfer,
8087 in->args.vc.actions);
8089 case INDIRECT_ACTION_DESTROY:
8090 port_action_handle_destroy(in->port,
8091 in->args.ia_destroy.action_id_n,
8092 in->args.ia_destroy.action_id);
8094 case INDIRECT_ACTION_UPDATE:
8095 port_action_handle_update(in->port, in->args.vc.attr.group,
8096 in->args.vc.actions);
8098 case INDIRECT_ACTION_QUERY:
8099 port_action_handle_query(in->port, in->args.ia.action_id);
8102 port_flow_validate(in->port, &in->args.vc.attr,
8103 in->args.vc.pattern, in->args.vc.actions,
8104 &in->args.vc.tunnel_ops);
8107 port_flow_create(in->port, &in->args.vc.attr,
8108 in->args.vc.pattern, in->args.vc.actions,
8109 &in->args.vc.tunnel_ops);
8112 port_flow_destroy(in->port, in->args.destroy.rule_n,
8113 in->args.destroy.rule);
8116 port_flow_flush(in->port);
8120 port_flow_dump(in->port, in->args.dump.mode,
8121 in->args.dump.rule, in->args.dump.file);
8124 port_flow_query(in->port, in->args.query.rule,
8125 &in->args.query.action);
8128 port_flow_list(in->port, in->args.list.group_n,
8129 in->args.list.group);
8132 port_flow_isolate(in->port, in->args.isolate.set);
8135 port_flow_aged(in->port, in->args.aged.destroy);
8138 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
8140 case TUNNEL_DESTROY:
8141 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
8144 port_flow_tunnel_list(in->port);
8147 port_meter_policy_add(in->port, in->args.policy.policy_id,
8148 in->args.vc.actions);
8155 /** Token generator and output processing callback (cmdline API). */
8157 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
8160 cmd_flow_tok(arg0, arg2);
8162 cmd_flow_parsed(arg0);
8165 /** Global parser instance (cmdline API). */
8166 cmdline_parse_inst_t cmd_flow = {
8168 .data = NULL, /**< Unused. */
8169 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
8172 }, /**< Tokens are returned by cmd_flow_tok(). */
8175 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
8178 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
8180 struct rte_ipv4_hdr *ipv4;
8181 struct rte_ether_hdr *eth;
8182 struct rte_ipv6_hdr *ipv6;
8183 struct rte_vxlan_hdr *vxlan;
8184 struct rte_vxlan_gpe_hdr *gpe;
8185 struct rte_flow_item_nvgre *nvgre;
8186 uint32_t ipv6_vtc_flow;
8188 switch (item->type) {
8189 case RTE_FLOW_ITEM_TYPE_ETH:
8190 eth = (struct rte_ether_hdr *)buf;
8192 eth->ether_type = rte_cpu_to_be_16(next_proto);
8194 case RTE_FLOW_ITEM_TYPE_IPV4:
8195 ipv4 = (struct rte_ipv4_hdr *)buf;
8196 ipv4->version_ihl = 0x45;
8197 if (next_proto && ipv4->next_proto_id == 0)
8198 ipv4->next_proto_id = (uint8_t)next_proto;
8200 case RTE_FLOW_ITEM_TYPE_IPV6:
8201 ipv6 = (struct rte_ipv6_hdr *)buf;
8202 if (next_proto && ipv6->proto == 0)
8203 ipv6->proto = (uint8_t)next_proto;
8204 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
8205 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
8206 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
8207 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
8209 case RTE_FLOW_ITEM_TYPE_VXLAN:
8210 vxlan = (struct rte_vxlan_hdr *)buf;
8211 vxlan->vx_flags = 0x08;
8213 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8214 gpe = (struct rte_vxlan_gpe_hdr *)buf;
8215 gpe->vx_flags = 0x0C;
8217 case RTE_FLOW_ITEM_TYPE_NVGRE:
8218 nvgre = (struct rte_flow_item_nvgre *)buf;
8219 nvgre->protocol = rte_cpu_to_be_16(0x6558);
8220 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
8227 /** Helper of get item's default mask. */
8229 flow_item_default_mask(const struct rte_flow_item *item)
8231 const void *mask = NULL;
8232 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
8234 switch (item->type) {
8235 case RTE_FLOW_ITEM_TYPE_ANY:
8236 mask = &rte_flow_item_any_mask;
8238 case RTE_FLOW_ITEM_TYPE_VF:
8239 mask = &rte_flow_item_vf_mask;
8241 case RTE_FLOW_ITEM_TYPE_PORT_ID:
8242 mask = &rte_flow_item_port_id_mask;
8244 case RTE_FLOW_ITEM_TYPE_RAW:
8245 mask = &rte_flow_item_raw_mask;
8247 case RTE_FLOW_ITEM_TYPE_ETH:
8248 mask = &rte_flow_item_eth_mask;
8250 case RTE_FLOW_ITEM_TYPE_VLAN:
8251 mask = &rte_flow_item_vlan_mask;
8253 case RTE_FLOW_ITEM_TYPE_IPV4:
8254 mask = &rte_flow_item_ipv4_mask;
8256 case RTE_FLOW_ITEM_TYPE_IPV6:
8257 mask = &rte_flow_item_ipv6_mask;
8259 case RTE_FLOW_ITEM_TYPE_ICMP:
8260 mask = &rte_flow_item_icmp_mask;
8262 case RTE_FLOW_ITEM_TYPE_UDP:
8263 mask = &rte_flow_item_udp_mask;
8265 case RTE_FLOW_ITEM_TYPE_TCP:
8266 mask = &rte_flow_item_tcp_mask;
8268 case RTE_FLOW_ITEM_TYPE_SCTP:
8269 mask = &rte_flow_item_sctp_mask;
8271 case RTE_FLOW_ITEM_TYPE_VXLAN:
8272 mask = &rte_flow_item_vxlan_mask;
8274 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8275 mask = &rte_flow_item_vxlan_gpe_mask;
8277 case RTE_FLOW_ITEM_TYPE_E_TAG:
8278 mask = &rte_flow_item_e_tag_mask;
8280 case RTE_FLOW_ITEM_TYPE_NVGRE:
8281 mask = &rte_flow_item_nvgre_mask;
8283 case RTE_FLOW_ITEM_TYPE_MPLS:
8284 mask = &rte_flow_item_mpls_mask;
8286 case RTE_FLOW_ITEM_TYPE_GRE:
8287 mask = &rte_flow_item_gre_mask;
8289 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
8290 mask = &gre_key_default_mask;
8292 case RTE_FLOW_ITEM_TYPE_META:
8293 mask = &rte_flow_item_meta_mask;
8295 case RTE_FLOW_ITEM_TYPE_FUZZY:
8296 mask = &rte_flow_item_fuzzy_mask;
8298 case RTE_FLOW_ITEM_TYPE_GTP:
8299 mask = &rte_flow_item_gtp_mask;
8301 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
8302 mask = &rte_flow_item_gtp_psc_mask;
8304 case RTE_FLOW_ITEM_TYPE_GENEVE:
8305 mask = &rte_flow_item_geneve_mask;
8307 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
8308 mask = &rte_flow_item_geneve_opt_mask;
8310 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
8311 mask = &rte_flow_item_pppoe_proto_id_mask;
8313 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
8314 mask = &rte_flow_item_l2tpv3oip_mask;
8316 case RTE_FLOW_ITEM_TYPE_ESP:
8317 mask = &rte_flow_item_esp_mask;
8319 case RTE_FLOW_ITEM_TYPE_AH:
8320 mask = &rte_flow_item_ah_mask;
8322 case RTE_FLOW_ITEM_TYPE_PFCP:
8323 mask = &rte_flow_item_pfcp_mask;
8331 /** Dispatch parsed buffer to function calls. */
8333 cmd_set_raw_parsed_sample(const struct buffer *in)
8335 uint32_t n = in->args.vc.actions_n;
8337 struct rte_flow_action *action = NULL;
8338 struct rte_flow_action *data = NULL;
8339 const struct rte_flow_action_rss *rss = NULL;
8341 uint16_t idx = in->port; /* We borrow port field as index */
8342 uint32_t max_size = sizeof(struct rte_flow_action) *
8343 ACTION_SAMPLE_ACTIONS_NUM;
8345 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
8346 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
8347 memset(data, 0x00, max_size);
8348 for (; i <= n - 1; i++) {
8349 action = in->args.vc.actions + i;
8350 if (action->type == RTE_FLOW_ACTION_TYPE_END)
8352 switch (action->type) {
8353 case RTE_FLOW_ACTION_TYPE_MARK:
8354 size = sizeof(struct rte_flow_action_mark);
8355 rte_memcpy(&sample_mark[idx],
8356 (const void *)action->conf, size);
8357 action->conf = &sample_mark[idx];
8359 case RTE_FLOW_ACTION_TYPE_COUNT:
8360 size = sizeof(struct rte_flow_action_count);
8361 rte_memcpy(&sample_count[idx],
8362 (const void *)action->conf, size);
8363 action->conf = &sample_count[idx];
8365 case RTE_FLOW_ACTION_TYPE_QUEUE:
8366 size = sizeof(struct rte_flow_action_queue);
8367 rte_memcpy(&sample_queue[idx],
8368 (const void *)action->conf, size);
8369 action->conf = &sample_queue[idx];
8371 case RTE_FLOW_ACTION_TYPE_RSS:
8372 size = sizeof(struct rte_flow_action_rss);
8374 rte_memcpy(&sample_rss_data[idx].conf,
8375 (const void *)rss, size);
8376 if (rss->key_len && rss->key) {
8377 sample_rss_data[idx].conf.key =
8378 sample_rss_data[idx].key;
8379 rte_memcpy((void *)((uintptr_t)
8380 sample_rss_data[idx].conf.key),
8381 (const void *)rss->key,
8382 sizeof(uint8_t) * rss->key_len);
8384 if (rss->queue_num && rss->queue) {
8385 sample_rss_data[idx].conf.queue =
8386 sample_rss_data[idx].queue;
8387 rte_memcpy((void *)((uintptr_t)
8388 sample_rss_data[idx].conf.queue),
8389 (const void *)rss->queue,
8390 sizeof(uint16_t) * rss->queue_num);
8392 action->conf = &sample_rss_data[idx].conf;
8394 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
8395 size = sizeof(struct rte_flow_action_raw_encap);
8396 rte_memcpy(&sample_encap[idx],
8397 (const void *)action->conf, size);
8398 action->conf = &sample_encap[idx];
8400 case RTE_FLOW_ACTION_TYPE_PORT_ID:
8401 size = sizeof(struct rte_flow_action_port_id);
8402 rte_memcpy(&sample_port_id[idx],
8403 (const void *)action->conf, size);
8404 action->conf = &sample_port_id[idx];
8406 case RTE_FLOW_ACTION_TYPE_PF:
8408 case RTE_FLOW_ACTION_TYPE_VF:
8409 size = sizeof(struct rte_flow_action_vf);
8410 rte_memcpy(&sample_vf[idx],
8411 (const void *)action->conf, size);
8412 action->conf = &sample_vf[idx];
8414 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
8415 size = sizeof(struct rte_flow_action_vxlan_encap);
8416 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
8417 action->conf = &sample_vxlan_encap[idx].conf;
8419 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
8420 size = sizeof(struct rte_flow_action_nvgre_encap);
8421 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
8422 action->conf = &sample_nvgre_encap[idx];
8425 printf("Error - Not supported action\n");
8428 rte_memcpy(data, action, sizeof(struct rte_flow_action));
8433 /** Dispatch parsed buffer to function calls. */
8435 cmd_set_raw_parsed(const struct buffer *in)
8437 uint32_t n = in->args.vc.pattern_n;
8439 struct rte_flow_item *item = NULL;
8441 uint8_t *data = NULL;
8442 uint8_t *data_tail = NULL;
8443 size_t *total_size = NULL;
8444 uint16_t upper_layer = 0;
8446 uint16_t idx = in->port; /* We borrow port field as index */
8447 int gtp_psc = -1; /* GTP PSC option index. */
8449 if (in->command == SET_SAMPLE_ACTIONS)
8450 return cmd_set_raw_parsed_sample(in);
8451 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
8452 in->command == SET_RAW_DECAP);
8453 if (in->command == SET_RAW_ENCAP) {
8454 total_size = &raw_encap_confs[idx].size;
8455 data = (uint8_t *)&raw_encap_confs[idx].data;
8457 total_size = &raw_decap_confs[idx].size;
8458 data = (uint8_t *)&raw_decap_confs[idx].data;
8461 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
8462 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
8463 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
8464 for (i = n - 1 ; i >= 0; --i) {
8465 const struct rte_flow_item_gtp *gtp;
8466 const struct rte_flow_item_geneve_opt *opt;
8468 item = in->args.vc.pattern + i;
8469 if (item->spec == NULL)
8470 item->spec = flow_item_default_mask(item);
8471 switch (item->type) {
8472 case RTE_FLOW_ITEM_TYPE_ETH:
8473 size = sizeof(struct rte_ether_hdr);
8475 case RTE_FLOW_ITEM_TYPE_VLAN:
8476 size = sizeof(struct rte_vlan_hdr);
8477 proto = RTE_ETHER_TYPE_VLAN;
8479 case RTE_FLOW_ITEM_TYPE_IPV4:
8480 size = sizeof(struct rte_ipv4_hdr);
8481 proto = RTE_ETHER_TYPE_IPV4;
8483 case RTE_FLOW_ITEM_TYPE_IPV6:
8484 size = sizeof(struct rte_ipv6_hdr);
8485 proto = RTE_ETHER_TYPE_IPV6;
8487 case RTE_FLOW_ITEM_TYPE_UDP:
8488 size = sizeof(struct rte_udp_hdr);
8491 case RTE_FLOW_ITEM_TYPE_TCP:
8492 size = sizeof(struct rte_tcp_hdr);
8495 case RTE_FLOW_ITEM_TYPE_VXLAN:
8496 size = sizeof(struct rte_vxlan_hdr);
8498 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8499 size = sizeof(struct rte_vxlan_gpe_hdr);
8501 case RTE_FLOW_ITEM_TYPE_GRE:
8502 size = sizeof(struct rte_gre_hdr);
8505 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
8506 size = sizeof(rte_be32_t);
8509 case RTE_FLOW_ITEM_TYPE_MPLS:
8510 size = sizeof(struct rte_mpls_hdr);
8513 case RTE_FLOW_ITEM_TYPE_NVGRE:
8514 size = sizeof(struct rte_flow_item_nvgre);
8517 case RTE_FLOW_ITEM_TYPE_GENEVE:
8518 size = sizeof(struct rte_geneve_hdr);
8520 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
8521 opt = (const struct rte_flow_item_geneve_opt *)
8523 size = offsetof(struct rte_flow_item_geneve_opt, data);
8524 if (opt->option_len && opt->data) {
8525 *total_size += opt->option_len *
8527 rte_memcpy(data_tail - (*total_size),
8529 opt->option_len * sizeof(uint32_t));
8532 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
8533 size = sizeof(rte_be32_t);
8536 case RTE_FLOW_ITEM_TYPE_ESP:
8537 size = sizeof(struct rte_esp_hdr);
8540 case RTE_FLOW_ITEM_TYPE_AH:
8541 size = sizeof(struct rte_flow_item_ah);
8544 case RTE_FLOW_ITEM_TYPE_GTP:
8546 size = sizeof(struct rte_gtp_hdr);
8549 if (gtp_psc != i + 1) {
8550 printf("Error - GTP PSC does not follow GTP\n");
8554 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
8555 /* Only E flag should be set. */
8556 printf("Error - GTP unsupported flags\n");
8559 struct rte_gtp_hdr_ext_word ext_word = {
8563 /* We have to add GTP header extra word. */
8564 *total_size += sizeof(ext_word);
8565 rte_memcpy(data_tail - (*total_size),
8566 &ext_word, sizeof(ext_word));
8568 size = sizeof(struct rte_gtp_hdr);
8570 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
8572 printf("Error - Multiple GTP PSC items\n");
8575 const struct rte_flow_item_gtp_psc
8584 if (opt->pdu_type & 0x0F) {
8585 /* Support the minimal option only. */
8586 printf("Error - GTP PSC option with "
8587 "extra fields not supported\n");
8590 psc.len = sizeof(psc);
8591 psc.pdu_type = opt->pdu_type;
8594 *total_size += sizeof(psc);
8595 rte_memcpy(data_tail - (*total_size),
8601 case RTE_FLOW_ITEM_TYPE_PFCP:
8602 size = sizeof(struct rte_flow_item_pfcp);
8605 printf("Error - Not supported item\n");
8608 *total_size += size;
8609 rte_memcpy(data_tail - (*total_size), item->spec, size);
8610 /* update some fields which cannot be set by cmdline */
8611 update_fields((data_tail - (*total_size)), item,
8613 upper_layer = proto;
8615 if (verbose_level & 0x1)
8616 printf("total data size is %zu\n", (*total_size));
8617 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
8618 memmove(data, (data_tail - (*total_size)), *total_size);
8623 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
8626 /** Populate help strings for current token (cmdline API). */
8628 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
8631 struct context *ctx = &cmd_flow_context;
8632 const struct token *token = &token_list[ctx->prev];
8637 /* Set token type and update global help with details. */
8638 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
8640 cmd_set_raw.help_str = token->help;
8642 cmd_set_raw.help_str = token->name;
8646 /** Token definition template (cmdline API). */
8647 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
8648 .ops = &(struct cmdline_token_ops){
8649 .parse = cmd_flow_parse,
8650 .complete_get_nb = cmd_flow_complete_get_nb,
8651 .complete_get_elt = cmd_flow_complete_get_elt,
8652 .get_help = cmd_set_raw_get_help,
8657 /** Populate the next dynamic token. */
8659 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
8660 cmdline_parse_token_hdr_t **hdr_inst)
8662 struct context *ctx = &cmd_flow_context;
8664 /* Always reinitialize context before requesting the first token. */
8665 if (!(hdr_inst - cmd_set_raw.tokens)) {
8666 cmd_flow_context_init(ctx);
8667 ctx->curr = START_SET;
8669 /* Return NULL when no more tokens are expected. */
8670 if (!ctx->next_num && (ctx->curr != START_SET)) {
8674 /* Determine if command should end here. */
8675 if (ctx->eol && ctx->last && ctx->next_num) {
8676 const enum index *list = ctx->next[ctx->next_num - 1];
8679 for (i = 0; list[i]; ++i) {
8686 *hdr = &cmd_set_raw_token_hdr;
8689 /** Token generator and output processing callback (cmdline API). */
8691 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
8694 cmd_set_raw_tok(arg0, arg2);
8696 cmd_set_raw_parsed(arg0);
8699 /** Global parser instance (cmdline API). */
8700 cmdline_parse_inst_t cmd_set_raw = {
8701 .f = cmd_set_raw_cb,
8702 .data = NULL, /**< Unused. */
8703 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
8706 }, /**< Tokens are returned by cmd_flow_tok(). */
8709 /* *** display raw_encap/raw_decap buf */
8710 struct cmd_show_set_raw_result {
8711 cmdline_fixed_string_t cmd_show;
8712 cmdline_fixed_string_t cmd_what;
8713 cmdline_fixed_string_t cmd_all;
8718 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
8720 struct cmd_show_set_raw_result *res = parsed_result;
8721 uint16_t index = res->cmd_index;
8723 uint8_t *raw_data = NULL;
8724 size_t raw_size = 0;
8725 char title[16] = {0};
8729 if (!strcmp(res->cmd_all, "all")) {
8732 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
8733 printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1);
8737 if (!strcmp(res->cmd_what, "raw_encap")) {
8738 raw_data = (uint8_t *)&raw_encap_confs[index].data;
8739 raw_size = raw_encap_confs[index].size;
8740 snprintf(title, 16, "\nindex: %u", index);
8741 rte_hexdump(stdout, title, raw_data, raw_size);
8743 raw_data = (uint8_t *)&raw_decap_confs[index].data;
8744 raw_size = raw_decap_confs[index].size;
8745 snprintf(title, 16, "\nindex: %u", index);
8746 rte_hexdump(stdout, title, raw_data, raw_size);
8748 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
8751 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
8752 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8754 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
8755 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8756 cmd_what, "raw_encap#raw_decap");
8757 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
8758 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
8759 cmd_index, RTE_UINT16);
8760 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
8761 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8763 cmdline_parse_inst_t cmd_show_set_raw = {
8764 .f = cmd_show_set_raw_parsed,
8766 .help_str = "show <raw_encap|raw_decap> <index>",
8768 (void *)&cmd_show_set_raw_cmd_show,
8769 (void *)&cmd_show_set_raw_cmd_what,
8770 (void *)&cmd_show_set_raw_cmd_index,
8774 cmdline_parse_inst_t cmd_show_set_raw_all = {
8775 .f = cmd_show_set_raw_parsed,
8777 .help_str = "show <raw_encap|raw_decap> all",
8779 (void *)&cmd_show_set_raw_cmd_show,
8780 (void *)&cmd_show_set_raw_cmd_what,
8781 (void *)&cmd_show_set_raw_cmd_all,