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,
177 ITEM_IPV4_FRAGMENT_OFFSET,
189 ITEM_IPV6_HAS_FRAG_EXT,
209 ITEM_VXLAN_LAST_RSVD,
211 ITEM_E_TAG_GRP_ECID_B,
220 ITEM_GRE_C_RSVD0_VER,
239 ITEM_ARP_ETH_IPV4_SHA,
240 ITEM_ARP_ETH_IPV4_SPA,
241 ITEM_ARP_ETH_IPV4_THA,
242 ITEM_ARP_ETH_IPV4_TPA,
244 ITEM_IPV6_EXT_NEXT_HDR,
246 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
247 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
248 ITEM_IPV6_FRAG_EXT_ID,
253 ITEM_ICMP6_ND_NS_TARGET_ADDR,
255 ITEM_ICMP6_ND_NA_TARGET_ADDR,
257 ITEM_ICMP6_ND_OPT_TYPE,
258 ITEM_ICMP6_ND_OPT_SLA_ETH,
259 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
260 ITEM_ICMP6_ND_OPT_TLA_ETH,
261 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
274 ITEM_HIGIG2_CLASSIFICATION,
280 ITEM_L2TPV3OIP_SESSION_ID,
290 ITEM_ECPRI_COMMON_TYPE,
291 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
292 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
293 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
294 ITEM_ECPRI_MSG_IQ_DATA_PCID,
295 ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
296 ITEM_ECPRI_MSG_DLY_MSR_MSRID,
298 ITEM_GENEVE_OPT_CLASS,
299 ITEM_GENEVE_OPT_TYPE,
300 ITEM_GENEVE_OPT_LENGTH,
301 ITEM_GENEVE_OPT_DATA,
303 ITEM_INTEGRITY_LEVEL,
304 ITEM_INTEGRITY_VALUE,
310 /* Validate/create actions. */
330 ACTION_RSS_FUNC_DEFAULT,
331 ACTION_RSS_FUNC_TOEPLITZ,
332 ACTION_RSS_FUNC_SIMPLE_XOR,
333 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
345 ACTION_PHY_PORT_ORIGINAL,
346 ACTION_PHY_PORT_INDEX,
348 ACTION_PORT_ID_ORIGINAL,
352 ACTION_METER_COLOR_TYPE,
353 ACTION_METER_COLOR_GREEN,
354 ACTION_METER_COLOR_YELLOW,
355 ACTION_METER_COLOR_RED,
357 ACTION_OF_SET_MPLS_TTL,
358 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
359 ACTION_OF_DEC_MPLS_TTL,
360 ACTION_OF_SET_NW_TTL,
361 ACTION_OF_SET_NW_TTL_NW_TTL,
362 ACTION_OF_DEC_NW_TTL,
363 ACTION_OF_COPY_TTL_OUT,
364 ACTION_OF_COPY_TTL_IN,
367 ACTION_OF_PUSH_VLAN_ETHERTYPE,
368 ACTION_OF_SET_VLAN_VID,
369 ACTION_OF_SET_VLAN_VID_VLAN_VID,
370 ACTION_OF_SET_VLAN_PCP,
371 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
373 ACTION_OF_POP_MPLS_ETHERTYPE,
375 ACTION_OF_PUSH_MPLS_ETHERTYPE,
382 ACTION_MPLSOGRE_ENCAP,
383 ACTION_MPLSOGRE_DECAP,
384 ACTION_MPLSOUDP_ENCAP,
385 ACTION_MPLSOUDP_DECAP,
387 ACTION_SET_IPV4_SRC_IPV4_SRC,
389 ACTION_SET_IPV4_DST_IPV4_DST,
391 ACTION_SET_IPV6_SRC_IPV6_SRC,
393 ACTION_SET_IPV6_DST_IPV6_DST,
395 ACTION_SET_TP_SRC_TP_SRC,
397 ACTION_SET_TP_DST_TP_DST,
403 ACTION_SET_MAC_SRC_MAC_SRC,
405 ACTION_SET_MAC_DST_MAC_DST,
407 ACTION_INC_TCP_SEQ_VALUE,
409 ACTION_DEC_TCP_SEQ_VALUE,
411 ACTION_INC_TCP_ACK_VALUE,
413 ACTION_DEC_TCP_ACK_VALUE,
416 ACTION_RAW_ENCAP_INDEX,
417 ACTION_RAW_ENCAP_INDEX_VALUE,
418 ACTION_RAW_DECAP_INDEX,
419 ACTION_RAW_DECAP_INDEX_VALUE,
422 ACTION_SET_TAG_INDEX,
425 ACTION_SET_META_DATA,
426 ACTION_SET_META_MASK,
427 ACTION_SET_IPV4_DSCP,
428 ACTION_SET_IPV4_DSCP_VALUE,
429 ACTION_SET_IPV6_DSCP,
430 ACTION_SET_IPV6_DSCP_VALUE,
436 ACTION_SAMPLE_INDEX_VALUE,
438 INDIRECT_ACTION_ID2PTR,
440 ACTION_MODIFY_FIELD_OP,
441 ACTION_MODIFY_FIELD_OP_VALUE,
442 ACTION_MODIFY_FIELD_DST_TYPE,
443 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
444 ACTION_MODIFY_FIELD_DST_LEVEL,
445 ACTION_MODIFY_FIELD_DST_OFFSET,
446 ACTION_MODIFY_FIELD_SRC_TYPE,
447 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
448 ACTION_MODIFY_FIELD_SRC_LEVEL,
449 ACTION_MODIFY_FIELD_SRC_OFFSET,
450 ACTION_MODIFY_FIELD_SRC_VALUE,
451 ACTION_MODIFY_FIELD_WIDTH,
453 ACTION_CONNTRACK_UPDATE,
454 ACTION_CONNTRACK_UPDATE_DIR,
455 ACTION_CONNTRACK_UPDATE_CTX,
461 /** Maximum size for pattern in struct rte_flow_item_raw. */
462 #define ITEM_RAW_PATTERN_SIZE 40
464 /** Maximum size for GENEVE option data pattern in bytes. */
465 #define ITEM_GENEVE_OPT_DATA_SIZE 124
467 /** Storage size for struct rte_flow_item_raw including pattern. */
468 #define ITEM_RAW_SIZE \
469 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
471 /** Maximum number of queue indices in struct rte_flow_action_rss. */
472 #define ACTION_RSS_QUEUE_NUM 128
474 /** Storage for struct rte_flow_action_rss including external data. */
475 struct action_rss_data {
476 struct rte_flow_action_rss conf;
477 uint8_t key[RSS_HASH_KEY_LENGTH];
478 uint16_t queue[ACTION_RSS_QUEUE_NUM];
481 /** Maximum data size in struct rte_flow_action_raw_encap. */
482 #define ACTION_RAW_ENCAP_MAX_DATA 512
483 #define RAW_ENCAP_CONFS_MAX_NUM 8
485 /** Storage for struct rte_flow_action_raw_encap. */
486 struct raw_encap_conf {
487 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
488 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
492 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
494 /** Storage for struct rte_flow_action_raw_encap including external data. */
495 struct action_raw_encap_data {
496 struct rte_flow_action_raw_encap conf;
497 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
498 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
502 /** Storage for struct rte_flow_action_raw_decap. */
503 struct raw_decap_conf {
504 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
508 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
510 /** Storage for struct rte_flow_action_raw_decap including external data. */
511 struct action_raw_decap_data {
512 struct rte_flow_action_raw_decap conf;
513 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
517 struct vxlan_encap_conf vxlan_encap_conf = {
521 .vni = "\x00\x00\x00",
523 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
524 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
525 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
526 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
527 "\x00\x00\x00\x00\x00\x00\x00\x01",
528 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
529 "\x00\x00\x00\x00\x00\x00\x11\x11",
533 .eth_src = "\x00\x00\x00\x00\x00\x00",
534 .eth_dst = "\xff\xff\xff\xff\xff\xff",
537 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
538 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
540 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
541 struct action_vxlan_encap_data {
542 struct rte_flow_action_vxlan_encap conf;
543 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
544 struct rte_flow_item_eth item_eth;
545 struct rte_flow_item_vlan item_vlan;
547 struct rte_flow_item_ipv4 item_ipv4;
548 struct rte_flow_item_ipv6 item_ipv6;
550 struct rte_flow_item_udp item_udp;
551 struct rte_flow_item_vxlan item_vxlan;
554 struct nvgre_encap_conf nvgre_encap_conf = {
557 .tni = "\x00\x00\x00",
558 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
559 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
560 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
561 "\x00\x00\x00\x00\x00\x00\x00\x01",
562 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
563 "\x00\x00\x00\x00\x00\x00\x11\x11",
565 .eth_src = "\x00\x00\x00\x00\x00\x00",
566 .eth_dst = "\xff\xff\xff\xff\xff\xff",
569 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
570 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
572 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
573 struct action_nvgre_encap_data {
574 struct rte_flow_action_nvgre_encap conf;
575 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
576 struct rte_flow_item_eth item_eth;
577 struct rte_flow_item_vlan item_vlan;
579 struct rte_flow_item_ipv4 item_ipv4;
580 struct rte_flow_item_ipv6 item_ipv6;
582 struct rte_flow_item_nvgre item_nvgre;
585 struct l2_encap_conf l2_encap_conf;
587 struct l2_decap_conf l2_decap_conf;
589 struct mplsogre_encap_conf mplsogre_encap_conf;
591 struct mplsogre_decap_conf mplsogre_decap_conf;
593 struct mplsoudp_encap_conf mplsoudp_encap_conf;
595 struct mplsoudp_decap_conf mplsoudp_decap_conf;
597 struct rte_flow_action_conntrack conntrack_context;
599 #define ACTION_SAMPLE_ACTIONS_NUM 10
600 #define RAW_SAMPLE_CONFS_MAX_NUM 8
601 /** Storage for struct rte_flow_action_sample including external data. */
602 struct action_sample_data {
603 struct rte_flow_action_sample conf;
606 /** Storage for struct rte_flow_action_sample. */
607 struct raw_sample_conf {
608 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
610 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
611 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
612 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
613 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
614 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
615 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
616 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
617 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
618 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
619 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
621 static const char *const modify_field_ops[] = {
622 "set", "add", "sub", NULL
625 static const char *const modify_field_ids[] = {
626 "start", "mac_dst", "mac_src",
627 "vlan_type", "vlan_id", "mac_type",
628 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
629 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
630 "tcp_port_src", "tcp_port_dst",
631 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
632 "udp_port_src", "udp_port_dst",
633 "vxlan_vni", "geneve_vni", "gtp_teid",
634 "tag", "mark", "meta", "pointer", "value", NULL
637 /** Maximum number of subsequent tokens and arguments on the stack. */
638 #define CTX_STACK_SIZE 16
640 /** Parser context. */
642 /** Stack of subsequent token lists to process. */
643 const enum index *next[CTX_STACK_SIZE];
644 /** Arguments for stacked tokens. */
645 const void *args[CTX_STACK_SIZE];
646 enum index curr; /**< Current token index. */
647 enum index prev; /**< Index of the last token seen. */
648 int next_num; /**< Number of entries in next[]. */
649 int args_num; /**< Number of entries in args[]. */
650 uint32_t eol:1; /**< EOL has been detected. */
651 uint32_t last:1; /**< No more arguments. */
652 portid_t port; /**< Current port ID (for completions). */
653 uint32_t objdata; /**< Object-specific data. */
654 void *object; /**< Address of current object for relative offsets. */
655 void *objmask; /**< Object a full mask must be written to. */
658 /** Token argument. */
660 uint32_t hton:1; /**< Use network byte ordering. */
661 uint32_t sign:1; /**< Value is signed. */
662 uint32_t bounded:1; /**< Value is bounded. */
663 uintmax_t min; /**< Minimum value if bounded. */
664 uintmax_t max; /**< Maximum value if bounded. */
665 uint32_t offset; /**< Relative offset from ctx->object. */
666 uint32_t size; /**< Field size. */
667 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
670 /** Parser token definition. */
672 /** Type displayed during completion (defaults to "TOKEN"). */
674 /** Help displayed during completion (defaults to token name). */
676 /** Private data used by parser functions. */
679 * Lists of subsequent tokens to push on the stack. Each call to the
680 * parser consumes the last entry of that stack.
682 const enum index *const *next;
683 /** Arguments stack for subsequent tokens that need them. */
684 const struct arg *const *args;
686 * Token-processing callback, returns -1 in case of error, the
687 * length of the matched string otherwise. If NULL, attempts to
688 * match the token name.
690 * If buf is not NULL, the result should be stored in it according
691 * to context. An error is returned if not large enough.
693 int (*call)(struct context *ctx, const struct token *token,
694 const char *str, unsigned int len,
695 void *buf, unsigned int size);
697 * Callback that provides possible values for this token, used for
698 * completion. Returns -1 in case of error, the number of possible
699 * values otherwise. If NULL, the token name is used.
701 * If buf is not NULL, entry index ent is written to buf and the
702 * full length of the entry is returned (same behavior as
705 int (*comp)(struct context *ctx, const struct token *token,
706 unsigned int ent, char *buf, unsigned int size);
707 /** Mandatory token name, no default value. */
711 /** Static initializer for the next field. */
712 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
714 /** Static initializer for a NEXT() entry. */
715 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
717 /** Static initializer for the args field. */
718 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
720 /** Static initializer for ARGS() to target a field. */
721 #define ARGS_ENTRY(s, f) \
722 (&(const struct arg){ \
723 .offset = offsetof(s, f), \
724 .size = sizeof(((s *)0)->f), \
727 /** Static initializer for ARGS() to target a bit-field. */
728 #define ARGS_ENTRY_BF(s, f, b) \
729 (&(const struct arg){ \
731 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
734 /** Static initializer for ARGS() to target a field with limits. */
735 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
736 (&(const struct arg){ \
740 .offset = offsetof(s, f), \
741 .size = sizeof(((s *)0)->f), \
744 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
745 #define ARGS_ENTRY_MASK(s, f, m) \
746 (&(const struct arg){ \
747 .offset = offsetof(s, f), \
748 .size = sizeof(((s *)0)->f), \
749 .mask = (const void *)(m), \
752 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
753 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
754 (&(const struct arg){ \
756 .offset = offsetof(s, f), \
757 .size = sizeof(((s *)0)->f), \
758 .mask = (const void *)(m), \
761 /** Static initializer for ARGS() to target a pointer. */
762 #define ARGS_ENTRY_PTR(s, f) \
763 (&(const struct arg){ \
764 .size = sizeof(*((s *)0)->f), \
767 /** Static initializer for ARGS() with arbitrary offset and size. */
768 #define ARGS_ENTRY_ARB(o, s) \
769 (&(const struct arg){ \
774 /** Same as ARGS_ENTRY_ARB() with bounded values. */
775 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
776 (&(const struct arg){ \
784 /** Same as ARGS_ENTRY() using network byte ordering. */
785 #define ARGS_ENTRY_HTON(s, f) \
786 (&(const struct arg){ \
788 .offset = offsetof(s, f), \
789 .size = sizeof(((s *)0)->f), \
792 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
793 #define ARG_ENTRY_HTON(s) \
794 (&(const struct arg){ \
800 /** Parser output buffer layout expected by cmd_flow_parsed(). */
802 enum index command; /**< Flow command. */
803 portid_t port; /**< Affected port ID. */
807 uint32_t action_id_n;
808 } ia_destroy; /**< Indirect action destroy arguments. */
811 } ia; /* Indirect action query arguments */
813 struct rte_flow_attr attr;
814 struct tunnel_ops tunnel_ops;
815 struct rte_flow_item *pattern;
816 struct rte_flow_action *actions;
820 } vc; /**< Validate/create arguments. */
824 } destroy; /**< Destroy arguments. */
829 } dump; /**< Dump arguments. */
832 struct rte_flow_action action;
833 } query; /**< Query arguments. */
837 } list; /**< List arguments. */
840 } isolate; /**< Isolated mode arguments. */
843 } aged; /**< Aged arguments. */
846 } policy;/**< Policy arguments. */
847 } args; /**< Command arguments. */
850 /** Private data for pattern items. */
851 struct parse_item_priv {
852 enum rte_flow_item_type type; /**< Item type. */
853 uint32_t size; /**< Size of item specification structure. */
856 #define PRIV_ITEM(t, s) \
857 (&(const struct parse_item_priv){ \
858 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
862 /** Private data for actions. */
863 struct parse_action_priv {
864 enum rte_flow_action_type type; /**< Action type. */
865 uint32_t size; /**< Size of action configuration structure. */
868 #define PRIV_ACTION(t, s) \
869 (&(const struct parse_action_priv){ \
870 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
874 static const enum index next_ia_create_attr[] = {
875 INDIRECT_ACTION_CREATE_ID,
876 INDIRECT_ACTION_INGRESS,
877 INDIRECT_ACTION_EGRESS,
878 INDIRECT_ACTION_TRANSFER,
879 INDIRECT_ACTION_SPEC,
883 static const enum index next_dump_subcmd[] = {
889 static const enum index next_ia_subcmd[] = {
890 INDIRECT_ACTION_CREATE,
891 INDIRECT_ACTION_UPDATE,
892 INDIRECT_ACTION_DESTROY,
893 INDIRECT_ACTION_QUERY,
897 static const enum index next_vc_attr[] = {
909 static const enum index next_destroy_attr[] = {
915 static const enum index next_dump_attr[] = {
921 static const enum index next_list_attr[] = {
927 static const enum index next_aged_attr[] = {
933 static const enum index next_ia_destroy_attr[] = {
934 INDIRECT_ACTION_DESTROY_ID,
939 static const enum index item_param[] = {
948 static const enum index next_item[] = {
985 ITEM_ICMP6_ND_OPT_SLA_ETH,
986 ITEM_ICMP6_ND_OPT_TLA_ETH,
1007 static const enum index item_fuzzy[] = {
1013 static const enum index item_any[] = {
1019 static const enum index item_vf[] = {
1025 static const enum index item_phy_port[] = {
1026 ITEM_PHY_PORT_INDEX,
1031 static const enum index item_port_id[] = {
1037 static const enum index item_mark[] = {
1043 static const enum index item_raw[] = {
1053 static const enum index item_eth[] = {
1062 static const enum index item_vlan[] = {
1067 ITEM_VLAN_INNER_TYPE,
1068 ITEM_VLAN_HAS_MORE_VLAN,
1073 static const enum index item_ipv4[] = {
1077 ITEM_IPV4_FRAGMENT_OFFSET,
1086 static const enum index item_ipv6[] = {
1093 ITEM_IPV6_HAS_FRAG_EXT,
1098 static const enum index item_icmp[] = {
1107 static const enum index item_udp[] = {
1114 static const enum index item_tcp[] = {
1122 static const enum index item_sctp[] = {
1131 static const enum index item_vxlan[] = {
1133 ITEM_VXLAN_LAST_RSVD,
1138 static const enum index item_e_tag[] = {
1139 ITEM_E_TAG_GRP_ECID_B,
1144 static const enum index item_nvgre[] = {
1150 static const enum index item_mpls[] = {
1158 static const enum index item_gre[] = {
1160 ITEM_GRE_C_RSVD0_VER,
1168 static const enum index item_gre_key[] = {
1174 static const enum index item_gtp[] = {
1182 static const enum index item_geneve[] = {
1190 static const enum index item_vxlan_gpe[] = {
1196 static const enum index item_arp_eth_ipv4[] = {
1197 ITEM_ARP_ETH_IPV4_SHA,
1198 ITEM_ARP_ETH_IPV4_SPA,
1199 ITEM_ARP_ETH_IPV4_THA,
1200 ITEM_ARP_ETH_IPV4_TPA,
1205 static const enum index item_ipv6_ext[] = {
1206 ITEM_IPV6_EXT_NEXT_HDR,
1211 static const enum index item_ipv6_frag_ext[] = {
1212 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1213 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1214 ITEM_IPV6_FRAG_EXT_ID,
1219 static const enum index item_icmp6[] = {
1226 static const enum index item_icmp6_nd_ns[] = {
1227 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1232 static const enum index item_icmp6_nd_na[] = {
1233 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1238 static const enum index item_icmp6_nd_opt[] = {
1239 ITEM_ICMP6_ND_OPT_TYPE,
1244 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1245 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1250 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1251 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1256 static const enum index item_meta[] = {
1262 static const enum index item_gtp_psc[] = {
1269 static const enum index item_pppoed[] = {
1275 static const enum index item_pppoes[] = {
1281 static const enum index item_pppoe_proto_id[] = {
1286 static const enum index item_higig2[] = {
1287 ITEM_HIGIG2_CLASSIFICATION,
1293 static const enum index item_esp[] = {
1299 static const enum index item_ah[] = {
1305 static const enum index item_pfcp[] = {
1312 static const enum index next_set_raw[] = {
1318 static const enum index item_tag[] = {
1325 static const enum index item_l2tpv3oip[] = {
1326 ITEM_L2TPV3OIP_SESSION_ID,
1331 static const enum index item_ecpri[] = {
1337 static const enum index item_ecpri_common[] = {
1338 ITEM_ECPRI_COMMON_TYPE,
1342 static const enum index item_ecpri_common_type[] = {
1343 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1344 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1345 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1349 static const enum index item_geneve_opt[] = {
1350 ITEM_GENEVE_OPT_CLASS,
1351 ITEM_GENEVE_OPT_TYPE,
1352 ITEM_GENEVE_OPT_LENGTH,
1353 ITEM_GENEVE_OPT_DATA,
1358 static const enum index item_integrity[] = {
1359 ITEM_INTEGRITY_LEVEL,
1360 ITEM_INTEGRITY_VALUE,
1364 static const enum index item_integrity_lv[] = {
1365 ITEM_INTEGRITY_LEVEL,
1366 ITEM_INTEGRITY_VALUE,
1371 static const enum index next_action[] = {
1388 ACTION_OF_SET_MPLS_TTL,
1389 ACTION_OF_DEC_MPLS_TTL,
1390 ACTION_OF_SET_NW_TTL,
1391 ACTION_OF_DEC_NW_TTL,
1392 ACTION_OF_COPY_TTL_OUT,
1393 ACTION_OF_COPY_TTL_IN,
1395 ACTION_OF_PUSH_VLAN,
1396 ACTION_OF_SET_VLAN_VID,
1397 ACTION_OF_SET_VLAN_PCP,
1399 ACTION_OF_PUSH_MPLS,
1406 ACTION_MPLSOGRE_ENCAP,
1407 ACTION_MPLSOGRE_DECAP,
1408 ACTION_MPLSOUDP_ENCAP,
1409 ACTION_MPLSOUDP_DECAP,
1410 ACTION_SET_IPV4_SRC,
1411 ACTION_SET_IPV4_DST,
1412 ACTION_SET_IPV6_SRC,
1413 ACTION_SET_IPV6_DST,
1429 ACTION_SET_IPV4_DSCP,
1430 ACTION_SET_IPV6_DSCP,
1434 ACTION_MODIFY_FIELD,
1436 ACTION_CONNTRACK_UPDATE,
1440 static const enum index action_mark[] = {
1446 static const enum index action_queue[] = {
1452 static const enum index action_count[] = {
1454 ACTION_COUNT_SHARED,
1459 static const enum index action_rss[] = {
1470 static const enum index action_vf[] = {
1477 static const enum index action_phy_port[] = {
1478 ACTION_PHY_PORT_ORIGINAL,
1479 ACTION_PHY_PORT_INDEX,
1484 static const enum index action_port_id[] = {
1485 ACTION_PORT_ID_ORIGINAL,
1491 static const enum index action_meter[] = {
1497 static const enum index action_meter_color[] = {
1498 ACTION_METER_COLOR_TYPE,
1503 static const enum index action_of_set_mpls_ttl[] = {
1504 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1509 static const enum index action_of_set_nw_ttl[] = {
1510 ACTION_OF_SET_NW_TTL_NW_TTL,
1515 static const enum index action_of_push_vlan[] = {
1516 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1521 static const enum index action_of_set_vlan_vid[] = {
1522 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1527 static const enum index action_of_set_vlan_pcp[] = {
1528 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1533 static const enum index action_of_pop_mpls[] = {
1534 ACTION_OF_POP_MPLS_ETHERTYPE,
1539 static const enum index action_of_push_mpls[] = {
1540 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1545 static const enum index action_set_ipv4_src[] = {
1546 ACTION_SET_IPV4_SRC_IPV4_SRC,
1551 static const enum index action_set_mac_src[] = {
1552 ACTION_SET_MAC_SRC_MAC_SRC,
1557 static const enum index action_set_ipv4_dst[] = {
1558 ACTION_SET_IPV4_DST_IPV4_DST,
1563 static const enum index action_set_ipv6_src[] = {
1564 ACTION_SET_IPV6_SRC_IPV6_SRC,
1569 static const enum index action_set_ipv6_dst[] = {
1570 ACTION_SET_IPV6_DST_IPV6_DST,
1575 static const enum index action_set_tp_src[] = {
1576 ACTION_SET_TP_SRC_TP_SRC,
1581 static const enum index action_set_tp_dst[] = {
1582 ACTION_SET_TP_DST_TP_DST,
1587 static const enum index action_set_ttl[] = {
1593 static const enum index action_jump[] = {
1599 static const enum index action_set_mac_dst[] = {
1600 ACTION_SET_MAC_DST_MAC_DST,
1605 static const enum index action_inc_tcp_seq[] = {
1606 ACTION_INC_TCP_SEQ_VALUE,
1611 static const enum index action_dec_tcp_seq[] = {
1612 ACTION_DEC_TCP_SEQ_VALUE,
1617 static const enum index action_inc_tcp_ack[] = {
1618 ACTION_INC_TCP_ACK_VALUE,
1623 static const enum index action_dec_tcp_ack[] = {
1624 ACTION_DEC_TCP_ACK_VALUE,
1629 static const enum index action_raw_encap[] = {
1630 ACTION_RAW_ENCAP_INDEX,
1635 static const enum index action_raw_decap[] = {
1636 ACTION_RAW_DECAP_INDEX,
1641 static const enum index action_set_tag[] = {
1642 ACTION_SET_TAG_DATA,
1643 ACTION_SET_TAG_INDEX,
1644 ACTION_SET_TAG_MASK,
1649 static const enum index action_set_meta[] = {
1650 ACTION_SET_META_DATA,
1651 ACTION_SET_META_MASK,
1656 static const enum index action_set_ipv4_dscp[] = {
1657 ACTION_SET_IPV4_DSCP_VALUE,
1662 static const enum index action_set_ipv6_dscp[] = {
1663 ACTION_SET_IPV6_DSCP_VALUE,
1668 static const enum index action_age[] = {
1675 static const enum index action_sample[] = {
1677 ACTION_SAMPLE_RATIO,
1678 ACTION_SAMPLE_INDEX,
1683 static const enum index next_action_sample[] = {
1696 static const enum index action_modify_field_dst[] = {
1697 ACTION_MODIFY_FIELD_DST_LEVEL,
1698 ACTION_MODIFY_FIELD_DST_OFFSET,
1699 ACTION_MODIFY_FIELD_SRC_TYPE,
1703 static const enum index action_modify_field_src[] = {
1704 ACTION_MODIFY_FIELD_SRC_LEVEL,
1705 ACTION_MODIFY_FIELD_SRC_OFFSET,
1706 ACTION_MODIFY_FIELD_SRC_VALUE,
1707 ACTION_MODIFY_FIELD_WIDTH,
1711 static const enum index action_update_conntrack[] = {
1712 ACTION_CONNTRACK_UPDATE_DIR,
1713 ACTION_CONNTRACK_UPDATE_CTX,
1718 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1719 const char *, unsigned int,
1720 void *, unsigned int);
1721 static int parse_set_sample_action(struct context *, const struct token *,
1722 const char *, unsigned int,
1723 void *, unsigned int);
1724 static int parse_set_init(struct context *, const struct token *,
1725 const char *, unsigned int,
1726 void *, unsigned int);
1727 static int parse_init(struct context *, const struct token *,
1728 const char *, unsigned int,
1729 void *, unsigned int);
1730 static int parse_vc(struct context *, const struct token *,
1731 const char *, unsigned int,
1732 void *, unsigned int);
1733 static int parse_vc_spec(struct context *, const struct token *,
1734 const char *, unsigned int, void *, unsigned int);
1735 static int parse_vc_conf(struct context *, const struct token *,
1736 const char *, unsigned int, void *, unsigned int);
1737 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1738 const char *, unsigned int,
1739 void *, unsigned int);
1740 static int parse_vc_action_meter_color_type(struct context *,
1741 const struct token *,
1742 const char *, unsigned int, void *,
1744 static int parse_vc_action_rss(struct context *, const struct token *,
1745 const char *, unsigned int, void *,
1747 static int parse_vc_action_rss_func(struct context *, const struct token *,
1748 const char *, unsigned int, void *,
1750 static int parse_vc_action_rss_type(struct context *, const struct token *,
1751 const char *, unsigned int, void *,
1753 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1754 const char *, unsigned int, void *,
1756 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1757 const char *, unsigned int, void *,
1759 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1760 const char *, unsigned int, void *,
1762 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1763 const char *, unsigned int, void *,
1765 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1766 const char *, unsigned int, void *,
1768 static int parse_vc_action_mplsogre_encap(struct context *,
1769 const struct token *, const char *,
1770 unsigned int, void *, unsigned int);
1771 static int parse_vc_action_mplsogre_decap(struct context *,
1772 const struct token *, const char *,
1773 unsigned int, void *, unsigned int);
1774 static int parse_vc_action_mplsoudp_encap(struct context *,
1775 const struct token *, const char *,
1776 unsigned int, void *, unsigned int);
1777 static int parse_vc_action_mplsoudp_decap(struct context *,
1778 const struct token *, const char *,
1779 unsigned int, void *, unsigned int);
1780 static int parse_vc_action_raw_encap(struct context *,
1781 const struct token *, const char *,
1782 unsigned int, void *, unsigned int);
1783 static int parse_vc_action_raw_decap(struct context *,
1784 const struct token *, const char *,
1785 unsigned int, void *, unsigned int);
1786 static int parse_vc_action_raw_encap_index(struct context *,
1787 const struct token *, const char *,
1788 unsigned int, void *, unsigned int);
1789 static int parse_vc_action_raw_decap_index(struct context *,
1790 const struct token *, const char *,
1791 unsigned int, void *, unsigned int);
1792 static int parse_vc_action_set_meta(struct context *ctx,
1793 const struct token *token, const char *str,
1794 unsigned int len, void *buf,
1796 static int parse_vc_action_sample(struct context *ctx,
1797 const struct token *token, const char *str,
1798 unsigned int len, void *buf,
1801 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
1802 const char *str, unsigned int len, void *buf,
1805 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
1806 const char *str, unsigned int len, void *buf,
1809 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
1810 const char *str, unsigned int len, void *buf,
1813 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
1814 const char *str, unsigned int len, void *buf,
1816 static int parse_destroy(struct context *, const struct token *,
1817 const char *, unsigned int,
1818 void *, unsigned int);
1819 static int parse_flush(struct context *, const struct token *,
1820 const char *, unsigned int,
1821 void *, unsigned int);
1822 static int parse_dump(struct context *, const struct token *,
1823 const char *, unsigned int,
1824 void *, unsigned int);
1825 static int parse_query(struct context *, const struct token *,
1826 const char *, unsigned int,
1827 void *, unsigned int);
1828 static int parse_action(struct context *, const struct token *,
1829 const char *, unsigned int,
1830 void *, unsigned int);
1831 static int parse_list(struct context *, const struct token *,
1832 const char *, unsigned int,
1833 void *, unsigned int);
1834 static int parse_aged(struct context *, const struct token *,
1835 const char *, unsigned int,
1836 void *, unsigned int);
1837 static int parse_isolate(struct context *, const struct token *,
1838 const char *, unsigned int,
1839 void *, unsigned int);
1840 static int parse_tunnel(struct context *, const struct token *,
1841 const char *, unsigned int,
1842 void *, unsigned int);
1843 static int parse_int(struct context *, const struct token *,
1844 const char *, unsigned int,
1845 void *, unsigned int);
1846 static int parse_prefix(struct context *, const struct token *,
1847 const char *, unsigned int,
1848 void *, unsigned int);
1849 static int parse_boolean(struct context *, const struct token *,
1850 const char *, unsigned int,
1851 void *, unsigned int);
1852 static int parse_string(struct context *, const struct token *,
1853 const char *, unsigned int,
1854 void *, unsigned int);
1855 static int parse_hex(struct context *ctx, const struct token *token,
1856 const char *str, unsigned int len,
1857 void *buf, unsigned int size);
1858 static int parse_string0(struct context *, const struct token *,
1859 const char *, unsigned int,
1860 void *, unsigned int);
1861 static int parse_mac_addr(struct context *, const struct token *,
1862 const char *, unsigned int,
1863 void *, unsigned int);
1864 static int parse_ipv4_addr(struct context *, const struct token *,
1865 const char *, unsigned int,
1866 void *, unsigned int);
1867 static int parse_ipv6_addr(struct context *, const struct token *,
1868 const char *, unsigned int,
1869 void *, unsigned int);
1870 static int parse_port(struct context *, const struct token *,
1871 const char *, unsigned int,
1872 void *, unsigned int);
1873 static int parse_ia(struct context *, const struct token *,
1874 const char *, unsigned int,
1875 void *, unsigned int);
1876 static int parse_ia_destroy(struct context *ctx, const struct token *token,
1877 const char *str, unsigned int len,
1878 void *buf, unsigned int size);
1879 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
1880 const char *str, unsigned int len, void *buf,
1882 static int parse_mp(struct context *, const struct token *,
1883 const char *, unsigned int,
1884 void *, unsigned int);
1885 static int comp_none(struct context *, const struct token *,
1886 unsigned int, char *, unsigned int);
1887 static int comp_boolean(struct context *, const struct token *,
1888 unsigned int, char *, unsigned int);
1889 static int comp_action(struct context *, const struct token *,
1890 unsigned int, char *, unsigned int);
1891 static int comp_port(struct context *, const struct token *,
1892 unsigned int, char *, unsigned int);
1893 static int comp_rule_id(struct context *, const struct token *,
1894 unsigned int, char *, unsigned int);
1895 static int comp_vc_action_rss_type(struct context *, const struct token *,
1896 unsigned int, char *, unsigned int);
1897 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1898 unsigned int, char *, unsigned int);
1899 static int comp_set_raw_index(struct context *, const struct token *,
1900 unsigned int, char *, unsigned int);
1901 static int comp_set_sample_index(struct context *, const struct token *,
1902 unsigned int, char *, unsigned int);
1903 static int comp_set_modify_field_op(struct context *, const struct token *,
1904 unsigned int, char *, unsigned int);
1905 static int comp_set_modify_field_id(struct context *, const struct token *,
1906 unsigned int, char *, unsigned int);
1908 /** Token definitions. */
1909 static const struct token token_list[] = {
1910 /* Special tokens. */
1913 .help = "null entry, abused as the entry point",
1914 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
1919 .help = "command may end here",
1922 .name = "START_SET",
1923 .help = "null entry, abused as the entry point for set",
1924 .next = NEXT(NEXT_ENTRY(SET)),
1929 .help = "set command may end here",
1931 /* Common tokens. */
1932 [COMMON_INTEGER] = {
1935 .help = "integer value",
1939 [COMMON_UNSIGNED] = {
1940 .name = "{unsigned}",
1942 .help = "unsigned integer value",
1949 .help = "prefix length for bit-mask",
1950 .call = parse_prefix,
1953 [COMMON_BOOLEAN] = {
1954 .name = "{boolean}",
1956 .help = "any boolean value",
1957 .call = parse_boolean,
1958 .comp = comp_boolean,
1963 .help = "fixed string",
1964 .call = parse_string,
1970 .help = "fixed string",
1973 [COMMON_FILE_PATH] = {
1974 .name = "{file path}",
1976 .help = "file path",
1977 .call = parse_string0,
1980 [COMMON_MAC_ADDR] = {
1981 .name = "{MAC address}",
1983 .help = "standard MAC address notation",
1984 .call = parse_mac_addr,
1987 [COMMON_IPV4_ADDR] = {
1988 .name = "{IPv4 address}",
1989 .type = "IPV4 ADDRESS",
1990 .help = "standard IPv4 address notation",
1991 .call = parse_ipv4_addr,
1994 [COMMON_IPV6_ADDR] = {
1995 .name = "{IPv6 address}",
1996 .type = "IPV6 ADDRESS",
1997 .help = "standard IPv6 address notation",
1998 .call = parse_ipv6_addr,
2001 [COMMON_RULE_ID] = {
2002 .name = "{rule id}",
2004 .help = "rule identifier",
2006 .comp = comp_rule_id,
2008 [COMMON_PORT_ID] = {
2009 .name = "{port_id}",
2011 .help = "port identifier",
2015 [COMMON_GROUP_ID] = {
2016 .name = "{group_id}",
2018 .help = "group identifier",
2022 [COMMON_PRIORITY_LEVEL] = {
2025 .help = "priority level",
2029 [COMMON_INDIRECT_ACTION_ID] = {
2030 .name = "{indirect_action_id}",
2031 .type = "INDIRECT_ACTION_ID",
2032 .help = "indirect action id",
2036 [COMMON_POLICY_ID] = {
2037 .name = "{policy_id}",
2038 .type = "POLCIY_ID",
2039 .help = "policy id",
2043 /* Top-level command. */
2046 .type = "{command} {port_id} [{arg} [...]]",
2047 .help = "manage ingress/egress flow rules",
2048 .next = NEXT(NEXT_ENTRY
2062 /* Top-level command. */
2063 [INDIRECT_ACTION] = {
2064 .name = "indirect_action",
2065 .type = "{command} {port_id} [{arg} [...]]",
2066 .help = "manage indirect actions",
2067 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2068 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2071 /* Sub-level commands. */
2072 [INDIRECT_ACTION_CREATE] = {
2074 .help = "create indirect action",
2075 .next = NEXT(next_ia_create_attr),
2078 [INDIRECT_ACTION_UPDATE] = {
2080 .help = "update indirect action",
2081 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2082 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2083 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2086 [INDIRECT_ACTION_DESTROY] = {
2088 .help = "destroy indirect action",
2089 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2090 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2091 .call = parse_ia_destroy,
2093 [INDIRECT_ACTION_QUERY] = {
2095 .help = "query indirect action",
2096 .next = NEXT(NEXT_ENTRY(END),
2097 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2098 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2103 .help = "check whether a flow rule can be created",
2104 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2105 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2110 .help = "create a flow rule",
2111 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2112 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2117 .help = "destroy specific flow rules",
2118 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2119 NEXT_ENTRY(COMMON_PORT_ID)),
2120 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2121 .call = parse_destroy,
2125 .help = "destroy all flow rules",
2126 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2127 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2128 .call = parse_flush,
2132 .help = "dump single/all flow rules to file",
2133 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2134 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2139 .help = "query an existing flow rule",
2140 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
2141 NEXT_ENTRY(COMMON_RULE_ID),
2142 NEXT_ENTRY(COMMON_PORT_ID)),
2143 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
2144 ARGS_ENTRY(struct buffer, args.query.rule),
2145 ARGS_ENTRY(struct buffer, port)),
2146 .call = parse_query,
2150 .help = "list existing flow rules",
2151 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2152 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2157 .help = "list and destroy aged flows",
2158 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2159 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2164 .help = "restrict ingress traffic to the defined flow rules",
2165 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
2166 NEXT_ENTRY(COMMON_PORT_ID)),
2167 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
2168 ARGS_ENTRY(struct buffer, port)),
2169 .call = parse_isolate,
2173 .help = "new tunnel API",
2174 .next = NEXT(NEXT_ENTRY
2175 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
2176 .call = parse_tunnel,
2178 /* Tunnel arguments. */
2181 .help = "create new tunnel object",
2182 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
2183 NEXT_ENTRY(COMMON_PORT_ID)),
2184 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2185 .call = parse_tunnel,
2187 [TUNNEL_CREATE_TYPE] = {
2189 .help = "create new tunnel",
2190 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
2191 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
2192 .call = parse_tunnel,
2194 [TUNNEL_DESTROY] = {
2196 .help = "destroy tunel",
2197 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
2198 NEXT_ENTRY(COMMON_PORT_ID)),
2199 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2200 .call = parse_tunnel,
2202 [TUNNEL_DESTROY_ID] = {
2204 .help = "tunnel identifier to testroy",
2205 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
2206 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2207 .call = parse_tunnel,
2211 .help = "list existing tunnels",
2212 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2213 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2214 .call = parse_tunnel,
2216 /* Destroy arguments. */
2219 .help = "specify a rule identifier",
2220 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2221 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
2222 .call = parse_destroy,
2224 /* Dump arguments. */
2228 .next = NEXT(next_dump_attr),
2229 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
2234 .help = "dump one rule",
2235 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2236 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
2237 ARGS_ENTRY(struct buffer, args.dump.rule)),
2240 /* Query arguments. */
2244 .help = "action to query, must be part of the rule",
2245 .call = parse_action,
2246 .comp = comp_action,
2248 /* List arguments. */
2251 .help = "specify a group",
2252 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2253 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
2258 .help = "specify aged flows need be destroyed",
2262 /* Validate/create attributes. */
2265 .help = "specify a group",
2266 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2267 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
2272 .help = "specify a priority level",
2273 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2274 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
2279 .help = "affect rule to ingress",
2280 .next = NEXT(next_vc_attr),
2285 .help = "affect rule to egress",
2286 .next = NEXT(next_vc_attr),
2291 .help = "apply rule directly to endpoints found in pattern",
2292 .next = NEXT(next_vc_attr),
2296 .name = "tunnel_set",
2297 .help = "tunnel steer rule",
2298 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2299 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2302 [VC_TUNNEL_MATCH] = {
2303 .name = "tunnel_match",
2304 .help = "tunnel match rule",
2305 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2306 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2309 /* Validate/create pattern. */
2312 .help = "submit a list of pattern items",
2313 .next = NEXT(next_item),
2318 .help = "match value perfectly (with full bit-mask)",
2319 .call = parse_vc_spec,
2321 [ITEM_PARAM_SPEC] = {
2323 .help = "match value according to configured bit-mask",
2324 .call = parse_vc_spec,
2326 [ITEM_PARAM_LAST] = {
2328 .help = "specify upper bound to establish a range",
2329 .call = parse_vc_spec,
2331 [ITEM_PARAM_MASK] = {
2333 .help = "specify bit-mask with relevant bits set to one",
2334 .call = parse_vc_spec,
2336 [ITEM_PARAM_PREFIX] = {
2338 .help = "generate bit-mask from a prefix length",
2339 .call = parse_vc_spec,
2343 .help = "specify next pattern item",
2344 .next = NEXT(next_item),
2348 .help = "end list of pattern items",
2349 .priv = PRIV_ITEM(END, 0),
2350 .next = NEXT(NEXT_ENTRY(ACTIONS)),
2355 .help = "no-op pattern item",
2356 .priv = PRIV_ITEM(VOID, 0),
2357 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2362 .help = "perform actions when pattern does not match",
2363 .priv = PRIV_ITEM(INVERT, 0),
2364 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2369 .help = "match any protocol for the current layer",
2370 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
2371 .next = NEXT(item_any),
2376 .help = "number of layers covered",
2377 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2378 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
2382 .help = "match traffic from/to the physical function",
2383 .priv = PRIV_ITEM(PF, 0),
2384 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2389 .help = "match traffic from/to a virtual function ID",
2390 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
2391 .next = NEXT(item_vf),
2397 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2398 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
2402 .help = "match traffic from/to a specific physical port",
2403 .priv = PRIV_ITEM(PHY_PORT,
2404 sizeof(struct rte_flow_item_phy_port)),
2405 .next = NEXT(item_phy_port),
2408 [ITEM_PHY_PORT_INDEX] = {
2410 .help = "physical port index",
2411 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
2413 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
2417 .help = "match traffic from/to a given DPDK port ID",
2418 .priv = PRIV_ITEM(PORT_ID,
2419 sizeof(struct rte_flow_item_port_id)),
2420 .next = NEXT(item_port_id),
2423 [ITEM_PORT_ID_ID] = {
2425 .help = "DPDK port ID",
2426 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
2428 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
2432 .help = "match traffic against value set in previously matched rule",
2433 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
2434 .next = NEXT(item_mark),
2439 .help = "Integer value to match against",
2440 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
2442 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
2446 .help = "match an arbitrary byte string",
2447 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
2448 .next = NEXT(item_raw),
2451 [ITEM_RAW_RELATIVE] = {
2453 .help = "look for pattern after the previous item",
2454 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2455 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2458 [ITEM_RAW_SEARCH] = {
2460 .help = "search pattern from offset (see also limit)",
2461 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2462 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2465 [ITEM_RAW_OFFSET] = {
2467 .help = "absolute or relative offset for pattern",
2468 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
2469 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
2471 [ITEM_RAW_LIMIT] = {
2473 .help = "search area limit for start of pattern",
2474 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2475 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
2477 [ITEM_RAW_PATTERN] = {
2479 .help = "byte string to look for",
2480 .next = NEXT(item_raw,
2481 NEXT_ENTRY(COMMON_STRING),
2482 NEXT_ENTRY(ITEM_PARAM_IS,
2485 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2486 ARGS_ENTRY(struct rte_flow_item_raw, length),
2487 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2488 ITEM_RAW_PATTERN_SIZE)),
2492 .help = "match Ethernet header",
2493 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
2494 .next = NEXT(item_eth),
2499 .help = "destination MAC",
2500 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2501 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
2505 .help = "source MAC",
2506 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2507 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
2511 .help = "EtherType",
2512 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2513 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
2515 [ITEM_ETH_HAS_VLAN] = {
2517 .help = "packet header contains VLAN",
2518 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2519 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
2524 .help = "match 802.1Q/ad VLAN tag",
2525 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
2526 .next = NEXT(item_vlan),
2531 .help = "tag control information",
2532 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2534 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
2538 .help = "priority code point",
2539 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2541 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2546 .help = "drop eligible indicator",
2547 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2549 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2554 .help = "VLAN identifier",
2555 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2557 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2560 [ITEM_VLAN_INNER_TYPE] = {
2561 .name = "inner_type",
2562 .help = "inner EtherType",
2563 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2565 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2568 [ITEM_VLAN_HAS_MORE_VLAN] = {
2569 .name = "has_more_vlan",
2570 .help = "packet header contains another VLAN",
2571 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2573 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
2578 .help = "match IPv4 header",
2579 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
2580 .next = NEXT(item_ipv4),
2583 [ITEM_IPV4_VER_IHL] = {
2584 .name = "version_ihl",
2585 .help = "match header length",
2586 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2588 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
2593 .help = "type of service",
2594 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2596 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2597 hdr.type_of_service)),
2600 .name = "packet_id",
2601 .help = "fragment packet id",
2602 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2604 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2607 [ITEM_IPV4_FRAGMENT_OFFSET] = {
2608 .name = "fragment_offset",
2609 .help = "fragmentation flags and fragment offset",
2610 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2612 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2613 hdr.fragment_offset)),
2617 .help = "time to live",
2618 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2620 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2623 [ITEM_IPV4_PROTO] = {
2625 .help = "next protocol ID",
2626 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2628 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2629 hdr.next_proto_id)),
2633 .help = "source address",
2634 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2636 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2641 .help = "destination address",
2642 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2644 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2649 .help = "match IPv6 header",
2650 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
2651 .next = NEXT(item_ipv6),
2656 .help = "traffic class",
2657 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2659 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2661 "\x0f\xf0\x00\x00")),
2663 [ITEM_IPV6_FLOW] = {
2665 .help = "flow label",
2666 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2668 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2670 "\x00\x0f\xff\xff")),
2672 [ITEM_IPV6_PROTO] = {
2674 .help = "protocol (next header)",
2675 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2677 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2682 .help = "hop limit",
2683 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2685 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2690 .help = "source address",
2691 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2693 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2698 .help = "destination address",
2699 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2701 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2704 [ITEM_IPV6_HAS_FRAG_EXT] = {
2705 .name = "has_frag_ext",
2706 .help = "fragment packet attribute",
2707 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2709 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
2714 .help = "match ICMP header",
2715 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
2716 .next = NEXT(item_icmp),
2719 [ITEM_ICMP_TYPE] = {
2721 .help = "ICMP packet type",
2722 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2724 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2727 [ITEM_ICMP_CODE] = {
2729 .help = "ICMP packet code",
2730 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2732 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2735 [ITEM_ICMP_IDENT] = {
2737 .help = "ICMP packet identifier",
2738 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2740 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2745 .help = "ICMP packet sequence number",
2746 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2748 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2753 .help = "match UDP header",
2754 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
2755 .next = NEXT(item_udp),
2760 .help = "UDP source port",
2761 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
2763 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2768 .help = "UDP destination port",
2769 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2770 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2775 .help = "match TCP header",
2776 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
2777 .next = NEXT(item_tcp),
2782 .help = "TCP source port",
2783 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2784 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2789 .help = "TCP destination port",
2790 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2791 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2794 [ITEM_TCP_FLAGS] = {
2796 .help = "TCP flags",
2797 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2798 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2803 .help = "match SCTP header",
2804 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
2805 .next = NEXT(item_sctp),
2810 .help = "SCTP source port",
2811 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2813 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2818 .help = "SCTP destination port",
2819 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2821 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2826 .help = "validation tag",
2827 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2829 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2832 [ITEM_SCTP_CKSUM] = {
2835 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2837 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2842 .help = "match VXLAN header",
2843 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
2844 .next = NEXT(item_vxlan),
2847 [ITEM_VXLAN_VNI] = {
2849 .help = "VXLAN identifier",
2850 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
2852 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
2854 [ITEM_VXLAN_LAST_RSVD] = {
2855 .name = "last_rsvd",
2856 .help = "VXLAN last reserved bits",
2857 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
2859 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
2864 .help = "match E-Tag header",
2865 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
2866 .next = NEXT(item_e_tag),
2869 [ITEM_E_TAG_GRP_ECID_B] = {
2870 .name = "grp_ecid_b",
2871 .help = "GRP and E-CID base",
2872 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
2874 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
2880 .help = "match NVGRE header",
2881 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
2882 .next = NEXT(item_nvgre),
2885 [ITEM_NVGRE_TNI] = {
2887 .help = "virtual subnet ID",
2888 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
2890 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
2894 .help = "match MPLS header",
2895 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
2896 .next = NEXT(item_mpls),
2899 [ITEM_MPLS_LABEL] = {
2901 .help = "MPLS label",
2902 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2904 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2910 .help = "MPLS Traffic Class",
2911 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2913 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2919 .help = "MPLS Bottom-of-Stack",
2920 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2922 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2928 .help = "match GRE header",
2929 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
2930 .next = NEXT(item_gre),
2933 [ITEM_GRE_PROTO] = {
2935 .help = "GRE protocol type",
2936 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
2938 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2941 [ITEM_GRE_C_RSVD0_VER] = {
2942 .name = "c_rsvd0_ver",
2944 "checksum (1b), undefined (1b), key bit (1b),"
2945 " sequence number (1b), reserved 0 (9b),"
2947 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
2949 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2952 [ITEM_GRE_C_BIT] = {
2954 .help = "checksum bit (C)",
2955 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
2957 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2959 "\x80\x00\x00\x00")),
2961 [ITEM_GRE_S_BIT] = {
2963 .help = "sequence number bit (S)",
2964 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2965 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2967 "\x10\x00\x00\x00")),
2969 [ITEM_GRE_K_BIT] = {
2971 .help = "key bit (K)",
2972 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2973 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2975 "\x20\x00\x00\x00")),
2979 .help = "fuzzy pattern match, expect faster than default",
2980 .priv = PRIV_ITEM(FUZZY,
2981 sizeof(struct rte_flow_item_fuzzy)),
2982 .next = NEXT(item_fuzzy),
2985 [ITEM_FUZZY_THRESH] = {
2987 .help = "match accuracy threshold",
2988 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
2990 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
2995 .help = "match GTP header",
2996 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
2997 .next = NEXT(item_gtp),
3000 [ITEM_GTP_FLAGS] = {
3001 .name = "v_pt_rsv_flags",
3002 .help = "GTP flags",
3003 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3004 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3007 [ITEM_GTP_MSG_TYPE] = {
3009 .help = "GTP message type",
3010 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3011 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3015 .help = "tunnel endpoint identifier",
3016 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3017 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3021 .help = "match GTP header",
3022 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3023 .next = NEXT(item_gtp),
3028 .help = "match GTP header",
3029 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3030 .next = NEXT(item_gtp),
3035 .help = "match GENEVE header",
3036 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3037 .next = NEXT(item_geneve),
3040 [ITEM_GENEVE_VNI] = {
3042 .help = "virtual network identifier",
3043 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3045 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3047 [ITEM_GENEVE_PROTO] = {
3049 .help = "GENEVE protocol type",
3050 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3052 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3055 [ITEM_GENEVE_OPTLEN] = {
3057 .help = "GENEVE options length in dwords",
3058 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3060 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3061 ver_opt_len_o_c_rsvd0,
3064 [ITEM_VXLAN_GPE] = {
3065 .name = "vxlan-gpe",
3066 .help = "match VXLAN-GPE header",
3067 .priv = PRIV_ITEM(VXLAN_GPE,
3068 sizeof(struct rte_flow_item_vxlan_gpe)),
3069 .next = NEXT(item_vxlan_gpe),
3072 [ITEM_VXLAN_GPE_VNI] = {
3074 .help = "VXLAN-GPE identifier",
3075 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3077 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
3080 [ITEM_ARP_ETH_IPV4] = {
3081 .name = "arp_eth_ipv4",
3082 .help = "match ARP header for Ethernet/IPv4",
3083 .priv = PRIV_ITEM(ARP_ETH_IPV4,
3084 sizeof(struct rte_flow_item_arp_eth_ipv4)),
3085 .next = NEXT(item_arp_eth_ipv4),
3088 [ITEM_ARP_ETH_IPV4_SHA] = {
3090 .help = "sender hardware address",
3091 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3093 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3096 [ITEM_ARP_ETH_IPV4_SPA] = {
3098 .help = "sender IPv4 address",
3099 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3101 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3104 [ITEM_ARP_ETH_IPV4_THA] = {
3106 .help = "target hardware address",
3107 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3109 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3112 [ITEM_ARP_ETH_IPV4_TPA] = {
3114 .help = "target IPv4 address",
3115 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3117 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3122 .help = "match presence of any IPv6 extension header",
3123 .priv = PRIV_ITEM(IPV6_EXT,
3124 sizeof(struct rte_flow_item_ipv6_ext)),
3125 .next = NEXT(item_ipv6_ext),
3128 [ITEM_IPV6_EXT_NEXT_HDR] = {
3130 .help = "next header",
3131 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3133 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
3136 [ITEM_IPV6_FRAG_EXT] = {
3137 .name = "ipv6_frag_ext",
3138 .help = "match presence of IPv6 fragment extension header",
3139 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
3140 sizeof(struct rte_flow_item_ipv6_frag_ext)),
3141 .next = NEXT(item_ipv6_frag_ext),
3144 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
3146 .help = "next header",
3147 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3149 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
3152 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
3153 .name = "frag_data",
3154 .help = "fragment flags and offset",
3155 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3157 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3160 [ITEM_IPV6_FRAG_EXT_ID] = {
3161 .name = "packet_id",
3162 .help = "fragment packet id",
3163 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3165 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3170 .help = "match any ICMPv6 header",
3171 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
3172 .next = NEXT(item_icmp6),
3175 [ITEM_ICMP6_TYPE] = {
3177 .help = "ICMPv6 type",
3178 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3180 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3183 [ITEM_ICMP6_CODE] = {
3185 .help = "ICMPv6 code",
3186 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3188 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3191 [ITEM_ICMP6_ND_NS] = {
3192 .name = "icmp6_nd_ns",
3193 .help = "match ICMPv6 neighbor discovery solicitation",
3194 .priv = PRIV_ITEM(ICMP6_ND_NS,
3195 sizeof(struct rte_flow_item_icmp6_nd_ns)),
3196 .next = NEXT(item_icmp6_nd_ns),
3199 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
3200 .name = "target_addr",
3201 .help = "target address",
3202 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
3204 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
3207 [ITEM_ICMP6_ND_NA] = {
3208 .name = "icmp6_nd_na",
3209 .help = "match ICMPv6 neighbor discovery advertisement",
3210 .priv = PRIV_ITEM(ICMP6_ND_NA,
3211 sizeof(struct rte_flow_item_icmp6_nd_na)),
3212 .next = NEXT(item_icmp6_nd_na),
3215 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
3216 .name = "target_addr",
3217 .help = "target address",
3218 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
3220 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
3223 [ITEM_ICMP6_ND_OPT] = {
3224 .name = "icmp6_nd_opt",
3225 .help = "match presence of any ICMPv6 neighbor discovery"
3227 .priv = PRIV_ITEM(ICMP6_ND_OPT,
3228 sizeof(struct rte_flow_item_icmp6_nd_opt)),
3229 .next = NEXT(item_icmp6_nd_opt),
3232 [ITEM_ICMP6_ND_OPT_TYPE] = {
3234 .help = "ND option type",
3235 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3237 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
3240 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
3241 .name = "icmp6_nd_opt_sla_eth",
3242 .help = "match ICMPv6 neighbor discovery source Ethernet"
3243 " link-layer address option",
3245 (ICMP6_ND_OPT_SLA_ETH,
3246 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
3247 .next = NEXT(item_icmp6_nd_opt_sla_eth),
3250 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
3252 .help = "source Ethernet LLA",
3253 .next = NEXT(item_icmp6_nd_opt_sla_eth,
3254 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3255 .args = ARGS(ARGS_ENTRY_HTON
3256 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
3258 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
3259 .name = "icmp6_nd_opt_tla_eth",
3260 .help = "match ICMPv6 neighbor discovery target Ethernet"
3261 " link-layer address option",
3263 (ICMP6_ND_OPT_TLA_ETH,
3264 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
3265 .next = NEXT(item_icmp6_nd_opt_tla_eth),
3268 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
3270 .help = "target Ethernet LLA",
3271 .next = NEXT(item_icmp6_nd_opt_tla_eth,
3272 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3273 .args = ARGS(ARGS_ENTRY_HTON
3274 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
3278 .help = "match metadata header",
3279 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
3280 .next = NEXT(item_meta),
3283 [ITEM_META_DATA] = {
3285 .help = "metadata value",
3286 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
3288 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
3289 data, "\xff\xff\xff\xff")),
3293 .help = "match GRE key",
3294 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
3295 .next = NEXT(item_gre_key),
3298 [ITEM_GRE_KEY_VALUE] = {
3300 .help = "key value",
3301 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
3303 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3307 .help = "match GTP extension header with type 0x85",
3308 .priv = PRIV_ITEM(GTP_PSC,
3309 sizeof(struct rte_flow_item_gtp_psc)),
3310 .next = NEXT(item_gtp_psc),
3313 [ITEM_GTP_PSC_QFI] = {
3315 .help = "QoS flow identifier",
3316 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3318 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3321 [ITEM_GTP_PSC_PDU_T] = {
3324 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3326 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3331 .help = "match PPPoE session header",
3332 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
3333 .next = NEXT(item_pppoes),
3338 .help = "match PPPoE discovery header",
3339 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
3340 .next = NEXT(item_pppoed),
3343 [ITEM_PPPOE_SEID] = {
3345 .help = "session identifier",
3346 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
3348 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
3351 [ITEM_PPPOE_PROTO_ID] = {
3352 .name = "pppoe_proto_id",
3353 .help = "match PPPoE session protocol identifier",
3354 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
3355 sizeof(struct rte_flow_item_pppoe_proto_id)),
3356 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
3358 .args = ARGS(ARGS_ENTRY_HTON
3359 (struct rte_flow_item_pppoe_proto_id, proto_id)),
3364 .help = "matches higig2 header",
3365 .priv = PRIV_ITEM(HIGIG2,
3366 sizeof(struct rte_flow_item_higig2_hdr)),
3367 .next = NEXT(item_higig2),
3370 [ITEM_HIGIG2_CLASSIFICATION] = {
3371 .name = "classification",
3372 .help = "matches classification of higig2 header",
3373 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3375 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3376 hdr.ppt1.classification)),
3378 [ITEM_HIGIG2_VID] = {
3380 .help = "matches vid of higig2 header",
3381 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3383 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3388 .help = "match tag value",
3389 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
3390 .next = NEXT(item_tag),
3395 .help = "tag value to match",
3396 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3397 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
3399 [ITEM_TAG_INDEX] = {
3401 .help = "index of tag array to match",
3402 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3403 NEXT_ENTRY(ITEM_PARAM_IS)),
3404 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
3406 [ITEM_L2TPV3OIP] = {
3407 .name = "l2tpv3oip",
3408 .help = "match L2TPv3 over IP header",
3409 .priv = PRIV_ITEM(L2TPV3OIP,
3410 sizeof(struct rte_flow_item_l2tpv3oip)),
3411 .next = NEXT(item_l2tpv3oip),
3414 [ITEM_L2TPV3OIP_SESSION_ID] = {
3415 .name = "session_id",
3416 .help = "session identifier",
3417 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
3419 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
3424 .help = "match ESP header",
3425 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
3426 .next = NEXT(item_esp),
3431 .help = "security policy index",
3432 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3433 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
3438 .help = "match AH header",
3439 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
3440 .next = NEXT(item_ah),
3445 .help = "security parameters index",
3446 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3447 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
3451 .help = "match pfcp header",
3452 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
3453 .next = NEXT(item_pfcp),
3456 [ITEM_PFCP_S_FIELD] = {
3459 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3461 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
3464 [ITEM_PFCP_SEID] = {
3466 .help = "session endpoint identifier",
3467 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3469 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
3473 .help = "match eCPRI header",
3474 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
3475 .next = NEXT(item_ecpri),
3478 [ITEM_ECPRI_COMMON] = {
3480 .help = "eCPRI common header",
3481 .next = NEXT(item_ecpri_common),
3483 [ITEM_ECPRI_COMMON_TYPE] = {
3485 .help = "type of common header",
3486 .next = NEXT(item_ecpri_common_type),
3487 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
3489 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
3491 .help = "Type #0: IQ Data",
3492 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3494 .call = parse_vc_item_ecpri_type,
3496 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
3498 .help = "Physical Channel ID",
3499 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3500 ITEM_ECPRI_COMMON, ITEM_NEXT),
3501 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3502 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3505 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
3507 .help = "Type #2: Real-Time Control Data",
3508 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3510 .call = parse_vc_item_ecpri_type,
3512 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
3514 .help = "Real-Time Control Data ID",
3515 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3516 ITEM_ECPRI_COMMON, ITEM_NEXT),
3517 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3518 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3521 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
3522 .name = "delay_measure",
3523 .help = "Type #5: One-Way Delay Measurement",
3524 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3526 .call = parse_vc_item_ecpri_type,
3528 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
3530 .help = "Measurement ID",
3531 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3532 ITEM_ECPRI_COMMON, ITEM_NEXT),
3533 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3534 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3537 [ITEM_GENEVE_OPT] = {
3538 .name = "geneve-opt",
3539 .help = "GENEVE header option",
3540 .priv = PRIV_ITEM(GENEVE_OPT,
3541 sizeof(struct rte_flow_item_geneve_opt) +
3542 ITEM_GENEVE_OPT_DATA_SIZE),
3543 .next = NEXT(item_geneve_opt),
3546 [ITEM_GENEVE_OPT_CLASS] = {
3548 .help = "GENEVE option class",
3549 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3551 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
3554 [ITEM_GENEVE_OPT_TYPE] = {
3556 .help = "GENEVE option type",
3557 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3559 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
3562 [ITEM_GENEVE_OPT_LENGTH] = {
3564 .help = "GENEVE option data length (in 32b words)",
3565 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3567 .args = ARGS(ARGS_ENTRY_BOUNDED(
3568 struct rte_flow_item_geneve_opt, option_len,
3571 [ITEM_GENEVE_OPT_DATA] = {
3573 .help = "GENEVE option data pattern",
3574 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
3576 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
3577 ARGS_ENTRY_ARB(0, 0),
3579 (sizeof(struct rte_flow_item_geneve_opt),
3580 ITEM_GENEVE_OPT_DATA_SIZE)),
3582 [ITEM_INTEGRITY] = {
3583 .name = "integrity",
3584 .help = "match packet integrity",
3585 .priv = PRIV_ITEM(INTEGRITY,
3586 sizeof(struct rte_flow_item_integrity)),
3587 .next = NEXT(item_integrity),
3590 [ITEM_INTEGRITY_LEVEL] = {
3592 .help = "integrity level",
3593 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3595 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
3597 [ITEM_INTEGRITY_VALUE] = {
3599 .help = "integrity value",
3600 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3602 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
3604 [ITEM_CONNTRACK] = {
3605 .name = "conntrack",
3606 .help = "conntrack state",
3607 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
3609 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
3611 /* Validate/create actions. */
3614 .help = "submit a list of associated actions",
3615 .next = NEXT(next_action),
3620 .help = "specify next action",
3621 .next = NEXT(next_action),
3625 .help = "end list of actions",
3626 .priv = PRIV_ACTION(END, 0),
3631 .help = "no-op action",
3632 .priv = PRIV_ACTION(VOID, 0),
3633 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3636 [ACTION_PASSTHRU] = {
3638 .help = "let subsequent rule process matched packets",
3639 .priv = PRIV_ACTION(PASSTHRU, 0),
3640 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3645 .help = "redirect traffic to a given group",
3646 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
3647 .next = NEXT(action_jump),
3650 [ACTION_JUMP_GROUP] = {
3652 .help = "group to redirect traffic to",
3653 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
3654 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
3655 .call = parse_vc_conf,
3659 .help = "attach 32 bit value to packets",
3660 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
3661 .next = NEXT(action_mark),
3664 [ACTION_MARK_ID] = {
3666 .help = "32 bit value to return with packets",
3667 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
3668 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
3669 .call = parse_vc_conf,
3673 .help = "flag packets",
3674 .priv = PRIV_ACTION(FLAG, 0),
3675 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3680 .help = "assign packets to a given queue index",
3681 .priv = PRIV_ACTION(QUEUE,
3682 sizeof(struct rte_flow_action_queue)),
3683 .next = NEXT(action_queue),
3686 [ACTION_QUEUE_INDEX] = {
3688 .help = "queue index to use",
3689 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
3690 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
3691 .call = parse_vc_conf,
3695 .help = "drop packets (note: passthru has priority)",
3696 .priv = PRIV_ACTION(DROP, 0),
3697 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3702 .help = "enable counters for this rule",
3703 .priv = PRIV_ACTION(COUNT,
3704 sizeof(struct rte_flow_action_count)),
3705 .next = NEXT(action_count),
3708 [ACTION_COUNT_ID] = {
3709 .name = "identifier",
3710 .help = "counter identifier to use",
3711 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
3712 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
3713 .call = parse_vc_conf,
3715 [ACTION_COUNT_SHARED] = {
3717 .help = "shared counter",
3718 .next = NEXT(action_count, NEXT_ENTRY(COMMON_BOOLEAN)),
3719 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
3721 .call = parse_vc_conf,
3725 .help = "spread packets among several queues",
3726 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
3727 .next = NEXT(action_rss),
3728 .call = parse_vc_action_rss,
3730 [ACTION_RSS_FUNC] = {
3732 .help = "RSS hash function to apply",
3733 .next = NEXT(action_rss,
3734 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
3735 ACTION_RSS_FUNC_TOEPLITZ,
3736 ACTION_RSS_FUNC_SIMPLE_XOR,
3737 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
3739 [ACTION_RSS_FUNC_DEFAULT] = {
3741 .help = "default hash function",
3742 .call = parse_vc_action_rss_func,
3744 [ACTION_RSS_FUNC_TOEPLITZ] = {
3746 .help = "Toeplitz hash function",
3747 .call = parse_vc_action_rss_func,
3749 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
3750 .name = "simple_xor",
3751 .help = "simple XOR hash function",
3752 .call = parse_vc_action_rss_func,
3754 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
3755 .name = "symmetric_toeplitz",
3756 .help = "Symmetric Toeplitz hash function",
3757 .call = parse_vc_action_rss_func,
3759 [ACTION_RSS_LEVEL] = {
3761 .help = "encapsulation level for \"types\"",
3762 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
3763 .args = ARGS(ARGS_ENTRY_ARB
3764 (offsetof(struct action_rss_data, conf) +
3765 offsetof(struct rte_flow_action_rss, level),
3766 sizeof(((struct rte_flow_action_rss *)0)->
3769 [ACTION_RSS_TYPES] = {
3771 .help = "specific RSS hash types",
3772 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
3774 [ACTION_RSS_TYPE] = {
3776 .help = "RSS hash type",
3777 .call = parse_vc_action_rss_type,
3778 .comp = comp_vc_action_rss_type,
3780 [ACTION_RSS_KEY] = {
3782 .help = "RSS hash key",
3783 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
3784 .args = ARGS(ARGS_ENTRY_ARB
3785 (offsetof(struct action_rss_data, conf) +
3786 offsetof(struct rte_flow_action_rss, key),
3787 sizeof(((struct rte_flow_action_rss *)0)->key)),
3789 (offsetof(struct action_rss_data, conf) +
3790 offsetof(struct rte_flow_action_rss, key_len),
3791 sizeof(((struct rte_flow_action_rss *)0)->
3793 ARGS_ENTRY(struct action_rss_data, key)),
3795 [ACTION_RSS_KEY_LEN] = {
3797 .help = "RSS hash key length in bytes",
3798 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
3799 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3800 (offsetof(struct action_rss_data, conf) +
3801 offsetof(struct rte_flow_action_rss, key_len),
3802 sizeof(((struct rte_flow_action_rss *)0)->
3805 RSS_HASH_KEY_LENGTH)),
3807 [ACTION_RSS_QUEUES] = {
3809 .help = "queue indices to use",
3810 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
3811 .call = parse_vc_conf,
3813 [ACTION_RSS_QUEUE] = {
3815 .help = "queue index",
3816 .call = parse_vc_action_rss_queue,
3817 .comp = comp_vc_action_rss_queue,
3821 .help = "direct traffic to physical function",
3822 .priv = PRIV_ACTION(PF, 0),
3823 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3828 .help = "direct traffic to a virtual function ID",
3829 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
3830 .next = NEXT(action_vf),
3833 [ACTION_VF_ORIGINAL] = {
3835 .help = "use original VF ID if possible",
3836 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
3837 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
3839 .call = parse_vc_conf,
3844 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
3845 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
3846 .call = parse_vc_conf,
3848 [ACTION_PHY_PORT] = {
3850 .help = "direct packets to physical port index",
3851 .priv = PRIV_ACTION(PHY_PORT,
3852 sizeof(struct rte_flow_action_phy_port)),
3853 .next = NEXT(action_phy_port),
3856 [ACTION_PHY_PORT_ORIGINAL] = {
3858 .help = "use original port index if possible",
3859 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
3860 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
3862 .call = parse_vc_conf,
3864 [ACTION_PHY_PORT_INDEX] = {
3866 .help = "physical port index",
3867 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
3868 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
3870 .call = parse_vc_conf,
3872 [ACTION_PORT_ID] = {
3874 .help = "direct matching traffic to a given DPDK port ID",
3875 .priv = PRIV_ACTION(PORT_ID,
3876 sizeof(struct rte_flow_action_port_id)),
3877 .next = NEXT(action_port_id),
3880 [ACTION_PORT_ID_ORIGINAL] = {
3882 .help = "use original DPDK port ID if possible",
3883 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
3884 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
3886 .call = parse_vc_conf,
3888 [ACTION_PORT_ID_ID] = {
3890 .help = "DPDK port ID",
3891 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
3892 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
3893 .call = parse_vc_conf,
3897 .help = "meter the directed packets at given id",
3898 .priv = PRIV_ACTION(METER,
3899 sizeof(struct rte_flow_action_meter)),
3900 .next = NEXT(action_meter),
3903 [ACTION_METER_COLOR] = {
3905 .help = "meter color for the packets",
3906 .priv = PRIV_ACTION(METER_COLOR,
3907 sizeof(struct rte_flow_action_meter_color)),
3908 .next = NEXT(action_meter_color),
3911 [ACTION_METER_COLOR_TYPE] = {
3913 .help = "specific meter color",
3914 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
3915 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
3916 ACTION_METER_COLOR_YELLOW,
3917 ACTION_METER_COLOR_RED)),
3919 [ACTION_METER_COLOR_GREEN] = {
3921 .help = "meter color green",
3922 .call = parse_vc_action_meter_color_type,
3924 [ACTION_METER_COLOR_YELLOW] = {
3926 .help = "meter color yellow",
3927 .call = parse_vc_action_meter_color_type,
3929 [ACTION_METER_COLOR_RED] = {
3931 .help = "meter color red",
3932 .call = parse_vc_action_meter_color_type,
3934 [ACTION_METER_ID] = {
3936 .help = "meter id to use",
3937 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
3938 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
3939 .call = parse_vc_conf,
3941 [ACTION_OF_SET_MPLS_TTL] = {
3942 .name = "of_set_mpls_ttl",
3943 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
3946 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
3947 .next = NEXT(action_of_set_mpls_ttl),
3950 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
3953 .next = NEXT(action_of_set_mpls_ttl,
3954 NEXT_ENTRY(COMMON_UNSIGNED)),
3955 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
3957 .call = parse_vc_conf,
3959 [ACTION_OF_DEC_MPLS_TTL] = {
3960 .name = "of_dec_mpls_ttl",
3961 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
3962 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
3963 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3966 [ACTION_OF_SET_NW_TTL] = {
3967 .name = "of_set_nw_ttl",
3968 .help = "OpenFlow's OFPAT_SET_NW_TTL",
3971 sizeof(struct rte_flow_action_of_set_nw_ttl)),
3972 .next = NEXT(action_of_set_nw_ttl),
3975 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
3978 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
3979 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
3981 .call = parse_vc_conf,
3983 [ACTION_OF_DEC_NW_TTL] = {
3984 .name = "of_dec_nw_ttl",
3985 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
3986 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
3987 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3990 [ACTION_OF_COPY_TTL_OUT] = {
3991 .name = "of_copy_ttl_out",
3992 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
3993 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
3994 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3997 [ACTION_OF_COPY_TTL_IN] = {
3998 .name = "of_copy_ttl_in",
3999 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
4000 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
4001 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4004 [ACTION_OF_POP_VLAN] = {
4005 .name = "of_pop_vlan",
4006 .help = "OpenFlow's OFPAT_POP_VLAN",
4007 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
4008 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4011 [ACTION_OF_PUSH_VLAN] = {
4012 .name = "of_push_vlan",
4013 .help = "OpenFlow's OFPAT_PUSH_VLAN",
4016 sizeof(struct rte_flow_action_of_push_vlan)),
4017 .next = NEXT(action_of_push_vlan),
4020 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
4021 .name = "ethertype",
4022 .help = "EtherType",
4023 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
4024 .args = ARGS(ARGS_ENTRY_HTON
4025 (struct rte_flow_action_of_push_vlan,
4027 .call = parse_vc_conf,
4029 [ACTION_OF_SET_VLAN_VID] = {
4030 .name = "of_set_vlan_vid",
4031 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
4034 sizeof(struct rte_flow_action_of_set_vlan_vid)),
4035 .next = NEXT(action_of_set_vlan_vid),
4038 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
4041 .next = NEXT(action_of_set_vlan_vid,
4042 NEXT_ENTRY(COMMON_UNSIGNED)),
4043 .args = ARGS(ARGS_ENTRY_HTON
4044 (struct rte_flow_action_of_set_vlan_vid,
4046 .call = parse_vc_conf,
4048 [ACTION_OF_SET_VLAN_PCP] = {
4049 .name = "of_set_vlan_pcp",
4050 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
4053 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
4054 .next = NEXT(action_of_set_vlan_pcp),
4057 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
4059 .help = "VLAN priority",
4060 .next = NEXT(action_of_set_vlan_pcp,
4061 NEXT_ENTRY(COMMON_UNSIGNED)),
4062 .args = ARGS(ARGS_ENTRY_HTON
4063 (struct rte_flow_action_of_set_vlan_pcp,
4065 .call = parse_vc_conf,
4067 [ACTION_OF_POP_MPLS] = {
4068 .name = "of_pop_mpls",
4069 .help = "OpenFlow's OFPAT_POP_MPLS",
4070 .priv = PRIV_ACTION(OF_POP_MPLS,
4071 sizeof(struct rte_flow_action_of_pop_mpls)),
4072 .next = NEXT(action_of_pop_mpls),
4075 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
4076 .name = "ethertype",
4077 .help = "EtherType",
4078 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4079 .args = ARGS(ARGS_ENTRY_HTON
4080 (struct rte_flow_action_of_pop_mpls,
4082 .call = parse_vc_conf,
4084 [ACTION_OF_PUSH_MPLS] = {
4085 .name = "of_push_mpls",
4086 .help = "OpenFlow's OFPAT_PUSH_MPLS",
4089 sizeof(struct rte_flow_action_of_push_mpls)),
4090 .next = NEXT(action_of_push_mpls),
4093 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
4094 .name = "ethertype",
4095 .help = "EtherType",
4096 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4097 .args = ARGS(ARGS_ENTRY_HTON
4098 (struct rte_flow_action_of_push_mpls,
4100 .call = parse_vc_conf,
4102 [ACTION_VXLAN_ENCAP] = {
4103 .name = "vxlan_encap",
4104 .help = "VXLAN encapsulation, uses configuration set by \"set"
4106 .priv = PRIV_ACTION(VXLAN_ENCAP,
4107 sizeof(struct action_vxlan_encap_data)),
4108 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4109 .call = parse_vc_action_vxlan_encap,
4111 [ACTION_VXLAN_DECAP] = {
4112 .name = "vxlan_decap",
4113 .help = "Performs a decapsulation action by stripping all"
4114 " headers of the VXLAN tunnel network overlay from the"
4116 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
4117 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4120 [ACTION_NVGRE_ENCAP] = {
4121 .name = "nvgre_encap",
4122 .help = "NVGRE encapsulation, uses configuration set by \"set"
4124 .priv = PRIV_ACTION(NVGRE_ENCAP,
4125 sizeof(struct action_nvgre_encap_data)),
4126 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4127 .call = parse_vc_action_nvgre_encap,
4129 [ACTION_NVGRE_DECAP] = {
4130 .name = "nvgre_decap",
4131 .help = "Performs a decapsulation action by stripping all"
4132 " headers of the NVGRE tunnel network overlay from the"
4134 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
4135 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4138 [ACTION_L2_ENCAP] = {
4140 .help = "l2 encap, uses configuration set by"
4141 " \"set l2_encap\"",
4142 .priv = PRIV_ACTION(RAW_ENCAP,
4143 sizeof(struct action_raw_encap_data)),
4144 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4145 .call = parse_vc_action_l2_encap,
4147 [ACTION_L2_DECAP] = {
4149 .help = "l2 decap, uses configuration set by"
4150 " \"set l2_decap\"",
4151 .priv = PRIV_ACTION(RAW_DECAP,
4152 sizeof(struct action_raw_decap_data)),
4153 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4154 .call = parse_vc_action_l2_decap,
4156 [ACTION_MPLSOGRE_ENCAP] = {
4157 .name = "mplsogre_encap",
4158 .help = "mplsogre encapsulation, uses configuration set by"
4159 " \"set mplsogre_encap\"",
4160 .priv = PRIV_ACTION(RAW_ENCAP,
4161 sizeof(struct action_raw_encap_data)),
4162 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4163 .call = parse_vc_action_mplsogre_encap,
4165 [ACTION_MPLSOGRE_DECAP] = {
4166 .name = "mplsogre_decap",
4167 .help = "mplsogre decapsulation, uses configuration set by"
4168 " \"set mplsogre_decap\"",
4169 .priv = PRIV_ACTION(RAW_DECAP,
4170 sizeof(struct action_raw_decap_data)),
4171 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4172 .call = parse_vc_action_mplsogre_decap,
4174 [ACTION_MPLSOUDP_ENCAP] = {
4175 .name = "mplsoudp_encap",
4176 .help = "mplsoudp encapsulation, uses configuration set by"
4177 " \"set mplsoudp_encap\"",
4178 .priv = PRIV_ACTION(RAW_ENCAP,
4179 sizeof(struct action_raw_encap_data)),
4180 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4181 .call = parse_vc_action_mplsoudp_encap,
4183 [ACTION_MPLSOUDP_DECAP] = {
4184 .name = "mplsoudp_decap",
4185 .help = "mplsoudp decapsulation, uses configuration set by"
4186 " \"set mplsoudp_decap\"",
4187 .priv = PRIV_ACTION(RAW_DECAP,
4188 sizeof(struct action_raw_decap_data)),
4189 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4190 .call = parse_vc_action_mplsoudp_decap,
4192 [ACTION_SET_IPV4_SRC] = {
4193 .name = "set_ipv4_src",
4194 .help = "Set a new IPv4 source address in the outermost"
4196 .priv = PRIV_ACTION(SET_IPV4_SRC,
4197 sizeof(struct rte_flow_action_set_ipv4)),
4198 .next = NEXT(action_set_ipv4_src),
4201 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
4202 .name = "ipv4_addr",
4203 .help = "new IPv4 source address to set",
4204 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4205 .args = ARGS(ARGS_ENTRY_HTON
4206 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4207 .call = parse_vc_conf,
4209 [ACTION_SET_IPV4_DST] = {
4210 .name = "set_ipv4_dst",
4211 .help = "Set a new IPv4 destination address in the outermost"
4213 .priv = PRIV_ACTION(SET_IPV4_DST,
4214 sizeof(struct rte_flow_action_set_ipv4)),
4215 .next = NEXT(action_set_ipv4_dst),
4218 [ACTION_SET_IPV4_DST_IPV4_DST] = {
4219 .name = "ipv4_addr",
4220 .help = "new IPv4 destination address to set",
4221 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4222 .args = ARGS(ARGS_ENTRY_HTON
4223 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4224 .call = parse_vc_conf,
4226 [ACTION_SET_IPV6_SRC] = {
4227 .name = "set_ipv6_src",
4228 .help = "Set a new IPv6 source address in the outermost"
4230 .priv = PRIV_ACTION(SET_IPV6_SRC,
4231 sizeof(struct rte_flow_action_set_ipv6)),
4232 .next = NEXT(action_set_ipv6_src),
4235 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
4236 .name = "ipv6_addr",
4237 .help = "new IPv6 source address to set",
4238 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4239 .args = ARGS(ARGS_ENTRY_HTON
4240 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4241 .call = parse_vc_conf,
4243 [ACTION_SET_IPV6_DST] = {
4244 .name = "set_ipv6_dst",
4245 .help = "Set a new IPv6 destination address in the outermost"
4247 .priv = PRIV_ACTION(SET_IPV6_DST,
4248 sizeof(struct rte_flow_action_set_ipv6)),
4249 .next = NEXT(action_set_ipv6_dst),
4252 [ACTION_SET_IPV6_DST_IPV6_DST] = {
4253 .name = "ipv6_addr",
4254 .help = "new IPv6 destination address to set",
4255 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4256 .args = ARGS(ARGS_ENTRY_HTON
4257 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4258 .call = parse_vc_conf,
4260 [ACTION_SET_TP_SRC] = {
4261 .name = "set_tp_src",
4262 .help = "set a new source port number in the outermost"
4264 .priv = PRIV_ACTION(SET_TP_SRC,
4265 sizeof(struct rte_flow_action_set_tp)),
4266 .next = NEXT(action_set_tp_src),
4269 [ACTION_SET_TP_SRC_TP_SRC] = {
4271 .help = "new source port number to set",
4272 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
4273 .args = ARGS(ARGS_ENTRY_HTON
4274 (struct rte_flow_action_set_tp, port)),
4275 .call = parse_vc_conf,
4277 [ACTION_SET_TP_DST] = {
4278 .name = "set_tp_dst",
4279 .help = "set a new destination port number in the outermost"
4281 .priv = PRIV_ACTION(SET_TP_DST,
4282 sizeof(struct rte_flow_action_set_tp)),
4283 .next = NEXT(action_set_tp_dst),
4286 [ACTION_SET_TP_DST_TP_DST] = {
4288 .help = "new destination port number to set",
4289 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
4290 .args = ARGS(ARGS_ENTRY_HTON
4291 (struct rte_flow_action_set_tp, port)),
4292 .call = parse_vc_conf,
4294 [ACTION_MAC_SWAP] = {
4296 .help = "Swap the source and destination MAC addresses"
4297 " in the outermost Ethernet header",
4298 .priv = PRIV_ACTION(MAC_SWAP, 0),
4299 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4302 [ACTION_DEC_TTL] = {
4304 .help = "decrease network TTL if available",
4305 .priv = PRIV_ACTION(DEC_TTL, 0),
4306 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4309 [ACTION_SET_TTL] = {
4311 .help = "set ttl value",
4312 .priv = PRIV_ACTION(SET_TTL,
4313 sizeof(struct rte_flow_action_set_ttl)),
4314 .next = NEXT(action_set_ttl),
4317 [ACTION_SET_TTL_TTL] = {
4318 .name = "ttl_value",
4319 .help = "new ttl value to set",
4320 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4321 .args = ARGS(ARGS_ENTRY_HTON
4322 (struct rte_flow_action_set_ttl, ttl_value)),
4323 .call = parse_vc_conf,
4325 [ACTION_SET_MAC_SRC] = {
4326 .name = "set_mac_src",
4327 .help = "set source mac address",
4328 .priv = PRIV_ACTION(SET_MAC_SRC,
4329 sizeof(struct rte_flow_action_set_mac)),
4330 .next = NEXT(action_set_mac_src),
4333 [ACTION_SET_MAC_SRC_MAC_SRC] = {
4335 .help = "new source mac address",
4336 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
4337 .args = ARGS(ARGS_ENTRY_HTON
4338 (struct rte_flow_action_set_mac, mac_addr)),
4339 .call = parse_vc_conf,
4341 [ACTION_SET_MAC_DST] = {
4342 .name = "set_mac_dst",
4343 .help = "set destination mac address",
4344 .priv = PRIV_ACTION(SET_MAC_DST,
4345 sizeof(struct rte_flow_action_set_mac)),
4346 .next = NEXT(action_set_mac_dst),
4349 [ACTION_SET_MAC_DST_MAC_DST] = {
4351 .help = "new destination mac address to set",
4352 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
4353 .args = ARGS(ARGS_ENTRY_HTON
4354 (struct rte_flow_action_set_mac, mac_addr)),
4355 .call = parse_vc_conf,
4357 [ACTION_INC_TCP_SEQ] = {
4358 .name = "inc_tcp_seq",
4359 .help = "increase TCP sequence number",
4360 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
4361 .next = NEXT(action_inc_tcp_seq),
4364 [ACTION_INC_TCP_SEQ_VALUE] = {
4366 .help = "the value to increase TCP sequence number by",
4367 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4368 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4369 .call = parse_vc_conf,
4371 [ACTION_DEC_TCP_SEQ] = {
4372 .name = "dec_tcp_seq",
4373 .help = "decrease TCP sequence number",
4374 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
4375 .next = NEXT(action_dec_tcp_seq),
4378 [ACTION_DEC_TCP_SEQ_VALUE] = {
4380 .help = "the value to decrease TCP sequence number by",
4381 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4382 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4383 .call = parse_vc_conf,
4385 [ACTION_INC_TCP_ACK] = {
4386 .name = "inc_tcp_ack",
4387 .help = "increase TCP acknowledgment number",
4388 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
4389 .next = NEXT(action_inc_tcp_ack),
4392 [ACTION_INC_TCP_ACK_VALUE] = {
4394 .help = "the value to increase TCP acknowledgment number by",
4395 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4396 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4397 .call = parse_vc_conf,
4399 [ACTION_DEC_TCP_ACK] = {
4400 .name = "dec_tcp_ack",
4401 .help = "decrease TCP acknowledgment number",
4402 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
4403 .next = NEXT(action_dec_tcp_ack),
4406 [ACTION_DEC_TCP_ACK_VALUE] = {
4408 .help = "the value to decrease TCP acknowledgment number by",
4409 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4410 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4411 .call = parse_vc_conf,
4413 [ACTION_RAW_ENCAP] = {
4414 .name = "raw_encap",
4415 .help = "encapsulation data, defined by set raw_encap",
4416 .priv = PRIV_ACTION(RAW_ENCAP,
4417 sizeof(struct action_raw_encap_data)),
4418 .next = NEXT(action_raw_encap),
4419 .call = parse_vc_action_raw_encap,
4421 [ACTION_RAW_ENCAP_INDEX] = {
4423 .help = "the index of raw_encap_confs",
4424 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
4426 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
4429 .help = "unsigned integer value",
4430 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4431 .call = parse_vc_action_raw_encap_index,
4432 .comp = comp_set_raw_index,
4434 [ACTION_RAW_DECAP] = {
4435 .name = "raw_decap",
4436 .help = "decapsulation data, defined by set raw_encap",
4437 .priv = PRIV_ACTION(RAW_DECAP,
4438 sizeof(struct action_raw_decap_data)),
4439 .next = NEXT(action_raw_decap),
4440 .call = parse_vc_action_raw_decap,
4442 [ACTION_RAW_DECAP_INDEX] = {
4444 .help = "the index of raw_encap_confs",
4445 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
4447 [ACTION_RAW_DECAP_INDEX_VALUE] = {
4450 .help = "unsigned integer value",
4451 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4452 .call = parse_vc_action_raw_decap_index,
4453 .comp = comp_set_raw_index,
4455 [ACTION_MODIFY_FIELD] = {
4456 .name = "modify_field",
4457 .help = "modify destination field with data from source field",
4458 .priv = PRIV_ACTION(MODIFY_FIELD,
4459 sizeof(struct rte_flow_action_modify_field)),
4460 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
4463 [ACTION_MODIFY_FIELD_OP] = {
4465 .help = "operation type",
4466 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
4467 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
4468 .call = parse_vc_conf,
4470 [ACTION_MODIFY_FIELD_OP_VALUE] = {
4471 .name = "{operation}",
4472 .help = "operation type value",
4473 .call = parse_vc_modify_field_op,
4474 .comp = comp_set_modify_field_op,
4476 [ACTION_MODIFY_FIELD_DST_TYPE] = {
4478 .help = "destination field type",
4479 .next = NEXT(action_modify_field_dst,
4480 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
4481 .call = parse_vc_conf,
4483 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
4484 .name = "{dst_type}",
4485 .help = "destination field type value",
4486 .call = parse_vc_modify_field_id,
4487 .comp = comp_set_modify_field_id,
4489 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
4490 .name = "dst_level",
4491 .help = "destination field level",
4492 .next = NEXT(action_modify_field_dst,
4493 NEXT_ENTRY(COMMON_UNSIGNED)),
4494 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4496 .call = parse_vc_conf,
4498 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
4499 .name = "dst_offset",
4500 .help = "destination field bit offset",
4501 .next = NEXT(action_modify_field_dst,
4502 NEXT_ENTRY(COMMON_UNSIGNED)),
4503 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4505 .call = parse_vc_conf,
4507 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
4509 .help = "source field type",
4510 .next = NEXT(action_modify_field_src,
4511 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
4512 .call = parse_vc_conf,
4514 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
4515 .name = "{src_type}",
4516 .help = "source field type value",
4517 .call = parse_vc_modify_field_id,
4518 .comp = comp_set_modify_field_id,
4520 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
4521 .name = "src_level",
4522 .help = "source field level",
4523 .next = NEXT(action_modify_field_src,
4524 NEXT_ENTRY(COMMON_UNSIGNED)),
4525 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4527 .call = parse_vc_conf,
4529 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
4530 .name = "src_offset",
4531 .help = "source field bit offset",
4532 .next = NEXT(action_modify_field_src,
4533 NEXT_ENTRY(COMMON_UNSIGNED)),
4534 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4536 .call = parse_vc_conf,
4538 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
4539 .name = "src_value",
4540 .help = "source immediate value",
4541 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
4542 NEXT_ENTRY(COMMON_UNSIGNED)),
4543 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4545 .call = parse_vc_conf,
4547 [ACTION_MODIFY_FIELD_WIDTH] = {
4549 .help = "number of bits to copy",
4550 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
4551 NEXT_ENTRY(COMMON_UNSIGNED)),
4552 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4554 .call = parse_vc_conf,
4556 /* Top level command. */
4559 .help = "set raw encap/decap/sample data",
4560 .type = "set raw_encap|raw_decap <index> <pattern>"
4561 " or set sample_actions <index> <action>",
4562 .next = NEXT(NEXT_ENTRY
4565 SET_SAMPLE_ACTIONS)),
4566 .call = parse_set_init,
4568 /* Sub-level commands. */
4570 .name = "raw_encap",
4571 .help = "set raw encap data",
4572 .next = NEXT(next_set_raw),
4573 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4574 (offsetof(struct buffer, port),
4575 sizeof(((struct buffer *)0)->port),
4576 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
4577 .call = parse_set_raw_encap_decap,
4580 .name = "raw_decap",
4581 .help = "set raw decap data",
4582 .next = NEXT(next_set_raw),
4583 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4584 (offsetof(struct buffer, port),
4585 sizeof(((struct buffer *)0)->port),
4586 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
4587 .call = parse_set_raw_encap_decap,
4591 .type = "COMMON_UNSIGNED",
4592 .help = "index of raw_encap/raw_decap data",
4593 .next = NEXT(next_item),
4596 [SET_SAMPLE_INDEX] = {
4599 .help = "index of sample actions",
4600 .next = NEXT(next_action_sample),
4603 [SET_SAMPLE_ACTIONS] = {
4604 .name = "sample_actions",
4605 .help = "set sample actions list",
4606 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
4607 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4608 (offsetof(struct buffer, port),
4609 sizeof(((struct buffer *)0)->port),
4610 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
4611 .call = parse_set_sample_action,
4613 [ACTION_SET_TAG] = {
4616 .priv = PRIV_ACTION(SET_TAG,
4617 sizeof(struct rte_flow_action_set_tag)),
4618 .next = NEXT(action_set_tag),
4621 [ACTION_SET_TAG_INDEX] = {
4623 .help = "index of tag array",
4624 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4625 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
4626 .call = parse_vc_conf,
4628 [ACTION_SET_TAG_DATA] = {
4630 .help = "tag value",
4631 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4632 .args = ARGS(ARGS_ENTRY
4633 (struct rte_flow_action_set_tag, data)),
4634 .call = parse_vc_conf,
4636 [ACTION_SET_TAG_MASK] = {
4638 .help = "mask for tag value",
4639 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4640 .args = ARGS(ARGS_ENTRY
4641 (struct rte_flow_action_set_tag, mask)),
4642 .call = parse_vc_conf,
4644 [ACTION_SET_META] = {
4646 .help = "set metadata",
4647 .priv = PRIV_ACTION(SET_META,
4648 sizeof(struct rte_flow_action_set_meta)),
4649 .next = NEXT(action_set_meta),
4650 .call = parse_vc_action_set_meta,
4652 [ACTION_SET_META_DATA] = {
4654 .help = "metadata value",
4655 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
4656 .args = ARGS(ARGS_ENTRY
4657 (struct rte_flow_action_set_meta, data)),
4658 .call = parse_vc_conf,
4660 [ACTION_SET_META_MASK] = {
4662 .help = "mask for metadata value",
4663 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
4664 .args = ARGS(ARGS_ENTRY
4665 (struct rte_flow_action_set_meta, mask)),
4666 .call = parse_vc_conf,
4668 [ACTION_SET_IPV4_DSCP] = {
4669 .name = "set_ipv4_dscp",
4670 .help = "set DSCP value",
4671 .priv = PRIV_ACTION(SET_IPV4_DSCP,
4672 sizeof(struct rte_flow_action_set_dscp)),
4673 .next = NEXT(action_set_ipv4_dscp),
4676 [ACTION_SET_IPV4_DSCP_VALUE] = {
4677 .name = "dscp_value",
4678 .help = "new IPv4 DSCP value to set",
4679 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
4680 .args = ARGS(ARGS_ENTRY
4681 (struct rte_flow_action_set_dscp, dscp)),
4682 .call = parse_vc_conf,
4684 [ACTION_SET_IPV6_DSCP] = {
4685 .name = "set_ipv6_dscp",
4686 .help = "set DSCP value",
4687 .priv = PRIV_ACTION(SET_IPV6_DSCP,
4688 sizeof(struct rte_flow_action_set_dscp)),
4689 .next = NEXT(action_set_ipv6_dscp),
4692 [ACTION_SET_IPV6_DSCP_VALUE] = {
4693 .name = "dscp_value",
4694 .help = "new IPv6 DSCP value to set",
4695 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
4696 .args = ARGS(ARGS_ENTRY
4697 (struct rte_flow_action_set_dscp, dscp)),
4698 .call = parse_vc_conf,
4702 .help = "set a specific metadata header",
4703 .next = NEXT(action_age),
4704 .priv = PRIV_ACTION(AGE,
4705 sizeof(struct rte_flow_action_age)),
4708 [ACTION_AGE_TIMEOUT] = {
4710 .help = "flow age timeout value",
4711 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
4713 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
4714 .call = parse_vc_conf,
4718 .help = "set a sample action",
4719 .next = NEXT(action_sample),
4720 .priv = PRIV_ACTION(SAMPLE,
4721 sizeof(struct action_sample_data)),
4722 .call = parse_vc_action_sample,
4724 [ACTION_SAMPLE_RATIO] = {
4726 .help = "flow sample ratio value",
4727 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
4728 .args = ARGS(ARGS_ENTRY_ARB
4729 (offsetof(struct action_sample_data, conf) +
4730 offsetof(struct rte_flow_action_sample, ratio),
4731 sizeof(((struct rte_flow_action_sample *)0)->
4734 [ACTION_SAMPLE_INDEX] = {
4736 .help = "the index of sample actions list",
4737 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
4739 [ACTION_SAMPLE_INDEX_VALUE] = {
4741 .type = "COMMON_UNSIGNED",
4742 .help = "unsigned integer value",
4743 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4744 .call = parse_vc_action_sample_index,
4745 .comp = comp_set_sample_index,
4747 [ACTION_CONNTRACK] = {
4748 .name = "conntrack",
4749 .help = "create a conntrack object",
4750 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4751 .priv = PRIV_ACTION(CONNTRACK,
4752 sizeof(struct rte_flow_action_conntrack)),
4755 [ACTION_CONNTRACK_UPDATE] = {
4756 .name = "conntrack_update",
4757 .help = "update a conntrack object",
4758 .next = NEXT(action_update_conntrack),
4759 .priv = PRIV_ACTION(CONNTRACK,
4760 sizeof(struct rte_flow_modify_conntrack)),
4763 [ACTION_CONNTRACK_UPDATE_DIR] = {
4765 .help = "update a conntrack object direction",
4766 .next = NEXT(action_update_conntrack),
4767 .call = parse_vc_action_conntrack_update,
4769 [ACTION_CONNTRACK_UPDATE_CTX] = {
4771 .help = "update a conntrack object context",
4772 .next = NEXT(action_update_conntrack),
4773 .call = parse_vc_action_conntrack_update,
4775 /* Indirect action destroy arguments. */
4776 [INDIRECT_ACTION_DESTROY_ID] = {
4777 .name = "action_id",
4778 .help = "specify a indirect action id to destroy",
4779 .next = NEXT(next_ia_destroy_attr,
4780 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4781 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
4782 args.ia_destroy.action_id)),
4783 .call = parse_ia_destroy,
4785 /* Indirect action create arguments. */
4786 [INDIRECT_ACTION_CREATE_ID] = {
4787 .name = "action_id",
4788 .help = "specify a indirect action id to create",
4789 .next = NEXT(next_ia_create_attr,
4790 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4791 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4793 [ACTION_INDIRECT] = {
4795 .help = "apply indirect action by id",
4796 .priv = PRIV_ACTION(INDIRECT, 0),
4797 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
4798 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
4801 [INDIRECT_ACTION_ID2PTR] = {
4802 .name = "{action_id}",
4803 .type = "INDIRECT_ACTION_ID",
4804 .help = "indirect action id",
4805 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4806 .call = parse_ia_id2ptr,
4809 [INDIRECT_ACTION_INGRESS] = {
4811 .help = "affect rule to ingress",
4812 .next = NEXT(next_ia_create_attr),
4815 [INDIRECT_ACTION_EGRESS] = {
4817 .help = "affect rule to egress",
4818 .next = NEXT(next_ia_create_attr),
4821 [INDIRECT_ACTION_TRANSFER] = {
4823 .help = "affect rule to transfer",
4824 .next = NEXT(next_ia_create_attr),
4827 [INDIRECT_ACTION_SPEC] = {
4829 .help = "specify action to create indirect handle",
4830 .next = NEXT(next_action),
4833 .name = "g_actions",
4834 .help = "submit a list of associated actions for green",
4835 .next = NEXT(next_action),
4839 .name = "y_actions",
4840 .help = "submit a list of associated actions for yellow",
4841 .next = NEXT(next_action),
4844 .name = "r_actions",
4845 .help = "submit a list of associated actions for red",
4846 .next = NEXT(next_action),
4849 /* Top-level command. */
4852 .type = "port meter policy {port_id} {arg}",
4853 .help = "add port meter policy",
4854 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
4857 /* Sub-level commands. */
4860 .help = "add port meter policy",
4861 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
4863 [ITEM_POL_METER] = {
4865 .help = "add port meter policy",
4866 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
4868 [ITEM_POL_POLICY] = {
4870 .help = "add port meter policy",
4871 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
4872 NEXT_ENTRY(ACTION_POL_Y),
4873 NEXT_ENTRY(ACTION_POL_G),
4874 NEXT_ENTRY(COMMON_POLICY_ID),
4875 NEXT_ENTRY(COMMON_PORT_ID)),
4876 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
4877 ARGS_ENTRY(struct buffer, port)),
4882 /** Remove and return last entry from argument stack. */
4883 static const struct arg *
4884 pop_args(struct context *ctx)
4886 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
4889 /** Add entry on top of the argument stack. */
4891 push_args(struct context *ctx, const struct arg *arg)
4893 if (ctx->args_num == CTX_STACK_SIZE)
4895 ctx->args[ctx->args_num++] = arg;
4899 /** Spread value into buffer according to bit-mask. */
4901 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
4903 uint32_t i = arg->size;
4911 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4920 unsigned int shift = 0;
4921 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
4923 for (shift = 0; arg->mask[i] >> shift; ++shift) {
4924 if (!(arg->mask[i] & (1 << shift)))
4929 *buf &= ~(1 << shift);
4930 *buf |= (val & 1) << shift;
4938 /** Compare a string with a partial one of a given length. */
4940 strcmp_partial(const char *full, const char *partial, size_t partial_len)
4942 int r = strncmp(full, partial, partial_len);
4946 if (strlen(full) <= partial_len)
4948 return full[partial_len];
4952 * Parse a prefix length and generate a bit-mask.
4954 * Last argument (ctx->args) is retrieved to determine mask size, storage
4955 * location and whether the result must use network byte ordering.
4958 parse_prefix(struct context *ctx, const struct token *token,
4959 const char *str, unsigned int len,
4960 void *buf, unsigned int size)
4962 const struct arg *arg = pop_args(ctx);
4963 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
4970 /* Argument is expected. */
4974 u = strtoumax(str, &end, 0);
4975 if (errno || (size_t)(end - str) != len)
4980 extra = arg_entry_bf_fill(NULL, 0, arg);
4989 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
4990 !arg_entry_bf_fill(ctx->objmask, -1, arg))
4997 if (bytes > size || bytes + !!extra > size)
5001 buf = (uint8_t *)ctx->object + arg->offset;
5002 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5004 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
5005 memset(buf, 0x00, size - bytes);
5007 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
5011 memset(buf, 0xff, bytes);
5012 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
5014 ((uint8_t *)buf)[bytes] = conv[extra];
5017 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5020 push_args(ctx, arg);
5024 /** Default parsing function for token name matching. */
5026 parse_default(struct context *ctx, const struct token *token,
5027 const char *str, unsigned int len,
5028 void *buf, unsigned int size)
5033 if (strcmp_partial(token->name, str, len))
5038 /** Parse flow command, initialize output buffer for subsequent tokens. */
5040 parse_init(struct context *ctx, const struct token *token,
5041 const char *str, unsigned int len,
5042 void *buf, unsigned int size)
5044 struct buffer *out = buf;
5046 /* Token name must match. */
5047 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5049 /* Nothing else to do if there is no buffer. */
5052 /* Make sure buffer is large enough. */
5053 if (size < sizeof(*out))
5055 /* Initialize buffer. */
5056 memset(out, 0x00, sizeof(*out));
5057 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5060 ctx->objmask = NULL;
5064 /** Parse tokens for indirect action commands. */
5066 parse_ia(struct context *ctx, const struct token *token,
5067 const char *str, unsigned int len,
5068 void *buf, unsigned int size)
5070 struct buffer *out = buf;
5072 /* Token name must match. */
5073 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5075 /* Nothing else to do if there is no buffer. */
5078 if (!out->command) {
5079 if (ctx->curr != INDIRECT_ACTION)
5081 if (sizeof(*out) > size)
5083 out->command = ctx->curr;
5086 ctx->objmask = NULL;
5087 out->args.vc.data = (uint8_t *)out + size;
5090 switch (ctx->curr) {
5091 case INDIRECT_ACTION_CREATE:
5092 case INDIRECT_ACTION_UPDATE:
5093 out->args.vc.actions =
5094 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5096 out->args.vc.attr.group = UINT32_MAX;
5098 case INDIRECT_ACTION_QUERY:
5099 out->command = ctx->curr;
5102 ctx->objmask = NULL;
5104 case INDIRECT_ACTION_EGRESS:
5105 out->args.vc.attr.egress = 1;
5107 case INDIRECT_ACTION_INGRESS:
5108 out->args.vc.attr.ingress = 1;
5110 case INDIRECT_ACTION_TRANSFER:
5111 out->args.vc.attr.transfer = 1;
5119 /** Parse tokens for indirect action destroy command. */
5121 parse_ia_destroy(struct context *ctx, const struct token *token,
5122 const char *str, unsigned int len,
5123 void *buf, unsigned int size)
5125 struct buffer *out = buf;
5126 uint32_t *action_id;
5128 /* Token name must match. */
5129 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5131 /* Nothing else to do if there is no buffer. */
5134 if (!out->command || out->command == INDIRECT_ACTION) {
5135 if (ctx->curr != INDIRECT_ACTION_DESTROY)
5137 if (sizeof(*out) > size)
5139 out->command = ctx->curr;
5142 ctx->objmask = NULL;
5143 out->args.ia_destroy.action_id =
5144 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5148 action_id = out->args.ia_destroy.action_id
5149 + out->args.ia_destroy.action_id_n++;
5150 if ((uint8_t *)action_id > (uint8_t *)out + size)
5153 ctx->object = action_id;
5154 ctx->objmask = NULL;
5158 /** Parse tokens for meter policy action commands. */
5160 parse_mp(struct context *ctx, const struct token *token,
5161 const char *str, unsigned int len,
5162 void *buf, unsigned int size)
5164 struct buffer *out = buf;
5166 /* Token name must match. */
5167 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5169 /* Nothing else to do if there is no buffer. */
5172 if (!out->command) {
5173 if (ctx->curr != ITEM_POL_POLICY)
5175 if (sizeof(*out) > size)
5177 out->command = ctx->curr;
5180 ctx->objmask = NULL;
5181 out->args.vc.data = (uint8_t *)out + size;
5184 switch (ctx->curr) {
5186 out->args.vc.actions =
5187 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5189 out->command = ctx->curr;
5192 ctx->objmask = NULL;
5199 /** Parse tokens for validate/create commands. */
5201 parse_vc(struct context *ctx, const struct token *token,
5202 const char *str, unsigned int len,
5203 void *buf, unsigned int size)
5205 struct buffer *out = buf;
5209 /* Token name must match. */
5210 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5212 /* Nothing else to do if there is no buffer. */
5215 if (!out->command) {
5216 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
5218 if (sizeof(*out) > size)
5220 out->command = ctx->curr;
5223 ctx->objmask = NULL;
5224 out->args.vc.data = (uint8_t *)out + size;
5228 switch (ctx->curr) {
5230 ctx->object = &out->args.vc.attr;
5233 case VC_TUNNEL_MATCH:
5234 ctx->object = &out->args.vc.tunnel_ops;
5237 ctx->objmask = NULL;
5238 switch (ctx->curr) {
5243 out->args.vc.tunnel_ops.enabled = 1;
5244 out->args.vc.tunnel_ops.actions = 1;
5246 case VC_TUNNEL_MATCH:
5247 out->args.vc.tunnel_ops.enabled = 1;
5248 out->args.vc.tunnel_ops.items = 1;
5251 out->args.vc.attr.ingress = 1;
5254 out->args.vc.attr.egress = 1;
5257 out->args.vc.attr.transfer = 1;
5260 out->args.vc.pattern =
5261 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5263 ctx->object = out->args.vc.pattern;
5264 ctx->objmask = NULL;
5267 out->args.vc.actions =
5268 (void *)RTE_ALIGN_CEIL((uintptr_t)
5269 (out->args.vc.pattern +
5270 out->args.vc.pattern_n),
5272 ctx->object = out->args.vc.actions;
5273 ctx->objmask = NULL;
5280 if (!out->args.vc.actions) {
5281 const struct parse_item_priv *priv = token->priv;
5282 struct rte_flow_item *item =
5283 out->args.vc.pattern + out->args.vc.pattern_n;
5285 data_size = priv->size * 3; /* spec, last, mask */
5286 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5287 (out->args.vc.data - data_size),
5289 if ((uint8_t *)item + sizeof(*item) > data)
5291 *item = (struct rte_flow_item){
5294 ++out->args.vc.pattern_n;
5296 ctx->objmask = NULL;
5298 const struct parse_action_priv *priv = token->priv;
5299 struct rte_flow_action *action =
5300 out->args.vc.actions + out->args.vc.actions_n;
5302 data_size = priv->size; /* configuration */
5303 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5304 (out->args.vc.data - data_size),
5306 if ((uint8_t *)action + sizeof(*action) > data)
5308 *action = (struct rte_flow_action){
5310 .conf = data_size ? data : NULL,
5312 ++out->args.vc.actions_n;
5313 ctx->object = action;
5314 ctx->objmask = NULL;
5316 memset(data, 0, data_size);
5317 out->args.vc.data = data;
5318 ctx->objdata = data_size;
5322 /** Parse pattern item parameter type. */
5324 parse_vc_spec(struct context *ctx, const struct token *token,
5325 const char *str, unsigned int len,
5326 void *buf, unsigned int size)
5328 struct buffer *out = buf;
5329 struct rte_flow_item *item;
5335 /* Token name must match. */
5336 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5338 /* Parse parameter types. */
5339 switch (ctx->curr) {
5340 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
5346 case ITEM_PARAM_SPEC:
5349 case ITEM_PARAM_LAST:
5352 case ITEM_PARAM_PREFIX:
5353 /* Modify next token to expect a prefix. */
5354 if (ctx->next_num < 2)
5356 ctx->next[ctx->next_num - 2] = prefix;
5358 case ITEM_PARAM_MASK:
5364 /* Nothing else to do if there is no buffer. */
5367 if (!out->args.vc.pattern_n)
5369 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
5370 data_size = ctx->objdata / 3; /* spec, last, mask */
5371 /* Point to selected object. */
5372 ctx->object = out->args.vc.data + (data_size * index);
5374 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
5375 item->mask = ctx->objmask;
5377 ctx->objmask = NULL;
5378 /* Update relevant item pointer. */
5379 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
5384 /** Parse action configuration field. */
5386 parse_vc_conf(struct context *ctx, const struct token *token,
5387 const char *str, unsigned int len,
5388 void *buf, unsigned int size)
5390 struct buffer *out = buf;
5393 /* Token name must match. */
5394 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5396 /* Nothing else to do if there is no buffer. */
5399 /* Point to selected object. */
5400 ctx->object = out->args.vc.data;
5401 ctx->objmask = NULL;
5405 /** Parse eCPRI common header type field. */
5407 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
5408 const char *str, unsigned int len,
5409 void *buf, unsigned int size)
5411 struct rte_flow_item_ecpri *ecpri;
5412 struct rte_flow_item_ecpri *ecpri_mask;
5413 struct rte_flow_item *item;
5416 struct buffer *out = buf;
5417 const struct arg *arg;
5420 /* Token name must match. */
5421 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5423 switch (ctx->curr) {
5424 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
5425 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
5427 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
5428 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
5430 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
5431 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
5438 arg = pop_args(ctx);
5441 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
5442 ecpri->hdr.common.type = msg_type;
5443 data_size = ctx->objdata / 3; /* spec, last, mask */
5444 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
5446 ecpri_mask->hdr.common.type = 0xFF;
5448 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
5449 ecpri_mask->hdr.common.u32 =
5450 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
5452 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
5454 item->mask = ecpri_mask;
5458 /** Parse meter color action type. */
5460 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
5461 const char *str, unsigned int len,
5462 void *buf, unsigned int size)
5464 struct rte_flow_action *action_data;
5465 struct rte_flow_action_meter_color *conf;
5466 enum rte_color color;
5470 /* Token name must match. */
5471 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5473 switch (ctx->curr) {
5474 case ACTION_METER_COLOR_GREEN:
5475 color = RTE_COLOR_GREEN;
5477 case ACTION_METER_COLOR_YELLOW:
5478 color = RTE_COLOR_YELLOW;
5480 case ACTION_METER_COLOR_RED:
5481 color = RTE_COLOR_RED;
5489 action_data = ctx->object;
5490 conf = (struct rte_flow_action_meter_color *)
5491 (uintptr_t)(action_data->conf);
5492 conf->color = color;
5496 /** Parse RSS action. */
5498 parse_vc_action_rss(struct context *ctx, const struct token *token,
5499 const char *str, unsigned int len,
5500 void *buf, unsigned int size)
5502 struct buffer *out = buf;
5503 struct rte_flow_action *action;
5504 struct action_rss_data *action_rss_data;
5508 ret = parse_vc(ctx, token, str, len, buf, size);
5511 /* Nothing else to do if there is no buffer. */
5514 if (!out->args.vc.actions_n)
5516 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5517 /* Point to selected object. */
5518 ctx->object = out->args.vc.data;
5519 ctx->objmask = NULL;
5520 /* Set up default configuration. */
5521 action_rss_data = ctx->object;
5522 *action_rss_data = (struct action_rss_data){
5523 .conf = (struct rte_flow_action_rss){
5524 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
5528 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
5530 .queue = action_rss_data->queue,
5534 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
5535 action_rss_data->queue[i] = i;
5536 action->conf = &action_rss_data->conf;
5541 * Parse func field for RSS action.
5543 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
5544 * ACTION_RSS_FUNC_* index that called this function.
5547 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
5548 const char *str, unsigned int len,
5549 void *buf, unsigned int size)
5551 struct action_rss_data *action_rss_data;
5552 enum rte_eth_hash_function func;
5556 /* Token name must match. */
5557 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5559 switch (ctx->curr) {
5560 case ACTION_RSS_FUNC_DEFAULT:
5561 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
5563 case ACTION_RSS_FUNC_TOEPLITZ:
5564 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
5566 case ACTION_RSS_FUNC_SIMPLE_XOR:
5567 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
5569 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
5570 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
5577 action_rss_data = ctx->object;
5578 action_rss_data->conf.func = func;
5583 * Parse type field for RSS action.
5585 * Valid tokens are type field names and the "end" token.
5588 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
5589 const char *str, unsigned int len,
5590 void *buf, unsigned int size)
5592 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
5593 struct action_rss_data *action_rss_data;
5599 if (ctx->curr != ACTION_RSS_TYPE)
5601 if (!(ctx->objdata >> 16) && ctx->object) {
5602 action_rss_data = ctx->object;
5603 action_rss_data->conf.types = 0;
5605 if (!strcmp_partial("end", str, len)) {
5606 ctx->objdata &= 0xffff;
5609 for (i = 0; rss_type_table[i].str; ++i)
5610 if (!strcmp_partial(rss_type_table[i].str, str, len))
5612 if (!rss_type_table[i].str)
5614 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
5616 if (ctx->next_num == RTE_DIM(ctx->next))
5618 ctx->next[ctx->next_num++] = next;
5621 action_rss_data = ctx->object;
5622 action_rss_data->conf.types |= rss_type_table[i].rss_type;
5627 * Parse queue field for RSS action.
5629 * Valid tokens are queue indices and the "end" token.
5632 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
5633 const char *str, unsigned int len,
5634 void *buf, unsigned int size)
5636 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
5637 struct action_rss_data *action_rss_data;
5638 const struct arg *arg;
5645 if (ctx->curr != ACTION_RSS_QUEUE)
5647 i = ctx->objdata >> 16;
5648 if (!strcmp_partial("end", str, len)) {
5649 ctx->objdata &= 0xffff;
5652 if (i >= ACTION_RSS_QUEUE_NUM)
5654 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
5655 i * sizeof(action_rss_data->queue[i]),
5656 sizeof(action_rss_data->queue[i]));
5657 if (push_args(ctx, arg))
5659 ret = parse_int(ctx, token, str, len, NULL, 0);
5665 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
5667 if (ctx->next_num == RTE_DIM(ctx->next))
5669 ctx->next[ctx->next_num++] = next;
5673 action_rss_data = ctx->object;
5674 action_rss_data->conf.queue_num = i;
5675 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
5679 /** Setup VXLAN encap configuration. */
5681 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
5683 /* Set up default configuration. */
5684 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
5685 .conf = (struct rte_flow_action_vxlan_encap){
5686 .definition = action_vxlan_encap_data->items,
5690 .type = RTE_FLOW_ITEM_TYPE_ETH,
5691 .spec = &action_vxlan_encap_data->item_eth,
5692 .mask = &rte_flow_item_eth_mask,
5695 .type = RTE_FLOW_ITEM_TYPE_VLAN,
5696 .spec = &action_vxlan_encap_data->item_vlan,
5697 .mask = &rte_flow_item_vlan_mask,
5700 .type = RTE_FLOW_ITEM_TYPE_IPV4,
5701 .spec = &action_vxlan_encap_data->item_ipv4,
5702 .mask = &rte_flow_item_ipv4_mask,
5705 .type = RTE_FLOW_ITEM_TYPE_UDP,
5706 .spec = &action_vxlan_encap_data->item_udp,
5707 .mask = &rte_flow_item_udp_mask,
5710 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
5711 .spec = &action_vxlan_encap_data->item_vxlan,
5712 .mask = &rte_flow_item_vxlan_mask,
5715 .type = RTE_FLOW_ITEM_TYPE_END,
5720 .tci = vxlan_encap_conf.vlan_tci,
5724 .src_addr = vxlan_encap_conf.ipv4_src,
5725 .dst_addr = vxlan_encap_conf.ipv4_dst,
5728 .src_port = vxlan_encap_conf.udp_src,
5729 .dst_port = vxlan_encap_conf.udp_dst,
5731 .item_vxlan.flags = 0,
5733 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
5734 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5735 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
5736 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5737 if (!vxlan_encap_conf.select_ipv4) {
5738 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
5739 &vxlan_encap_conf.ipv6_src,
5740 sizeof(vxlan_encap_conf.ipv6_src));
5741 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
5742 &vxlan_encap_conf.ipv6_dst,
5743 sizeof(vxlan_encap_conf.ipv6_dst));
5744 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
5745 .type = RTE_FLOW_ITEM_TYPE_IPV6,
5746 .spec = &action_vxlan_encap_data->item_ipv6,
5747 .mask = &rte_flow_item_ipv6_mask,
5750 if (!vxlan_encap_conf.select_vlan)
5751 action_vxlan_encap_data->items[1].type =
5752 RTE_FLOW_ITEM_TYPE_VOID;
5753 if (vxlan_encap_conf.select_tos_ttl) {
5754 if (vxlan_encap_conf.select_ipv4) {
5755 static struct rte_flow_item_ipv4 ipv4_mask_tos;
5757 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
5758 sizeof(ipv4_mask_tos));
5759 ipv4_mask_tos.hdr.type_of_service = 0xff;
5760 ipv4_mask_tos.hdr.time_to_live = 0xff;
5761 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
5762 vxlan_encap_conf.ip_tos;
5763 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
5764 vxlan_encap_conf.ip_ttl;
5765 action_vxlan_encap_data->items[2].mask =
5768 static struct rte_flow_item_ipv6 ipv6_mask_tos;
5770 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
5771 sizeof(ipv6_mask_tos));
5772 ipv6_mask_tos.hdr.vtc_flow |=
5773 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
5774 ipv6_mask_tos.hdr.hop_limits = 0xff;
5775 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
5777 ((uint32_t)vxlan_encap_conf.ip_tos <<
5778 RTE_IPV6_HDR_TC_SHIFT);
5779 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
5780 vxlan_encap_conf.ip_ttl;
5781 action_vxlan_encap_data->items[2].mask =
5785 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
5786 RTE_DIM(vxlan_encap_conf.vni));
5790 /** Parse VXLAN encap action. */
5792 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
5793 const char *str, unsigned int len,
5794 void *buf, unsigned int size)
5796 struct buffer *out = buf;
5797 struct rte_flow_action *action;
5798 struct action_vxlan_encap_data *action_vxlan_encap_data;
5801 ret = parse_vc(ctx, token, str, len, buf, size);
5804 /* Nothing else to do if there is no buffer. */
5807 if (!out->args.vc.actions_n)
5809 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5810 /* Point to selected object. */
5811 ctx->object = out->args.vc.data;
5812 ctx->objmask = NULL;
5813 action_vxlan_encap_data = ctx->object;
5814 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
5815 action->conf = &action_vxlan_encap_data->conf;
5819 /** Setup NVGRE encap configuration. */
5821 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
5823 /* Set up default configuration. */
5824 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
5825 .conf = (struct rte_flow_action_nvgre_encap){
5826 .definition = action_nvgre_encap_data->items,
5830 .type = RTE_FLOW_ITEM_TYPE_ETH,
5831 .spec = &action_nvgre_encap_data->item_eth,
5832 .mask = &rte_flow_item_eth_mask,
5835 .type = RTE_FLOW_ITEM_TYPE_VLAN,
5836 .spec = &action_nvgre_encap_data->item_vlan,
5837 .mask = &rte_flow_item_vlan_mask,
5840 .type = RTE_FLOW_ITEM_TYPE_IPV4,
5841 .spec = &action_nvgre_encap_data->item_ipv4,
5842 .mask = &rte_flow_item_ipv4_mask,
5845 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
5846 .spec = &action_nvgre_encap_data->item_nvgre,
5847 .mask = &rte_flow_item_nvgre_mask,
5850 .type = RTE_FLOW_ITEM_TYPE_END,
5855 .tci = nvgre_encap_conf.vlan_tci,
5859 .src_addr = nvgre_encap_conf.ipv4_src,
5860 .dst_addr = nvgre_encap_conf.ipv4_dst,
5862 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
5863 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
5864 .item_nvgre.flow_id = 0,
5866 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
5867 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5868 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
5869 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5870 if (!nvgre_encap_conf.select_ipv4) {
5871 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
5872 &nvgre_encap_conf.ipv6_src,
5873 sizeof(nvgre_encap_conf.ipv6_src));
5874 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
5875 &nvgre_encap_conf.ipv6_dst,
5876 sizeof(nvgre_encap_conf.ipv6_dst));
5877 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
5878 .type = RTE_FLOW_ITEM_TYPE_IPV6,
5879 .spec = &action_nvgre_encap_data->item_ipv6,
5880 .mask = &rte_flow_item_ipv6_mask,
5883 if (!nvgre_encap_conf.select_vlan)
5884 action_nvgre_encap_data->items[1].type =
5885 RTE_FLOW_ITEM_TYPE_VOID;
5886 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
5887 RTE_DIM(nvgre_encap_conf.tni));
5891 /** Parse NVGRE encap action. */
5893 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
5894 const char *str, unsigned int len,
5895 void *buf, unsigned int size)
5897 struct buffer *out = buf;
5898 struct rte_flow_action *action;
5899 struct action_nvgre_encap_data *action_nvgre_encap_data;
5902 ret = parse_vc(ctx, token, str, len, buf, size);
5905 /* Nothing else to do if there is no buffer. */
5908 if (!out->args.vc.actions_n)
5910 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5911 /* Point to selected object. */
5912 ctx->object = out->args.vc.data;
5913 ctx->objmask = NULL;
5914 action_nvgre_encap_data = ctx->object;
5915 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
5916 action->conf = &action_nvgre_encap_data->conf;
5920 /** Parse l2 encap action. */
5922 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
5923 const char *str, unsigned int len,
5924 void *buf, unsigned int size)
5926 struct buffer *out = buf;
5927 struct rte_flow_action *action;
5928 struct action_raw_encap_data *action_encap_data;
5929 struct rte_flow_item_eth eth = { .type = 0, };
5930 struct rte_flow_item_vlan vlan = {
5931 .tci = mplsoudp_encap_conf.vlan_tci,
5937 ret = parse_vc(ctx, token, str, len, buf, size);
5940 /* Nothing else to do if there is no buffer. */
5943 if (!out->args.vc.actions_n)
5945 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5946 /* Point to selected object. */
5947 ctx->object = out->args.vc.data;
5948 ctx->objmask = NULL;
5949 /* Copy the headers to the buffer. */
5950 action_encap_data = ctx->object;
5951 *action_encap_data = (struct action_raw_encap_data) {
5952 .conf = (struct rte_flow_action_raw_encap){
5953 .data = action_encap_data->data,
5957 header = action_encap_data->data;
5958 if (l2_encap_conf.select_vlan)
5959 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5960 else if (l2_encap_conf.select_ipv4)
5961 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5963 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5964 memcpy(eth.dst.addr_bytes,
5965 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5966 memcpy(eth.src.addr_bytes,
5967 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5968 memcpy(header, ð, sizeof(eth));
5969 header += sizeof(eth);
5970 if (l2_encap_conf.select_vlan) {
5971 if (l2_encap_conf.select_ipv4)
5972 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5974 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5975 memcpy(header, &vlan, sizeof(vlan));
5976 header += sizeof(vlan);
5978 action_encap_data->conf.size = header -
5979 action_encap_data->data;
5980 action->conf = &action_encap_data->conf;
5984 /** Parse l2 decap action. */
5986 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
5987 const char *str, unsigned int len,
5988 void *buf, unsigned int size)
5990 struct buffer *out = buf;
5991 struct rte_flow_action *action;
5992 struct action_raw_decap_data *action_decap_data;
5993 struct rte_flow_item_eth eth = { .type = 0, };
5994 struct rte_flow_item_vlan vlan = {
5995 .tci = mplsoudp_encap_conf.vlan_tci,
6001 ret = parse_vc(ctx, token, str, len, buf, size);
6004 /* Nothing else to do if there is no buffer. */
6007 if (!out->args.vc.actions_n)
6009 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6010 /* Point to selected object. */
6011 ctx->object = out->args.vc.data;
6012 ctx->objmask = NULL;
6013 /* Copy the headers to the buffer. */
6014 action_decap_data = ctx->object;
6015 *action_decap_data = (struct action_raw_decap_data) {
6016 .conf = (struct rte_flow_action_raw_decap){
6017 .data = action_decap_data->data,
6021 header = action_decap_data->data;
6022 if (l2_decap_conf.select_vlan)
6023 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6024 memcpy(header, ð, sizeof(eth));
6025 header += sizeof(eth);
6026 if (l2_decap_conf.select_vlan) {
6027 memcpy(header, &vlan, sizeof(vlan));
6028 header += sizeof(vlan);
6030 action_decap_data->conf.size = header -
6031 action_decap_data->data;
6032 action->conf = &action_decap_data->conf;
6036 #define ETHER_TYPE_MPLS_UNICAST 0x8847
6038 /** Parse MPLSOGRE encap action. */
6040 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
6041 const char *str, unsigned int len,
6042 void *buf, unsigned int size)
6044 struct buffer *out = buf;
6045 struct rte_flow_action *action;
6046 struct action_raw_encap_data *action_encap_data;
6047 struct rte_flow_item_eth eth = { .type = 0, };
6048 struct rte_flow_item_vlan vlan = {
6049 .tci = mplsogre_encap_conf.vlan_tci,
6052 struct rte_flow_item_ipv4 ipv4 = {
6054 .src_addr = mplsogre_encap_conf.ipv4_src,
6055 .dst_addr = mplsogre_encap_conf.ipv4_dst,
6056 .next_proto_id = IPPROTO_GRE,
6057 .version_ihl = RTE_IPV4_VHL_DEF,
6058 .time_to_live = IPDEFTTL,
6061 struct rte_flow_item_ipv6 ipv6 = {
6063 .proto = IPPROTO_GRE,
6064 .hop_limits = IPDEFTTL,
6067 struct rte_flow_item_gre gre = {
6068 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6070 struct rte_flow_item_mpls mpls = {
6076 ret = parse_vc(ctx, token, str, len, buf, size);
6079 /* Nothing else to do if there is no buffer. */
6082 if (!out->args.vc.actions_n)
6084 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6085 /* Point to selected object. */
6086 ctx->object = out->args.vc.data;
6087 ctx->objmask = NULL;
6088 /* Copy the headers to the buffer. */
6089 action_encap_data = ctx->object;
6090 *action_encap_data = (struct action_raw_encap_data) {
6091 .conf = (struct rte_flow_action_raw_encap){
6092 .data = action_encap_data->data,
6097 header = action_encap_data->data;
6098 if (mplsogre_encap_conf.select_vlan)
6099 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6100 else if (mplsogre_encap_conf.select_ipv4)
6101 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6103 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6104 memcpy(eth.dst.addr_bytes,
6105 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6106 memcpy(eth.src.addr_bytes,
6107 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6108 memcpy(header, ð, sizeof(eth));
6109 header += sizeof(eth);
6110 if (mplsogre_encap_conf.select_vlan) {
6111 if (mplsogre_encap_conf.select_ipv4)
6112 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6114 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6115 memcpy(header, &vlan, sizeof(vlan));
6116 header += sizeof(vlan);
6118 if (mplsogre_encap_conf.select_ipv4) {
6119 memcpy(header, &ipv4, sizeof(ipv4));
6120 header += sizeof(ipv4);
6122 memcpy(&ipv6.hdr.src_addr,
6123 &mplsogre_encap_conf.ipv6_src,
6124 sizeof(mplsogre_encap_conf.ipv6_src));
6125 memcpy(&ipv6.hdr.dst_addr,
6126 &mplsogre_encap_conf.ipv6_dst,
6127 sizeof(mplsogre_encap_conf.ipv6_dst));
6128 memcpy(header, &ipv6, sizeof(ipv6));
6129 header += sizeof(ipv6);
6131 memcpy(header, &gre, sizeof(gre));
6132 header += sizeof(gre);
6133 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
6134 RTE_DIM(mplsogre_encap_conf.label));
6135 mpls.label_tc_s[2] |= 0x1;
6136 memcpy(header, &mpls, sizeof(mpls));
6137 header += sizeof(mpls);
6138 action_encap_data->conf.size = header -
6139 action_encap_data->data;
6140 action->conf = &action_encap_data->conf;
6144 /** Parse MPLSOGRE decap action. */
6146 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
6147 const char *str, unsigned int len,
6148 void *buf, unsigned int size)
6150 struct buffer *out = buf;
6151 struct rte_flow_action *action;
6152 struct action_raw_decap_data *action_decap_data;
6153 struct rte_flow_item_eth eth = { .type = 0, };
6154 struct rte_flow_item_vlan vlan = {.tci = 0};
6155 struct rte_flow_item_ipv4 ipv4 = {
6157 .next_proto_id = IPPROTO_GRE,
6160 struct rte_flow_item_ipv6 ipv6 = {
6162 .proto = IPPROTO_GRE,
6165 struct rte_flow_item_gre gre = {
6166 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6168 struct rte_flow_item_mpls mpls;
6172 ret = parse_vc(ctx, token, str, len, buf, size);
6175 /* Nothing else to do if there is no buffer. */
6178 if (!out->args.vc.actions_n)
6180 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6181 /* Point to selected object. */
6182 ctx->object = out->args.vc.data;
6183 ctx->objmask = NULL;
6184 /* Copy the headers to the buffer. */
6185 action_decap_data = ctx->object;
6186 *action_decap_data = (struct action_raw_decap_data) {
6187 .conf = (struct rte_flow_action_raw_decap){
6188 .data = action_decap_data->data,
6192 header = action_decap_data->data;
6193 if (mplsogre_decap_conf.select_vlan)
6194 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6195 else if (mplsogre_encap_conf.select_ipv4)
6196 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6198 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6199 memcpy(eth.dst.addr_bytes,
6200 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6201 memcpy(eth.src.addr_bytes,
6202 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6203 memcpy(header, ð, sizeof(eth));
6204 header += sizeof(eth);
6205 if (mplsogre_encap_conf.select_vlan) {
6206 if (mplsogre_encap_conf.select_ipv4)
6207 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6209 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6210 memcpy(header, &vlan, sizeof(vlan));
6211 header += sizeof(vlan);
6213 if (mplsogre_encap_conf.select_ipv4) {
6214 memcpy(header, &ipv4, sizeof(ipv4));
6215 header += sizeof(ipv4);
6217 memcpy(header, &ipv6, sizeof(ipv6));
6218 header += sizeof(ipv6);
6220 memcpy(header, &gre, sizeof(gre));
6221 header += sizeof(gre);
6222 memset(&mpls, 0, sizeof(mpls));
6223 memcpy(header, &mpls, sizeof(mpls));
6224 header += sizeof(mpls);
6225 action_decap_data->conf.size = header -
6226 action_decap_data->data;
6227 action->conf = &action_decap_data->conf;
6231 /** Parse MPLSOUDP encap action. */
6233 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
6234 const char *str, unsigned int len,
6235 void *buf, unsigned int size)
6237 struct buffer *out = buf;
6238 struct rte_flow_action *action;
6239 struct action_raw_encap_data *action_encap_data;
6240 struct rte_flow_item_eth eth = { .type = 0, };
6241 struct rte_flow_item_vlan vlan = {
6242 .tci = mplsoudp_encap_conf.vlan_tci,
6245 struct rte_flow_item_ipv4 ipv4 = {
6247 .src_addr = mplsoudp_encap_conf.ipv4_src,
6248 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
6249 .next_proto_id = IPPROTO_UDP,
6250 .version_ihl = RTE_IPV4_VHL_DEF,
6251 .time_to_live = IPDEFTTL,
6254 struct rte_flow_item_ipv6 ipv6 = {
6256 .proto = IPPROTO_UDP,
6257 .hop_limits = IPDEFTTL,
6260 struct rte_flow_item_udp udp = {
6262 .src_port = mplsoudp_encap_conf.udp_src,
6263 .dst_port = mplsoudp_encap_conf.udp_dst,
6266 struct rte_flow_item_mpls mpls;
6270 ret = parse_vc(ctx, token, str, len, buf, size);
6273 /* Nothing else to do if there is no buffer. */
6276 if (!out->args.vc.actions_n)
6278 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6279 /* Point to selected object. */
6280 ctx->object = out->args.vc.data;
6281 ctx->objmask = NULL;
6282 /* Copy the headers to the buffer. */
6283 action_encap_data = ctx->object;
6284 *action_encap_data = (struct action_raw_encap_data) {
6285 .conf = (struct rte_flow_action_raw_encap){
6286 .data = action_encap_data->data,
6291 header = action_encap_data->data;
6292 if (mplsoudp_encap_conf.select_vlan)
6293 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6294 else if (mplsoudp_encap_conf.select_ipv4)
6295 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6297 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6298 memcpy(eth.dst.addr_bytes,
6299 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6300 memcpy(eth.src.addr_bytes,
6301 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6302 memcpy(header, ð, sizeof(eth));
6303 header += sizeof(eth);
6304 if (mplsoudp_encap_conf.select_vlan) {
6305 if (mplsoudp_encap_conf.select_ipv4)
6306 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6308 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6309 memcpy(header, &vlan, sizeof(vlan));
6310 header += sizeof(vlan);
6312 if (mplsoudp_encap_conf.select_ipv4) {
6313 memcpy(header, &ipv4, sizeof(ipv4));
6314 header += sizeof(ipv4);
6316 memcpy(&ipv6.hdr.src_addr,
6317 &mplsoudp_encap_conf.ipv6_src,
6318 sizeof(mplsoudp_encap_conf.ipv6_src));
6319 memcpy(&ipv6.hdr.dst_addr,
6320 &mplsoudp_encap_conf.ipv6_dst,
6321 sizeof(mplsoudp_encap_conf.ipv6_dst));
6322 memcpy(header, &ipv6, sizeof(ipv6));
6323 header += sizeof(ipv6);
6325 memcpy(header, &udp, sizeof(udp));
6326 header += sizeof(udp);
6327 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
6328 RTE_DIM(mplsoudp_encap_conf.label));
6329 mpls.label_tc_s[2] |= 0x1;
6330 memcpy(header, &mpls, sizeof(mpls));
6331 header += sizeof(mpls);
6332 action_encap_data->conf.size = header -
6333 action_encap_data->data;
6334 action->conf = &action_encap_data->conf;
6338 /** Parse MPLSOUDP decap action. */
6340 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
6341 const char *str, unsigned int len,
6342 void *buf, unsigned int size)
6344 struct buffer *out = buf;
6345 struct rte_flow_action *action;
6346 struct action_raw_decap_data *action_decap_data;
6347 struct rte_flow_item_eth eth = { .type = 0, };
6348 struct rte_flow_item_vlan vlan = {.tci = 0};
6349 struct rte_flow_item_ipv4 ipv4 = {
6351 .next_proto_id = IPPROTO_UDP,
6354 struct rte_flow_item_ipv6 ipv6 = {
6356 .proto = IPPROTO_UDP,
6359 struct rte_flow_item_udp udp = {
6361 .dst_port = rte_cpu_to_be_16(6635),
6364 struct rte_flow_item_mpls mpls;
6368 ret = parse_vc(ctx, token, str, len, buf, size);
6371 /* Nothing else to do if there is no buffer. */
6374 if (!out->args.vc.actions_n)
6376 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6377 /* Point to selected object. */
6378 ctx->object = out->args.vc.data;
6379 ctx->objmask = NULL;
6380 /* Copy the headers to the buffer. */
6381 action_decap_data = ctx->object;
6382 *action_decap_data = (struct action_raw_decap_data) {
6383 .conf = (struct rte_flow_action_raw_decap){
6384 .data = action_decap_data->data,
6388 header = action_decap_data->data;
6389 if (mplsoudp_decap_conf.select_vlan)
6390 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6391 else if (mplsoudp_encap_conf.select_ipv4)
6392 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6394 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6395 memcpy(eth.dst.addr_bytes,
6396 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6397 memcpy(eth.src.addr_bytes,
6398 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6399 memcpy(header, ð, sizeof(eth));
6400 header += sizeof(eth);
6401 if (mplsoudp_encap_conf.select_vlan) {
6402 if (mplsoudp_encap_conf.select_ipv4)
6403 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6405 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6406 memcpy(header, &vlan, sizeof(vlan));
6407 header += sizeof(vlan);
6409 if (mplsoudp_encap_conf.select_ipv4) {
6410 memcpy(header, &ipv4, sizeof(ipv4));
6411 header += sizeof(ipv4);
6413 memcpy(header, &ipv6, sizeof(ipv6));
6414 header += sizeof(ipv6);
6416 memcpy(header, &udp, sizeof(udp));
6417 header += sizeof(udp);
6418 memset(&mpls, 0, sizeof(mpls));
6419 memcpy(header, &mpls, sizeof(mpls));
6420 header += sizeof(mpls);
6421 action_decap_data->conf.size = header -
6422 action_decap_data->data;
6423 action->conf = &action_decap_data->conf;
6428 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
6429 const char *str, unsigned int len, void *buf,
6432 struct action_raw_decap_data *action_raw_decap_data;
6433 struct rte_flow_action *action;
6434 const struct arg *arg;
6435 struct buffer *out = buf;
6439 RTE_SET_USED(token);
6442 arg = ARGS_ENTRY_ARB_BOUNDED
6443 (offsetof(struct action_raw_decap_data, idx),
6444 sizeof(((struct action_raw_decap_data *)0)->idx),
6445 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
6446 if (push_args(ctx, arg))
6448 ret = parse_int(ctx, token, str, len, NULL, 0);
6455 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6456 action_raw_decap_data = ctx->object;
6457 idx = action_raw_decap_data->idx;
6458 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
6459 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
6460 action->conf = &action_raw_decap_data->conf;
6466 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
6467 const char *str, unsigned int len, void *buf,
6470 struct action_raw_encap_data *action_raw_encap_data;
6471 struct rte_flow_action *action;
6472 const struct arg *arg;
6473 struct buffer *out = buf;
6477 RTE_SET_USED(token);
6480 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
6482 arg = ARGS_ENTRY_ARB_BOUNDED
6483 (offsetof(struct action_raw_encap_data, idx),
6484 sizeof(((struct action_raw_encap_data *)0)->idx),
6485 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
6486 if (push_args(ctx, arg))
6488 ret = parse_int(ctx, token, str, len, NULL, 0);
6495 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6496 action_raw_encap_data = ctx->object;
6497 idx = action_raw_encap_data->idx;
6498 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
6499 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
6500 action_raw_encap_data->conf.preserve = NULL;
6501 action->conf = &action_raw_encap_data->conf;
6506 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
6507 const char *str, unsigned int len, void *buf,
6510 struct buffer *out = buf;
6511 struct rte_flow_action *action;
6512 struct action_raw_encap_data *action_raw_encap_data = NULL;
6515 ret = parse_vc(ctx, token, str, len, buf, size);
6518 /* Nothing else to do if there is no buffer. */
6521 if (!out->args.vc.actions_n)
6523 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6524 /* Point to selected object. */
6525 ctx->object = out->args.vc.data;
6526 ctx->objmask = NULL;
6527 /* Copy the headers to the buffer. */
6528 action_raw_encap_data = ctx->object;
6529 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
6530 action_raw_encap_data->conf.preserve = NULL;
6531 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
6532 action->conf = &action_raw_encap_data->conf;
6537 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
6538 const char *str, unsigned int len, void *buf,
6541 struct buffer *out = buf;
6542 struct rte_flow_action *action;
6543 struct action_raw_decap_data *action_raw_decap_data = NULL;
6546 ret = parse_vc(ctx, token, str, len, buf, size);
6549 /* Nothing else to do if there is no buffer. */
6552 if (!out->args.vc.actions_n)
6554 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6555 /* Point to selected object. */
6556 ctx->object = out->args.vc.data;
6557 ctx->objmask = NULL;
6558 /* Copy the headers to the buffer. */
6559 action_raw_decap_data = ctx->object;
6560 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
6561 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
6562 action->conf = &action_raw_decap_data->conf;
6567 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
6568 const char *str, unsigned int len, void *buf,
6573 ret = parse_vc(ctx, token, str, len, buf, size);
6576 ret = rte_flow_dynf_metadata_register();
6583 parse_vc_action_sample(struct context *ctx, const struct token *token,
6584 const char *str, unsigned int len, void *buf,
6587 struct buffer *out = buf;
6588 struct rte_flow_action *action;
6589 struct action_sample_data *action_sample_data = NULL;
6590 static struct rte_flow_action end_action = {
6591 RTE_FLOW_ACTION_TYPE_END, 0
6595 ret = parse_vc(ctx, token, str, len, buf, size);
6598 /* Nothing else to do if there is no buffer. */
6601 if (!out->args.vc.actions_n)
6603 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6604 /* Point to selected object. */
6605 ctx->object = out->args.vc.data;
6606 ctx->objmask = NULL;
6607 /* Copy the headers to the buffer. */
6608 action_sample_data = ctx->object;
6609 action_sample_data->conf.actions = &end_action;
6610 action->conf = &action_sample_data->conf;
6615 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
6616 const char *str, unsigned int len, void *buf,
6619 struct action_sample_data *action_sample_data;
6620 struct rte_flow_action *action;
6621 const struct arg *arg;
6622 struct buffer *out = buf;
6626 RTE_SET_USED(token);
6629 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
6631 arg = ARGS_ENTRY_ARB_BOUNDED
6632 (offsetof(struct action_sample_data, idx),
6633 sizeof(((struct action_sample_data *)0)->idx),
6634 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
6635 if (push_args(ctx, arg))
6637 ret = parse_int(ctx, token, str, len, NULL, 0);
6644 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6645 action_sample_data = ctx->object;
6646 idx = action_sample_data->idx;
6647 action_sample_data->conf.actions = raw_sample_confs[idx].data;
6648 action->conf = &action_sample_data->conf;
6652 /** Parse operation for modify_field command. */
6654 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
6655 const char *str, unsigned int len, void *buf,
6658 struct rte_flow_action_modify_field *action_modify_field;
6664 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
6666 for (i = 0; modify_field_ops[i]; ++i)
6667 if (!strcmp_partial(modify_field_ops[i], str, len))
6669 if (!modify_field_ops[i])
6673 action_modify_field = ctx->object;
6674 action_modify_field->operation = (enum rte_flow_modify_op)i;
6678 /** Parse id for modify_field command. */
6680 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
6681 const char *str, unsigned int len, void *buf,
6684 struct rte_flow_action_modify_field *action_modify_field;
6690 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
6691 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
6693 for (i = 0; modify_field_ids[i]; ++i)
6694 if (!strcmp_partial(modify_field_ids[i], str, len))
6696 if (!modify_field_ids[i])
6700 action_modify_field = ctx->object;
6701 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
6702 action_modify_field->dst.field = (enum rte_flow_field_id)i;
6704 action_modify_field->src.field = (enum rte_flow_field_id)i;
6708 /** Parse the conntrack update, not a rte_flow_action. */
6710 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
6711 const char *str, unsigned int len, void *buf,
6714 struct buffer *out = buf;
6715 struct rte_flow_modify_conntrack *ct_modify = NULL;
6718 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
6719 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
6721 /* Token name must match. */
6722 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6724 /* Nothing else to do if there is no buffer. */
6727 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
6728 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
6729 ct_modify->new_ct.is_original_dir =
6730 conntrack_context.is_original_dir;
6731 ct_modify->direction = 1;
6735 old_dir = ct_modify->new_ct.is_original_dir;
6736 memcpy(&ct_modify->new_ct, &conntrack_context,
6737 sizeof(conntrack_context));
6738 ct_modify->new_ct.is_original_dir = old_dir;
6739 ct_modify->state = 1;
6744 /** Parse tokens for destroy command. */
6746 parse_destroy(struct context *ctx, const struct token *token,
6747 const char *str, unsigned int len,
6748 void *buf, unsigned int size)
6750 struct buffer *out = buf;
6752 /* Token name must match. */
6753 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6755 /* Nothing else to do if there is no buffer. */
6758 if (!out->command) {
6759 if (ctx->curr != DESTROY)
6761 if (sizeof(*out) > size)
6763 out->command = ctx->curr;
6766 ctx->objmask = NULL;
6767 out->args.destroy.rule =
6768 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6772 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
6773 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
6776 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
6777 ctx->objmask = NULL;
6781 /** Parse tokens for flush command. */
6783 parse_flush(struct context *ctx, const struct token *token,
6784 const char *str, unsigned int len,
6785 void *buf, unsigned int size)
6787 struct buffer *out = buf;
6789 /* Token name must match. */
6790 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6792 /* Nothing else to do if there is no buffer. */
6795 if (!out->command) {
6796 if (ctx->curr != FLUSH)
6798 if (sizeof(*out) > size)
6800 out->command = ctx->curr;
6803 ctx->objmask = NULL;
6808 /** Parse tokens for dump command. */
6810 parse_dump(struct context *ctx, const struct token *token,
6811 const char *str, unsigned int len,
6812 void *buf, unsigned int size)
6814 struct buffer *out = buf;
6816 /* Token name must match. */
6817 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6819 /* Nothing else to do if there is no buffer. */
6822 if (!out->command) {
6823 if (ctx->curr != DUMP)
6825 if (sizeof(*out) > size)
6827 out->command = ctx->curr;
6830 ctx->objmask = NULL;
6833 switch (ctx->curr) {
6836 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
6837 out->command = ctx->curr;
6840 ctx->objmask = NULL;
6847 /** Parse tokens for query command. */
6849 parse_query(struct context *ctx, const struct token *token,
6850 const char *str, unsigned int len,
6851 void *buf, unsigned int size)
6853 struct buffer *out = buf;
6855 /* Token name must match. */
6856 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6858 /* Nothing else to do if there is no buffer. */
6861 if (!out->command) {
6862 if (ctx->curr != QUERY)
6864 if (sizeof(*out) > size)
6866 out->command = ctx->curr;
6869 ctx->objmask = NULL;
6874 /** Parse action names. */
6876 parse_action(struct context *ctx, const struct token *token,
6877 const char *str, unsigned int len,
6878 void *buf, unsigned int size)
6880 struct buffer *out = buf;
6881 const struct arg *arg = pop_args(ctx);
6885 /* Argument is expected. */
6888 /* Parse action name. */
6889 for (i = 0; next_action[i]; ++i) {
6890 const struct parse_action_priv *priv;
6892 token = &token_list[next_action[i]];
6893 if (strcmp_partial(token->name, str, len))
6899 memcpy((uint8_t *)ctx->object + arg->offset,
6905 push_args(ctx, arg);
6909 /** Parse tokens for list command. */
6911 parse_list(struct context *ctx, const struct token *token,
6912 const char *str, unsigned int len,
6913 void *buf, unsigned int size)
6915 struct buffer *out = buf;
6917 /* Token name must match. */
6918 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6920 /* Nothing else to do if there is no buffer. */
6923 if (!out->command) {
6924 if (ctx->curr != LIST)
6926 if (sizeof(*out) > size)
6928 out->command = ctx->curr;
6931 ctx->objmask = NULL;
6932 out->args.list.group =
6933 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6937 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
6938 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
6941 ctx->object = out->args.list.group + out->args.list.group_n++;
6942 ctx->objmask = NULL;
6946 /** Parse tokens for list all aged flows command. */
6948 parse_aged(struct context *ctx, const struct token *token,
6949 const char *str, unsigned int len,
6950 void *buf, unsigned int size)
6952 struct buffer *out = buf;
6954 /* Token name must match. */
6955 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6957 /* Nothing else to do if there is no buffer. */
6960 if (!out->command) {
6961 if (ctx->curr != AGED)
6963 if (sizeof(*out) > size)
6965 out->command = ctx->curr;
6968 ctx->objmask = NULL;
6970 if (ctx->curr == AGED_DESTROY)
6971 out->args.aged.destroy = 1;
6975 /** Parse tokens for isolate command. */
6977 parse_isolate(struct context *ctx, const struct token *token,
6978 const char *str, unsigned int len,
6979 void *buf, unsigned int size)
6981 struct buffer *out = buf;
6983 /* Token name must match. */
6984 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6986 /* Nothing else to do if there is no buffer. */
6989 if (!out->command) {
6990 if (ctx->curr != ISOLATE)
6992 if (sizeof(*out) > size)
6994 out->command = ctx->curr;
6997 ctx->objmask = NULL;
7003 parse_tunnel(struct context *ctx, const struct token *token,
7004 const char *str, unsigned int len,
7005 void *buf, unsigned int size)
7007 struct buffer *out = buf;
7009 /* Token name must match. */
7010 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7012 /* Nothing else to do if there is no buffer. */
7015 if (!out->command) {
7016 if (ctx->curr != TUNNEL)
7018 if (sizeof(*out) > size)
7020 out->command = ctx->curr;
7023 ctx->objmask = NULL;
7025 switch (ctx->curr) {
7029 case TUNNEL_DESTROY:
7031 out->command = ctx->curr;
7033 case TUNNEL_CREATE_TYPE:
7034 case TUNNEL_DESTROY_ID:
7035 ctx->object = &out->args.vc.tunnel_ops;
7044 * Parse signed/unsigned integers 8 to 64-bit long.
7046 * Last argument (ctx->args) is retrieved to determine integer type and
7050 parse_int(struct context *ctx, const struct token *token,
7051 const char *str, unsigned int len,
7052 void *buf, unsigned int size)
7054 const struct arg *arg = pop_args(ctx);
7059 /* Argument is expected. */
7064 (uintmax_t)strtoimax(str, &end, 0) :
7065 strtoumax(str, &end, 0);
7066 if (errno || (size_t)(end - str) != len)
7069 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
7070 (intmax_t)u > (intmax_t)arg->max)) ||
7071 (!arg->sign && (u < arg->min || u > arg->max))))
7076 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
7077 !arg_entry_bf_fill(ctx->objmask, -1, arg))
7081 buf = (uint8_t *)ctx->object + arg->offset;
7083 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
7087 case sizeof(uint8_t):
7088 *(uint8_t *)buf = u;
7090 case sizeof(uint16_t):
7091 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
7093 case sizeof(uint8_t [3]):
7094 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7096 ((uint8_t *)buf)[0] = u;
7097 ((uint8_t *)buf)[1] = u >> 8;
7098 ((uint8_t *)buf)[2] = u >> 16;
7102 ((uint8_t *)buf)[0] = u >> 16;
7103 ((uint8_t *)buf)[1] = u >> 8;
7104 ((uint8_t *)buf)[2] = u;
7106 case sizeof(uint32_t):
7107 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
7109 case sizeof(uint64_t):
7110 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
7115 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
7117 buf = (uint8_t *)ctx->objmask + arg->offset;
7122 push_args(ctx, arg);
7129 * Three arguments (ctx->args) are retrieved from the stack to store data,
7130 * its actual length and address (in that order).
7133 parse_string(struct context *ctx, const struct token *token,
7134 const char *str, unsigned int len,
7135 void *buf, unsigned int size)
7137 const struct arg *arg_data = pop_args(ctx);
7138 const struct arg *arg_len = pop_args(ctx);
7139 const struct arg *arg_addr = pop_args(ctx);
7140 char tmp[16]; /* Ought to be enough. */
7143 /* Arguments are expected. */
7147 push_args(ctx, arg_data);
7151 push_args(ctx, arg_len);
7152 push_args(ctx, arg_data);
7155 size = arg_data->size;
7156 /* Bit-mask fill is not supported. */
7157 if (arg_data->mask || size < len)
7161 /* Let parse_int() fill length information first. */
7162 ret = snprintf(tmp, sizeof(tmp), "%u", len);
7165 push_args(ctx, arg_len);
7166 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7171 buf = (uint8_t *)ctx->object + arg_data->offset;
7172 /* Output buffer is not necessarily NUL-terminated. */
7173 memcpy(buf, str, len);
7174 memset((uint8_t *)buf + len, 0x00, size - len);
7176 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7177 /* Save address if requested. */
7178 if (arg_addr->size) {
7179 memcpy((uint8_t *)ctx->object + arg_addr->offset,
7181 (uint8_t *)ctx->object + arg_data->offset
7185 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7187 (uint8_t *)ctx->objmask + arg_data->offset
7193 push_args(ctx, arg_addr);
7194 push_args(ctx, arg_len);
7195 push_args(ctx, arg_data);
7200 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
7206 /* Check input parameters */
7207 if ((src == NULL) ||
7213 /* Convert chars to bytes */
7214 for (i = 0, len = 0; i < *size; i += 2) {
7215 snprintf(tmp, 3, "%s", src + i);
7216 dst[len++] = strtoul(tmp, &c, 16);
7231 parse_hex(struct context *ctx, const struct token *token,
7232 const char *str, unsigned int len,
7233 void *buf, unsigned int size)
7235 const struct arg *arg_data = pop_args(ctx);
7236 const struct arg *arg_len = pop_args(ctx);
7237 const struct arg *arg_addr = pop_args(ctx);
7238 char tmp[16]; /* Ought to be enough. */
7240 unsigned int hexlen = len;
7241 unsigned int length = 256;
7242 uint8_t hex_tmp[length];
7244 /* Arguments are expected. */
7248 push_args(ctx, arg_data);
7252 push_args(ctx, arg_len);
7253 push_args(ctx, arg_data);
7256 size = arg_data->size;
7257 /* Bit-mask fill is not supported. */
7263 /* translate bytes string to array. */
7264 if (str[0] == '0' && ((str[1] == 'x') ||
7269 if (hexlen > length)
7271 ret = parse_hex_string(str, hex_tmp, &hexlen);
7274 /* Let parse_int() fill length information first. */
7275 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
7278 /* Save length if requested. */
7279 if (arg_len->size) {
7280 push_args(ctx, arg_len);
7281 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7287 buf = (uint8_t *)ctx->object + arg_data->offset;
7288 /* Output buffer is not necessarily NUL-terminated. */
7289 memcpy(buf, hex_tmp, hexlen);
7290 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
7292 memset((uint8_t *)ctx->objmask + arg_data->offset,
7294 /* Save address if requested. */
7295 if (arg_addr->size) {
7296 memcpy((uint8_t *)ctx->object + arg_addr->offset,
7298 (uint8_t *)ctx->object + arg_data->offset
7302 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7304 (uint8_t *)ctx->objmask + arg_data->offset
7310 push_args(ctx, arg_addr);
7311 push_args(ctx, arg_len);
7312 push_args(ctx, arg_data);
7318 * Parse a zero-ended string.
7321 parse_string0(struct context *ctx, const struct token *token __rte_unused,
7322 const char *str, unsigned int len,
7323 void *buf, unsigned int size)
7325 const struct arg *arg_data = pop_args(ctx);
7327 /* Arguments are expected. */
7330 size = arg_data->size;
7331 /* Bit-mask fill is not supported. */
7332 if (arg_data->mask || size < len + 1)
7336 buf = (uint8_t *)ctx->object + arg_data->offset;
7337 strncpy(buf, str, len);
7339 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7342 push_args(ctx, arg_data);
7347 * Parse a MAC address.
7349 * Last argument (ctx->args) is retrieved to determine storage size and
7353 parse_mac_addr(struct context *ctx, const struct token *token,
7354 const char *str, unsigned int len,
7355 void *buf, unsigned int size)
7357 const struct arg *arg = pop_args(ctx);
7358 struct rte_ether_addr tmp;
7362 /* Argument is expected. */
7366 /* Bit-mask fill is not supported. */
7367 if (arg->mask || size != sizeof(tmp))
7369 /* Only network endian is supported. */
7372 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
7373 if (ret < 0 || (unsigned int)ret != len)
7377 buf = (uint8_t *)ctx->object + arg->offset;
7378 memcpy(buf, &tmp, size);
7380 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7383 push_args(ctx, arg);
7388 * Parse an IPv4 address.
7390 * Last argument (ctx->args) is retrieved to determine storage size and
7394 parse_ipv4_addr(struct context *ctx, const struct token *token,
7395 const char *str, unsigned int len,
7396 void *buf, unsigned int size)
7398 const struct arg *arg = pop_args(ctx);
7403 /* Argument is expected. */
7407 /* Bit-mask fill is not supported. */
7408 if (arg->mask || size != sizeof(tmp))
7410 /* Only network endian is supported. */
7413 memcpy(str2, str, len);
7415 ret = inet_pton(AF_INET, str2, &tmp);
7417 /* Attempt integer parsing. */
7418 push_args(ctx, arg);
7419 return parse_int(ctx, token, str, len, buf, size);
7423 buf = (uint8_t *)ctx->object + arg->offset;
7424 memcpy(buf, &tmp, size);
7426 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7429 push_args(ctx, arg);
7434 * Parse an IPv6 address.
7436 * Last argument (ctx->args) is retrieved to determine storage size and
7440 parse_ipv6_addr(struct context *ctx, const struct token *token,
7441 const char *str, unsigned int len,
7442 void *buf, unsigned int size)
7444 const struct arg *arg = pop_args(ctx);
7446 struct in6_addr tmp;
7450 /* Argument is expected. */
7454 /* Bit-mask fill is not supported. */
7455 if (arg->mask || size != sizeof(tmp))
7457 /* Only network endian is supported. */
7460 memcpy(str2, str, len);
7462 ret = inet_pton(AF_INET6, str2, &tmp);
7467 buf = (uint8_t *)ctx->object + arg->offset;
7468 memcpy(buf, &tmp, size);
7470 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7473 push_args(ctx, arg);
7477 /** Boolean values (even indices stand for false). */
7478 static const char *const boolean_name[] = {
7488 * Parse a boolean value.
7490 * Last argument (ctx->args) is retrieved to determine storage size and
7494 parse_boolean(struct context *ctx, const struct token *token,
7495 const char *str, unsigned int len,
7496 void *buf, unsigned int size)
7498 const struct arg *arg = pop_args(ctx);
7502 /* Argument is expected. */
7505 for (i = 0; boolean_name[i]; ++i)
7506 if (!strcmp_partial(boolean_name[i], str, len))
7508 /* Process token as integer. */
7509 if (boolean_name[i])
7510 str = i & 1 ? "1" : "0";
7511 push_args(ctx, arg);
7512 ret = parse_int(ctx, token, str, strlen(str), buf, size);
7513 return ret > 0 ? (int)len : ret;
7516 /** Parse port and update context. */
7518 parse_port(struct context *ctx, const struct token *token,
7519 const char *str, unsigned int len,
7520 void *buf, unsigned int size)
7522 struct buffer *out = &(struct buffer){ .port = 0 };
7530 ctx->objmask = NULL;
7531 size = sizeof(*out);
7533 ret = parse_int(ctx, token, str, len, out, size);
7535 ctx->port = out->port;
7542 parse_ia_id2ptr(struct context *ctx, const struct token *token,
7543 const char *str, unsigned int len,
7544 void *buf, unsigned int size)
7546 struct rte_flow_action *action = ctx->object;
7554 ctx->objmask = NULL;
7555 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
7556 ctx->object = action;
7557 if (ret != (int)len)
7559 /* set indirect action */
7561 action->conf = port_action_handle_get_by_id(ctx->port, id);
7562 ret = (action->conf) ? ret : -1;
7567 /** Parse set command, initialize output buffer for subsequent tokens. */
7569 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
7570 const char *str, unsigned int len,
7571 void *buf, unsigned int size)
7573 struct buffer *out = buf;
7575 /* Token name must match. */
7576 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7578 /* Nothing else to do if there is no buffer. */
7581 /* Make sure buffer is large enough. */
7582 if (size < sizeof(*out))
7585 ctx->objmask = NULL;
7589 out->command = ctx->curr;
7590 /* For encap/decap we need is pattern */
7591 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7596 /** Parse set command, initialize output buffer for subsequent tokens. */
7598 parse_set_sample_action(struct context *ctx, const struct token *token,
7599 const char *str, unsigned int len,
7600 void *buf, unsigned int size)
7602 struct buffer *out = buf;
7604 /* Token name must match. */
7605 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7607 /* Nothing else to do if there is no buffer. */
7610 /* Make sure buffer is large enough. */
7611 if (size < sizeof(*out))
7614 ctx->objmask = NULL;
7618 out->command = ctx->curr;
7619 /* For sampler we need is actions */
7620 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7626 * Parse set raw_encap/raw_decap command,
7627 * initialize output buffer for subsequent tokens.
7630 parse_set_init(struct context *ctx, const struct token *token,
7631 const char *str, unsigned int len,
7632 void *buf, unsigned int size)
7634 struct buffer *out = buf;
7636 /* Token name must match. */
7637 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7639 /* Nothing else to do if there is no buffer. */
7642 /* Make sure buffer is large enough. */
7643 if (size < sizeof(*out))
7645 /* Initialize buffer. */
7646 memset(out, 0x00, sizeof(*out));
7647 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
7650 ctx->objmask = NULL;
7651 if (!out->command) {
7652 if (ctx->curr != SET)
7654 if (sizeof(*out) > size)
7656 out->command = ctx->curr;
7657 out->args.vc.data = (uint8_t *)out + size;
7658 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7664 /** No completion. */
7666 comp_none(struct context *ctx, const struct token *token,
7667 unsigned int ent, char *buf, unsigned int size)
7677 /** Complete boolean values. */
7679 comp_boolean(struct context *ctx, const struct token *token,
7680 unsigned int ent, char *buf, unsigned int size)
7686 for (i = 0; boolean_name[i]; ++i)
7687 if (buf && i == ent)
7688 return strlcpy(buf, boolean_name[i], size);
7694 /** Complete action names. */
7696 comp_action(struct context *ctx, const struct token *token,
7697 unsigned int ent, char *buf, unsigned int size)
7703 for (i = 0; next_action[i]; ++i)
7704 if (buf && i == ent)
7705 return strlcpy(buf, token_list[next_action[i]].name,
7712 /** Complete available ports. */
7714 comp_port(struct context *ctx, const struct token *token,
7715 unsigned int ent, char *buf, unsigned int size)
7722 RTE_ETH_FOREACH_DEV(p) {
7723 if (buf && i == ent)
7724 return snprintf(buf, size, "%u", p);
7732 /** Complete available rule IDs. */
7734 comp_rule_id(struct context *ctx, const struct token *token,
7735 unsigned int ent, char *buf, unsigned int size)
7738 struct rte_port *port;
7739 struct port_flow *pf;
7742 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
7743 ctx->port == (portid_t)RTE_PORT_ALL)
7745 port = &ports[ctx->port];
7746 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
7747 if (buf && i == ent)
7748 return snprintf(buf, size, "%u", pf->id);
7756 /** Complete type field for RSS action. */
7758 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
7759 unsigned int ent, char *buf, unsigned int size)
7765 for (i = 0; rss_type_table[i].str; ++i)
7770 return strlcpy(buf, rss_type_table[ent].str, size);
7772 return snprintf(buf, size, "end");
7776 /** Complete queue field for RSS action. */
7778 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
7779 unsigned int ent, char *buf, unsigned int size)
7786 return snprintf(buf, size, "%u", ent);
7788 return snprintf(buf, size, "end");
7792 /** Complete index number for set raw_encap/raw_decap commands. */
7794 comp_set_raw_index(struct context *ctx, const struct token *token,
7795 unsigned int ent, char *buf, unsigned int size)
7801 RTE_SET_USED(token);
7802 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
7803 if (buf && idx == ent)
7804 return snprintf(buf, size, "%u", idx);
7810 /** Complete index number for set raw_encap/raw_decap commands. */
7812 comp_set_sample_index(struct context *ctx, const struct token *token,
7813 unsigned int ent, char *buf, unsigned int size)
7819 RTE_SET_USED(token);
7820 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
7821 if (buf && idx == ent)
7822 return snprintf(buf, size, "%u", idx);
7828 /** Complete operation for modify_field command. */
7830 comp_set_modify_field_op(struct context *ctx, const struct token *token,
7831 unsigned int ent, char *buf, unsigned int size)
7836 RTE_SET_USED(token);
7837 for (idx = 0; modify_field_ops[idx]; ++idx)
7842 return strlcpy(buf, modify_field_ops[ent], size);
7846 /** Complete field id for modify_field command. */
7848 comp_set_modify_field_id(struct context *ctx, const struct token *token,
7849 unsigned int ent, char *buf, unsigned int size)
7854 RTE_SET_USED(token);
7855 for (idx = 0; modify_field_ids[idx]; ++idx)
7860 return strlcpy(buf, modify_field_ids[ent], size);
7864 /** Internal context. */
7865 static struct context cmd_flow_context;
7867 /** Global parser instance (cmdline API). */
7868 cmdline_parse_inst_t cmd_flow;
7869 cmdline_parse_inst_t cmd_set_raw;
7871 /** Initialize context. */
7873 cmd_flow_context_init(struct context *ctx)
7875 /* A full memset() is not necessary. */
7885 ctx->objmask = NULL;
7888 /** Parse a token (cmdline API). */
7890 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
7893 struct context *ctx = &cmd_flow_context;
7894 const struct token *token;
7895 const enum index *list;
7900 token = &token_list[ctx->curr];
7901 /* Check argument length. */
7904 for (len = 0; src[len]; ++len)
7905 if (src[len] == '#' || isspace(src[len]))
7909 /* Last argument and EOL detection. */
7910 for (i = len; src[i]; ++i)
7911 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
7913 else if (!isspace(src[i])) {
7918 if (src[i] == '\r' || src[i] == '\n') {
7922 /* Initialize context if necessary. */
7923 if (!ctx->next_num) {
7926 ctx->next[ctx->next_num++] = token->next[0];
7928 /* Process argument through candidates. */
7929 ctx->prev = ctx->curr;
7930 list = ctx->next[ctx->next_num - 1];
7931 for (i = 0; list[i]; ++i) {
7932 const struct token *next = &token_list[list[i]];
7935 ctx->curr = list[i];
7937 tmp = next->call(ctx, next, src, len, result, size);
7939 tmp = parse_default(ctx, next, src, len, result, size);
7940 if (tmp == -1 || tmp != len)
7948 /* Push subsequent tokens if any. */
7950 for (i = 0; token->next[i]; ++i) {
7951 if (ctx->next_num == RTE_DIM(ctx->next))
7953 ctx->next[ctx->next_num++] = token->next[i];
7955 /* Push arguments if any. */
7957 for (i = 0; token->args[i]; ++i) {
7958 if (ctx->args_num == RTE_DIM(ctx->args))
7960 ctx->args[ctx->args_num++] = token->args[i];
7965 /** Return number of completion entries (cmdline API). */
7967 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
7969 struct context *ctx = &cmd_flow_context;
7970 const struct token *token = &token_list[ctx->curr];
7971 const enum index *list;
7975 /* Count number of tokens in current list. */
7977 list = ctx->next[ctx->next_num - 1];
7979 list = token->next[0];
7980 for (i = 0; list[i]; ++i)
7985 * If there is a single token, use its completion callback, otherwise
7986 * return the number of entries.
7988 token = &token_list[list[0]];
7989 if (i == 1 && token->comp) {
7990 /* Save index for cmd_flow_get_help(). */
7991 ctx->prev = list[0];
7992 return token->comp(ctx, token, 0, NULL, 0);
7997 /** Return a completion entry (cmdline API). */
7999 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
8000 char *dst, unsigned int size)
8002 struct context *ctx = &cmd_flow_context;
8003 const struct token *token = &token_list[ctx->curr];
8004 const enum index *list;
8008 /* Count number of tokens in current list. */
8010 list = ctx->next[ctx->next_num - 1];
8012 list = token->next[0];
8013 for (i = 0; list[i]; ++i)
8017 /* If there is a single token, use its completion callback. */
8018 token = &token_list[list[0]];
8019 if (i == 1 && token->comp) {
8020 /* Save index for cmd_flow_get_help(). */
8021 ctx->prev = list[0];
8022 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
8024 /* Otherwise make sure the index is valid and use defaults. */
8027 token = &token_list[list[index]];
8028 strlcpy(dst, token->name, size);
8029 /* Save index for cmd_flow_get_help(). */
8030 ctx->prev = list[index];
8034 /** Populate help strings for current token (cmdline API). */
8036 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
8038 struct context *ctx = &cmd_flow_context;
8039 const struct token *token = &token_list[ctx->prev];
8044 /* Set token type and update global help with details. */
8045 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
8047 cmd_flow.help_str = token->help;
8049 cmd_flow.help_str = token->name;
8053 /** Token definition template (cmdline API). */
8054 static struct cmdline_token_hdr cmd_flow_token_hdr = {
8055 .ops = &(struct cmdline_token_ops){
8056 .parse = cmd_flow_parse,
8057 .complete_get_nb = cmd_flow_complete_get_nb,
8058 .complete_get_elt = cmd_flow_complete_get_elt,
8059 .get_help = cmd_flow_get_help,
8064 /** Populate the next dynamic token. */
8066 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
8067 cmdline_parse_token_hdr_t **hdr_inst)
8069 struct context *ctx = &cmd_flow_context;
8071 /* Always reinitialize context before requesting the first token. */
8072 if (!(hdr_inst - cmd_flow.tokens))
8073 cmd_flow_context_init(ctx);
8074 /* Return NULL when no more tokens are expected. */
8075 if (!ctx->next_num && ctx->curr) {
8079 /* Determine if command should end here. */
8080 if (ctx->eol && ctx->last && ctx->next_num) {
8081 const enum index *list = ctx->next[ctx->next_num - 1];
8084 for (i = 0; list[i]; ++i) {
8091 *hdr = &cmd_flow_token_hdr;
8094 /** Dispatch parsed buffer to function calls. */
8096 cmd_flow_parsed(const struct buffer *in)
8098 switch (in->command) {
8099 case INDIRECT_ACTION_CREATE:
8100 port_action_handle_create(
8101 in->port, in->args.vc.attr.group,
8102 &((const struct rte_flow_indir_action_conf) {
8103 .ingress = in->args.vc.attr.ingress,
8104 .egress = in->args.vc.attr.egress,
8105 .transfer = in->args.vc.attr.transfer,
8107 in->args.vc.actions);
8109 case INDIRECT_ACTION_DESTROY:
8110 port_action_handle_destroy(in->port,
8111 in->args.ia_destroy.action_id_n,
8112 in->args.ia_destroy.action_id);
8114 case INDIRECT_ACTION_UPDATE:
8115 port_action_handle_update(in->port, in->args.vc.attr.group,
8116 in->args.vc.actions);
8118 case INDIRECT_ACTION_QUERY:
8119 port_action_handle_query(in->port, in->args.ia.action_id);
8122 port_flow_validate(in->port, &in->args.vc.attr,
8123 in->args.vc.pattern, in->args.vc.actions,
8124 &in->args.vc.tunnel_ops);
8127 port_flow_create(in->port, &in->args.vc.attr,
8128 in->args.vc.pattern, in->args.vc.actions,
8129 &in->args.vc.tunnel_ops);
8132 port_flow_destroy(in->port, in->args.destroy.rule_n,
8133 in->args.destroy.rule);
8136 port_flow_flush(in->port);
8140 port_flow_dump(in->port, in->args.dump.mode,
8141 in->args.dump.rule, in->args.dump.file);
8144 port_flow_query(in->port, in->args.query.rule,
8145 &in->args.query.action);
8148 port_flow_list(in->port, in->args.list.group_n,
8149 in->args.list.group);
8152 port_flow_isolate(in->port, in->args.isolate.set);
8155 port_flow_aged(in->port, in->args.aged.destroy);
8158 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
8160 case TUNNEL_DESTROY:
8161 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
8164 port_flow_tunnel_list(in->port);
8167 port_meter_policy_add(in->port, in->args.policy.policy_id,
8168 in->args.vc.actions);
8175 /** Token generator and output processing callback (cmdline API). */
8177 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
8180 cmd_flow_tok(arg0, arg2);
8182 cmd_flow_parsed(arg0);
8185 /** Global parser instance (cmdline API). */
8186 cmdline_parse_inst_t cmd_flow = {
8188 .data = NULL, /**< Unused. */
8189 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
8192 }, /**< Tokens are returned by cmd_flow_tok(). */
8195 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
8198 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
8200 struct rte_ipv4_hdr *ipv4;
8201 struct rte_ether_hdr *eth;
8202 struct rte_ipv6_hdr *ipv6;
8203 struct rte_vxlan_hdr *vxlan;
8204 struct rte_vxlan_gpe_hdr *gpe;
8205 struct rte_flow_item_nvgre *nvgre;
8206 uint32_t ipv6_vtc_flow;
8208 switch (item->type) {
8209 case RTE_FLOW_ITEM_TYPE_ETH:
8210 eth = (struct rte_ether_hdr *)buf;
8212 eth->ether_type = rte_cpu_to_be_16(next_proto);
8214 case RTE_FLOW_ITEM_TYPE_IPV4:
8215 ipv4 = (struct rte_ipv4_hdr *)buf;
8216 if (!ipv4->version_ihl)
8217 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
8218 if (next_proto && ipv4->next_proto_id == 0)
8219 ipv4->next_proto_id = (uint8_t)next_proto;
8221 case RTE_FLOW_ITEM_TYPE_IPV6:
8222 ipv6 = (struct rte_ipv6_hdr *)buf;
8223 if (next_proto && ipv6->proto == 0)
8224 ipv6->proto = (uint8_t)next_proto;
8225 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
8226 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
8227 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
8228 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
8230 case RTE_FLOW_ITEM_TYPE_VXLAN:
8231 vxlan = (struct rte_vxlan_hdr *)buf;
8232 vxlan->vx_flags = 0x08;
8234 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8235 gpe = (struct rte_vxlan_gpe_hdr *)buf;
8236 gpe->vx_flags = 0x0C;
8238 case RTE_FLOW_ITEM_TYPE_NVGRE:
8239 nvgre = (struct rte_flow_item_nvgre *)buf;
8240 nvgre->protocol = rte_cpu_to_be_16(0x6558);
8241 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
8248 /** Helper of get item's default mask. */
8250 flow_item_default_mask(const struct rte_flow_item *item)
8252 const void *mask = NULL;
8253 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
8255 switch (item->type) {
8256 case RTE_FLOW_ITEM_TYPE_ANY:
8257 mask = &rte_flow_item_any_mask;
8259 case RTE_FLOW_ITEM_TYPE_VF:
8260 mask = &rte_flow_item_vf_mask;
8262 case RTE_FLOW_ITEM_TYPE_PORT_ID:
8263 mask = &rte_flow_item_port_id_mask;
8265 case RTE_FLOW_ITEM_TYPE_RAW:
8266 mask = &rte_flow_item_raw_mask;
8268 case RTE_FLOW_ITEM_TYPE_ETH:
8269 mask = &rte_flow_item_eth_mask;
8271 case RTE_FLOW_ITEM_TYPE_VLAN:
8272 mask = &rte_flow_item_vlan_mask;
8274 case RTE_FLOW_ITEM_TYPE_IPV4:
8275 mask = &rte_flow_item_ipv4_mask;
8277 case RTE_FLOW_ITEM_TYPE_IPV6:
8278 mask = &rte_flow_item_ipv6_mask;
8280 case RTE_FLOW_ITEM_TYPE_ICMP:
8281 mask = &rte_flow_item_icmp_mask;
8283 case RTE_FLOW_ITEM_TYPE_UDP:
8284 mask = &rte_flow_item_udp_mask;
8286 case RTE_FLOW_ITEM_TYPE_TCP:
8287 mask = &rte_flow_item_tcp_mask;
8289 case RTE_FLOW_ITEM_TYPE_SCTP:
8290 mask = &rte_flow_item_sctp_mask;
8292 case RTE_FLOW_ITEM_TYPE_VXLAN:
8293 mask = &rte_flow_item_vxlan_mask;
8295 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8296 mask = &rte_flow_item_vxlan_gpe_mask;
8298 case RTE_FLOW_ITEM_TYPE_E_TAG:
8299 mask = &rte_flow_item_e_tag_mask;
8301 case RTE_FLOW_ITEM_TYPE_NVGRE:
8302 mask = &rte_flow_item_nvgre_mask;
8304 case RTE_FLOW_ITEM_TYPE_MPLS:
8305 mask = &rte_flow_item_mpls_mask;
8307 case RTE_FLOW_ITEM_TYPE_GRE:
8308 mask = &rte_flow_item_gre_mask;
8310 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
8311 mask = &gre_key_default_mask;
8313 case RTE_FLOW_ITEM_TYPE_META:
8314 mask = &rte_flow_item_meta_mask;
8316 case RTE_FLOW_ITEM_TYPE_FUZZY:
8317 mask = &rte_flow_item_fuzzy_mask;
8319 case RTE_FLOW_ITEM_TYPE_GTP:
8320 mask = &rte_flow_item_gtp_mask;
8322 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
8323 mask = &rte_flow_item_gtp_psc_mask;
8325 case RTE_FLOW_ITEM_TYPE_GENEVE:
8326 mask = &rte_flow_item_geneve_mask;
8328 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
8329 mask = &rte_flow_item_geneve_opt_mask;
8331 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
8332 mask = &rte_flow_item_pppoe_proto_id_mask;
8334 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
8335 mask = &rte_flow_item_l2tpv3oip_mask;
8337 case RTE_FLOW_ITEM_TYPE_ESP:
8338 mask = &rte_flow_item_esp_mask;
8340 case RTE_FLOW_ITEM_TYPE_AH:
8341 mask = &rte_flow_item_ah_mask;
8343 case RTE_FLOW_ITEM_TYPE_PFCP:
8344 mask = &rte_flow_item_pfcp_mask;
8352 /** Dispatch parsed buffer to function calls. */
8354 cmd_set_raw_parsed_sample(const struct buffer *in)
8356 uint32_t n = in->args.vc.actions_n;
8358 struct rte_flow_action *action = NULL;
8359 struct rte_flow_action *data = NULL;
8360 const struct rte_flow_action_rss *rss = NULL;
8362 uint16_t idx = in->port; /* We borrow port field as index */
8363 uint32_t max_size = sizeof(struct rte_flow_action) *
8364 ACTION_SAMPLE_ACTIONS_NUM;
8366 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
8367 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
8368 memset(data, 0x00, max_size);
8369 for (; i <= n - 1; i++) {
8370 action = in->args.vc.actions + i;
8371 if (action->type == RTE_FLOW_ACTION_TYPE_END)
8373 switch (action->type) {
8374 case RTE_FLOW_ACTION_TYPE_MARK:
8375 size = sizeof(struct rte_flow_action_mark);
8376 rte_memcpy(&sample_mark[idx],
8377 (const void *)action->conf, size);
8378 action->conf = &sample_mark[idx];
8380 case RTE_FLOW_ACTION_TYPE_COUNT:
8381 size = sizeof(struct rte_flow_action_count);
8382 rte_memcpy(&sample_count[idx],
8383 (const void *)action->conf, size);
8384 action->conf = &sample_count[idx];
8386 case RTE_FLOW_ACTION_TYPE_QUEUE:
8387 size = sizeof(struct rte_flow_action_queue);
8388 rte_memcpy(&sample_queue[idx],
8389 (const void *)action->conf, size);
8390 action->conf = &sample_queue[idx];
8392 case RTE_FLOW_ACTION_TYPE_RSS:
8393 size = sizeof(struct rte_flow_action_rss);
8395 rte_memcpy(&sample_rss_data[idx].conf,
8396 (const void *)rss, size);
8397 if (rss->key_len && rss->key) {
8398 sample_rss_data[idx].conf.key =
8399 sample_rss_data[idx].key;
8400 rte_memcpy((void *)((uintptr_t)
8401 sample_rss_data[idx].conf.key),
8402 (const void *)rss->key,
8403 sizeof(uint8_t) * rss->key_len);
8405 if (rss->queue_num && rss->queue) {
8406 sample_rss_data[idx].conf.queue =
8407 sample_rss_data[idx].queue;
8408 rte_memcpy((void *)((uintptr_t)
8409 sample_rss_data[idx].conf.queue),
8410 (const void *)rss->queue,
8411 sizeof(uint16_t) * rss->queue_num);
8413 action->conf = &sample_rss_data[idx].conf;
8415 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
8416 size = sizeof(struct rte_flow_action_raw_encap);
8417 rte_memcpy(&sample_encap[idx],
8418 (const void *)action->conf, size);
8419 action->conf = &sample_encap[idx];
8421 case RTE_FLOW_ACTION_TYPE_PORT_ID:
8422 size = sizeof(struct rte_flow_action_port_id);
8423 rte_memcpy(&sample_port_id[idx],
8424 (const void *)action->conf, size);
8425 action->conf = &sample_port_id[idx];
8427 case RTE_FLOW_ACTION_TYPE_PF:
8429 case RTE_FLOW_ACTION_TYPE_VF:
8430 size = sizeof(struct rte_flow_action_vf);
8431 rte_memcpy(&sample_vf[idx],
8432 (const void *)action->conf, size);
8433 action->conf = &sample_vf[idx];
8435 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
8436 size = sizeof(struct rte_flow_action_vxlan_encap);
8437 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
8438 action->conf = &sample_vxlan_encap[idx].conf;
8440 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
8441 size = sizeof(struct rte_flow_action_nvgre_encap);
8442 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
8443 action->conf = &sample_nvgre_encap[idx];
8446 fprintf(stderr, "Error - Not supported action\n");
8449 rte_memcpy(data, action, sizeof(struct rte_flow_action));
8454 /** Dispatch parsed buffer to function calls. */
8456 cmd_set_raw_parsed(const struct buffer *in)
8458 uint32_t n = in->args.vc.pattern_n;
8460 struct rte_flow_item *item = NULL;
8462 uint8_t *data = NULL;
8463 uint8_t *data_tail = NULL;
8464 size_t *total_size = NULL;
8465 uint16_t upper_layer = 0;
8467 uint16_t idx = in->port; /* We borrow port field as index */
8468 int gtp_psc = -1; /* GTP PSC option index. */
8470 if (in->command == SET_SAMPLE_ACTIONS)
8471 return cmd_set_raw_parsed_sample(in);
8472 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
8473 in->command == SET_RAW_DECAP);
8474 if (in->command == SET_RAW_ENCAP) {
8475 total_size = &raw_encap_confs[idx].size;
8476 data = (uint8_t *)&raw_encap_confs[idx].data;
8478 total_size = &raw_decap_confs[idx].size;
8479 data = (uint8_t *)&raw_decap_confs[idx].data;
8482 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
8483 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
8484 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
8485 for (i = n - 1 ; i >= 0; --i) {
8486 const struct rte_flow_item_gtp *gtp;
8487 const struct rte_flow_item_geneve_opt *opt;
8489 item = in->args.vc.pattern + i;
8490 if (item->spec == NULL)
8491 item->spec = flow_item_default_mask(item);
8492 switch (item->type) {
8493 case RTE_FLOW_ITEM_TYPE_ETH:
8494 size = sizeof(struct rte_ether_hdr);
8496 case RTE_FLOW_ITEM_TYPE_VLAN:
8497 size = sizeof(struct rte_vlan_hdr);
8498 proto = RTE_ETHER_TYPE_VLAN;
8500 case RTE_FLOW_ITEM_TYPE_IPV4:
8501 size = sizeof(struct rte_ipv4_hdr);
8502 proto = RTE_ETHER_TYPE_IPV4;
8504 case RTE_FLOW_ITEM_TYPE_IPV6:
8505 size = sizeof(struct rte_ipv6_hdr);
8506 proto = RTE_ETHER_TYPE_IPV6;
8508 case RTE_FLOW_ITEM_TYPE_UDP:
8509 size = sizeof(struct rte_udp_hdr);
8512 case RTE_FLOW_ITEM_TYPE_TCP:
8513 size = sizeof(struct rte_tcp_hdr);
8516 case RTE_FLOW_ITEM_TYPE_VXLAN:
8517 size = sizeof(struct rte_vxlan_hdr);
8519 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8520 size = sizeof(struct rte_vxlan_gpe_hdr);
8522 case RTE_FLOW_ITEM_TYPE_GRE:
8523 size = sizeof(struct rte_gre_hdr);
8526 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
8527 size = sizeof(rte_be32_t);
8530 case RTE_FLOW_ITEM_TYPE_MPLS:
8531 size = sizeof(struct rte_mpls_hdr);
8534 case RTE_FLOW_ITEM_TYPE_NVGRE:
8535 size = sizeof(struct rte_flow_item_nvgre);
8538 case RTE_FLOW_ITEM_TYPE_GENEVE:
8539 size = sizeof(struct rte_geneve_hdr);
8541 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
8542 opt = (const struct rte_flow_item_geneve_opt *)
8544 size = offsetof(struct rte_flow_item_geneve_opt, data);
8545 if (opt->option_len && opt->data) {
8546 *total_size += opt->option_len *
8548 rte_memcpy(data_tail - (*total_size),
8550 opt->option_len * sizeof(uint32_t));
8553 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
8554 size = sizeof(rte_be32_t);
8557 case RTE_FLOW_ITEM_TYPE_ESP:
8558 size = sizeof(struct rte_esp_hdr);
8561 case RTE_FLOW_ITEM_TYPE_AH:
8562 size = sizeof(struct rte_flow_item_ah);
8565 case RTE_FLOW_ITEM_TYPE_GTP:
8567 size = sizeof(struct rte_gtp_hdr);
8570 if (gtp_psc != i + 1) {
8572 "Error - GTP PSC does not follow GTP\n");
8576 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
8577 /* Only E flag should be set. */
8579 "Error - GTP unsupported flags\n");
8582 struct rte_gtp_hdr_ext_word ext_word = {
8586 /* We have to add GTP header extra word. */
8587 *total_size += sizeof(ext_word);
8588 rte_memcpy(data_tail - (*total_size),
8589 &ext_word, sizeof(ext_word));
8591 size = sizeof(struct rte_gtp_hdr);
8593 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
8596 "Error - Multiple GTP PSC items\n");
8599 const struct rte_flow_item_gtp_psc
8607 psc.len = sizeof(psc);
8608 psc.pdu_type = opt->hdr.type;
8609 psc.qfi = opt->hdr.qfi;
8611 *total_size += sizeof(psc);
8612 rte_memcpy(data_tail - (*total_size),
8618 case RTE_FLOW_ITEM_TYPE_PFCP:
8619 size = sizeof(struct rte_flow_item_pfcp);
8622 fprintf(stderr, "Error - Not supported item\n");
8625 *total_size += size;
8626 rte_memcpy(data_tail - (*total_size), item->spec, size);
8627 /* update some fields which cannot be set by cmdline */
8628 update_fields((data_tail - (*total_size)), item,
8630 upper_layer = proto;
8632 if (verbose_level & 0x1)
8633 printf("total data size is %zu\n", (*total_size));
8634 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
8635 memmove(data, (data_tail - (*total_size)), *total_size);
8640 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
8643 /** Populate help strings for current token (cmdline API). */
8645 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
8648 struct context *ctx = &cmd_flow_context;
8649 const struct token *token = &token_list[ctx->prev];
8654 /* Set token type and update global help with details. */
8655 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
8657 cmd_set_raw.help_str = token->help;
8659 cmd_set_raw.help_str = token->name;
8663 /** Token definition template (cmdline API). */
8664 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
8665 .ops = &(struct cmdline_token_ops){
8666 .parse = cmd_flow_parse,
8667 .complete_get_nb = cmd_flow_complete_get_nb,
8668 .complete_get_elt = cmd_flow_complete_get_elt,
8669 .get_help = cmd_set_raw_get_help,
8674 /** Populate the next dynamic token. */
8676 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
8677 cmdline_parse_token_hdr_t **hdr_inst)
8679 struct context *ctx = &cmd_flow_context;
8681 /* Always reinitialize context before requesting the first token. */
8682 if (!(hdr_inst - cmd_set_raw.tokens)) {
8683 cmd_flow_context_init(ctx);
8684 ctx->curr = START_SET;
8686 /* Return NULL when no more tokens are expected. */
8687 if (!ctx->next_num && (ctx->curr != START_SET)) {
8691 /* Determine if command should end here. */
8692 if (ctx->eol && ctx->last && ctx->next_num) {
8693 const enum index *list = ctx->next[ctx->next_num - 1];
8696 for (i = 0; list[i]; ++i) {
8703 *hdr = &cmd_set_raw_token_hdr;
8706 /** Token generator and output processing callback (cmdline API). */
8708 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
8711 cmd_set_raw_tok(arg0, arg2);
8713 cmd_set_raw_parsed(arg0);
8716 /** Global parser instance (cmdline API). */
8717 cmdline_parse_inst_t cmd_set_raw = {
8718 .f = cmd_set_raw_cb,
8719 .data = NULL, /**< Unused. */
8720 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
8723 }, /**< Tokens are returned by cmd_flow_tok(). */
8726 /* *** display raw_encap/raw_decap buf */
8727 struct cmd_show_set_raw_result {
8728 cmdline_fixed_string_t cmd_show;
8729 cmdline_fixed_string_t cmd_what;
8730 cmdline_fixed_string_t cmd_all;
8735 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
8737 struct cmd_show_set_raw_result *res = parsed_result;
8738 uint16_t index = res->cmd_index;
8740 uint8_t *raw_data = NULL;
8741 size_t raw_size = 0;
8742 char title[16] = {0};
8746 if (!strcmp(res->cmd_all, "all")) {
8749 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
8750 fprintf(stderr, "index should be 0-%u\n",
8751 RAW_ENCAP_CONFS_MAX_NUM - 1);
8755 if (!strcmp(res->cmd_what, "raw_encap")) {
8756 raw_data = (uint8_t *)&raw_encap_confs[index].data;
8757 raw_size = raw_encap_confs[index].size;
8758 snprintf(title, 16, "\nindex: %u", index);
8759 rte_hexdump(stdout, title, raw_data, raw_size);
8761 raw_data = (uint8_t *)&raw_decap_confs[index].data;
8762 raw_size = raw_decap_confs[index].size;
8763 snprintf(title, 16, "\nindex: %u", index);
8764 rte_hexdump(stdout, title, raw_data, raw_size);
8766 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
8769 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
8770 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8772 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
8773 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8774 cmd_what, "raw_encap#raw_decap");
8775 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
8776 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
8777 cmd_index, RTE_UINT16);
8778 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
8779 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8781 cmdline_parse_inst_t cmd_show_set_raw = {
8782 .f = cmd_show_set_raw_parsed,
8784 .help_str = "show <raw_encap|raw_decap> <index>",
8786 (void *)&cmd_show_set_raw_cmd_show,
8787 (void *)&cmd_show_set_raw_cmd_what,
8788 (void *)&cmd_show_set_raw_cmd_index,
8792 cmdline_parse_inst_t cmd_show_set_raw_all = {
8793 .f = cmd_show_set_raw_parsed,
8795 .help_str = "show <raw_encap|raw_decap> all",
8797 (void *)&cmd_show_set_raw_cmd_show,
8798 (void *)&cmd_show_set_raw_cmd_what,
8799 (void *)&cmd_show_set_raw_cmd_all,