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,
309 ITEM_PORT_REPRESENTOR,
310 ITEM_PORT_REPRESENTOR_PORT_ID,
312 /* Validate/create actions. */
331 ACTION_RSS_FUNC_DEFAULT,
332 ACTION_RSS_FUNC_TOEPLITZ,
333 ACTION_RSS_FUNC_SIMPLE_XOR,
334 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
346 ACTION_PHY_PORT_ORIGINAL,
347 ACTION_PHY_PORT_INDEX,
349 ACTION_PORT_ID_ORIGINAL,
353 ACTION_METER_COLOR_TYPE,
354 ACTION_METER_COLOR_GREEN,
355 ACTION_METER_COLOR_YELLOW,
356 ACTION_METER_COLOR_RED,
358 ACTION_OF_SET_MPLS_TTL,
359 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
360 ACTION_OF_DEC_MPLS_TTL,
361 ACTION_OF_SET_NW_TTL,
362 ACTION_OF_SET_NW_TTL_NW_TTL,
363 ACTION_OF_DEC_NW_TTL,
364 ACTION_OF_COPY_TTL_OUT,
365 ACTION_OF_COPY_TTL_IN,
368 ACTION_OF_PUSH_VLAN_ETHERTYPE,
369 ACTION_OF_SET_VLAN_VID,
370 ACTION_OF_SET_VLAN_VID_VLAN_VID,
371 ACTION_OF_SET_VLAN_PCP,
372 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
374 ACTION_OF_POP_MPLS_ETHERTYPE,
376 ACTION_OF_PUSH_MPLS_ETHERTYPE,
383 ACTION_MPLSOGRE_ENCAP,
384 ACTION_MPLSOGRE_DECAP,
385 ACTION_MPLSOUDP_ENCAP,
386 ACTION_MPLSOUDP_DECAP,
388 ACTION_SET_IPV4_SRC_IPV4_SRC,
390 ACTION_SET_IPV4_DST_IPV4_DST,
392 ACTION_SET_IPV6_SRC_IPV6_SRC,
394 ACTION_SET_IPV6_DST_IPV6_DST,
396 ACTION_SET_TP_SRC_TP_SRC,
398 ACTION_SET_TP_DST_TP_DST,
404 ACTION_SET_MAC_SRC_MAC_SRC,
406 ACTION_SET_MAC_DST_MAC_DST,
408 ACTION_INC_TCP_SEQ_VALUE,
410 ACTION_DEC_TCP_SEQ_VALUE,
412 ACTION_INC_TCP_ACK_VALUE,
414 ACTION_DEC_TCP_ACK_VALUE,
417 ACTION_RAW_ENCAP_INDEX,
418 ACTION_RAW_ENCAP_INDEX_VALUE,
419 ACTION_RAW_DECAP_INDEX,
420 ACTION_RAW_DECAP_INDEX_VALUE,
423 ACTION_SET_TAG_INDEX,
426 ACTION_SET_META_DATA,
427 ACTION_SET_META_MASK,
428 ACTION_SET_IPV4_DSCP,
429 ACTION_SET_IPV4_DSCP_VALUE,
430 ACTION_SET_IPV6_DSCP,
431 ACTION_SET_IPV6_DSCP_VALUE,
437 ACTION_SAMPLE_INDEX_VALUE,
439 INDIRECT_ACTION_ID2PTR,
441 ACTION_MODIFY_FIELD_OP,
442 ACTION_MODIFY_FIELD_OP_VALUE,
443 ACTION_MODIFY_FIELD_DST_TYPE,
444 ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
445 ACTION_MODIFY_FIELD_DST_LEVEL,
446 ACTION_MODIFY_FIELD_DST_OFFSET,
447 ACTION_MODIFY_FIELD_SRC_TYPE,
448 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
449 ACTION_MODIFY_FIELD_SRC_LEVEL,
450 ACTION_MODIFY_FIELD_SRC_OFFSET,
451 ACTION_MODIFY_FIELD_SRC_VALUE,
452 ACTION_MODIFY_FIELD_WIDTH,
454 ACTION_CONNTRACK_UPDATE,
455 ACTION_CONNTRACK_UPDATE_DIR,
456 ACTION_CONNTRACK_UPDATE_CTX,
462 /** Maximum size for pattern in struct rte_flow_item_raw. */
463 #define ITEM_RAW_PATTERN_SIZE 40
465 /** Maximum size for GENEVE option data pattern in bytes. */
466 #define ITEM_GENEVE_OPT_DATA_SIZE 124
468 /** Storage size for struct rte_flow_item_raw including pattern. */
469 #define ITEM_RAW_SIZE \
470 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
472 /** Maximum number of queue indices in struct rte_flow_action_rss. */
473 #define ACTION_RSS_QUEUE_NUM 128
475 /** Storage for struct rte_flow_action_rss including external data. */
476 struct action_rss_data {
477 struct rte_flow_action_rss conf;
478 uint8_t key[RSS_HASH_KEY_LENGTH];
479 uint16_t queue[ACTION_RSS_QUEUE_NUM];
482 /** Maximum data size in struct rte_flow_action_raw_encap. */
483 #define ACTION_RAW_ENCAP_MAX_DATA 512
484 #define RAW_ENCAP_CONFS_MAX_NUM 8
486 /** Storage for struct rte_flow_action_raw_encap. */
487 struct raw_encap_conf {
488 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
489 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
493 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
495 /** Storage for struct rte_flow_action_raw_encap including external data. */
496 struct action_raw_encap_data {
497 struct rte_flow_action_raw_encap conf;
498 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
499 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
503 /** Storage for struct rte_flow_action_raw_decap. */
504 struct raw_decap_conf {
505 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
509 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
511 /** Storage for struct rte_flow_action_raw_decap including external data. */
512 struct action_raw_decap_data {
513 struct rte_flow_action_raw_decap conf;
514 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
518 struct vxlan_encap_conf vxlan_encap_conf = {
522 .vni = "\x00\x00\x00",
524 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
525 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
526 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
527 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
528 "\x00\x00\x00\x00\x00\x00\x00\x01",
529 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
530 "\x00\x00\x00\x00\x00\x00\x11\x11",
534 .eth_src = "\x00\x00\x00\x00\x00\x00",
535 .eth_dst = "\xff\xff\xff\xff\xff\xff",
538 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
539 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
541 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
542 struct action_vxlan_encap_data {
543 struct rte_flow_action_vxlan_encap conf;
544 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
545 struct rte_flow_item_eth item_eth;
546 struct rte_flow_item_vlan item_vlan;
548 struct rte_flow_item_ipv4 item_ipv4;
549 struct rte_flow_item_ipv6 item_ipv6;
551 struct rte_flow_item_udp item_udp;
552 struct rte_flow_item_vxlan item_vxlan;
555 struct nvgre_encap_conf nvgre_encap_conf = {
558 .tni = "\x00\x00\x00",
559 .ipv4_src = RTE_IPV4(127, 0, 0, 1),
560 .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
561 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
562 "\x00\x00\x00\x00\x00\x00\x00\x01",
563 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
564 "\x00\x00\x00\x00\x00\x00\x11\x11",
566 .eth_src = "\x00\x00\x00\x00\x00\x00",
567 .eth_dst = "\xff\xff\xff\xff\xff\xff",
570 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
571 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
573 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
574 struct action_nvgre_encap_data {
575 struct rte_flow_action_nvgre_encap conf;
576 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
577 struct rte_flow_item_eth item_eth;
578 struct rte_flow_item_vlan item_vlan;
580 struct rte_flow_item_ipv4 item_ipv4;
581 struct rte_flow_item_ipv6 item_ipv6;
583 struct rte_flow_item_nvgre item_nvgre;
586 struct l2_encap_conf l2_encap_conf;
588 struct l2_decap_conf l2_decap_conf;
590 struct mplsogre_encap_conf mplsogre_encap_conf;
592 struct mplsogre_decap_conf mplsogre_decap_conf;
594 struct mplsoudp_encap_conf mplsoudp_encap_conf;
596 struct mplsoudp_decap_conf mplsoudp_decap_conf;
598 struct rte_flow_action_conntrack conntrack_context;
600 #define ACTION_SAMPLE_ACTIONS_NUM 10
601 #define RAW_SAMPLE_CONFS_MAX_NUM 8
602 /** Storage for struct rte_flow_action_sample including external data. */
603 struct action_sample_data {
604 struct rte_flow_action_sample conf;
607 /** Storage for struct rte_flow_action_sample. */
608 struct raw_sample_conf {
609 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
611 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
612 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
613 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
614 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
615 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
616 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
617 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
618 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
619 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
620 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
622 static const char *const modify_field_ops[] = {
623 "set", "add", "sub", NULL
626 static const char *const modify_field_ids[] = {
627 "start", "mac_dst", "mac_src",
628 "vlan_type", "vlan_id", "mac_type",
629 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
630 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
631 "tcp_port_src", "tcp_port_dst",
632 "tcp_seq_num", "tcp_ack_num", "tcp_flags",
633 "udp_port_src", "udp_port_dst",
634 "vxlan_vni", "geneve_vni", "gtp_teid",
635 "tag", "mark", "meta", "pointer", "value", NULL
638 /** Maximum number of subsequent tokens and arguments on the stack. */
639 #define CTX_STACK_SIZE 16
641 /** Parser context. */
643 /** Stack of subsequent token lists to process. */
644 const enum index *next[CTX_STACK_SIZE];
645 /** Arguments for stacked tokens. */
646 const void *args[CTX_STACK_SIZE];
647 enum index curr; /**< Current token index. */
648 enum index prev; /**< Index of the last token seen. */
649 int next_num; /**< Number of entries in next[]. */
650 int args_num; /**< Number of entries in args[]. */
651 uint32_t eol:1; /**< EOL has been detected. */
652 uint32_t last:1; /**< No more arguments. */
653 portid_t port; /**< Current port ID (for completions). */
654 uint32_t objdata; /**< Object-specific data. */
655 void *object; /**< Address of current object for relative offsets. */
656 void *objmask; /**< Object a full mask must be written to. */
659 /** Token argument. */
661 uint32_t hton:1; /**< Use network byte ordering. */
662 uint32_t sign:1; /**< Value is signed. */
663 uint32_t bounded:1; /**< Value is bounded. */
664 uintmax_t min; /**< Minimum value if bounded. */
665 uintmax_t max; /**< Maximum value if bounded. */
666 uint32_t offset; /**< Relative offset from ctx->object. */
667 uint32_t size; /**< Field size. */
668 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
671 /** Parser token definition. */
673 /** Type displayed during completion (defaults to "TOKEN"). */
675 /** Help displayed during completion (defaults to token name). */
677 /** Private data used by parser functions. */
680 * Lists of subsequent tokens to push on the stack. Each call to the
681 * parser consumes the last entry of that stack.
683 const enum index *const *next;
684 /** Arguments stack for subsequent tokens that need them. */
685 const struct arg *const *args;
687 * Token-processing callback, returns -1 in case of error, the
688 * length of the matched string otherwise. If NULL, attempts to
689 * match the token name.
691 * If buf is not NULL, the result should be stored in it according
692 * to context. An error is returned if not large enough.
694 int (*call)(struct context *ctx, const struct token *token,
695 const char *str, unsigned int len,
696 void *buf, unsigned int size);
698 * Callback that provides possible values for this token, used for
699 * completion. Returns -1 in case of error, the number of possible
700 * values otherwise. If NULL, the token name is used.
702 * If buf is not NULL, entry index ent is written to buf and the
703 * full length of the entry is returned (same behavior as
706 int (*comp)(struct context *ctx, const struct token *token,
707 unsigned int ent, char *buf, unsigned int size);
708 /** Mandatory token name, no default value. */
712 /** Static initializer for the next field. */
713 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
715 /** Static initializer for a NEXT() entry. */
716 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
718 /** Static initializer for the args field. */
719 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
721 /** Static initializer for ARGS() to target a field. */
722 #define ARGS_ENTRY(s, f) \
723 (&(const struct arg){ \
724 .offset = offsetof(s, f), \
725 .size = sizeof(((s *)0)->f), \
728 /** Static initializer for ARGS() to target a bit-field. */
729 #define ARGS_ENTRY_BF(s, f, b) \
730 (&(const struct arg){ \
732 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
735 /** Static initializer for ARGS() to target a field with limits. */
736 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
737 (&(const struct arg){ \
741 .offset = offsetof(s, f), \
742 .size = sizeof(((s *)0)->f), \
745 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
746 #define ARGS_ENTRY_MASK(s, f, m) \
747 (&(const struct arg){ \
748 .offset = offsetof(s, f), \
749 .size = sizeof(((s *)0)->f), \
750 .mask = (const void *)(m), \
753 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
754 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
755 (&(const struct arg){ \
757 .offset = offsetof(s, f), \
758 .size = sizeof(((s *)0)->f), \
759 .mask = (const void *)(m), \
762 /** Static initializer for ARGS() to target a pointer. */
763 #define ARGS_ENTRY_PTR(s, f) \
764 (&(const struct arg){ \
765 .size = sizeof(*((s *)0)->f), \
768 /** Static initializer for ARGS() with arbitrary offset and size. */
769 #define ARGS_ENTRY_ARB(o, s) \
770 (&(const struct arg){ \
775 /** Same as ARGS_ENTRY_ARB() with bounded values. */
776 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
777 (&(const struct arg){ \
785 /** Same as ARGS_ENTRY() using network byte ordering. */
786 #define ARGS_ENTRY_HTON(s, f) \
787 (&(const struct arg){ \
789 .offset = offsetof(s, f), \
790 .size = sizeof(((s *)0)->f), \
793 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
794 #define ARG_ENTRY_HTON(s) \
795 (&(const struct arg){ \
801 /** Parser output buffer layout expected by cmd_flow_parsed(). */
803 enum index command; /**< Flow command. */
804 portid_t port; /**< Affected port ID. */
808 uint32_t action_id_n;
809 } ia_destroy; /**< Indirect action destroy arguments. */
812 } ia; /* Indirect action query arguments */
814 struct rte_flow_attr attr;
815 struct tunnel_ops tunnel_ops;
816 struct rte_flow_item *pattern;
817 struct rte_flow_action *actions;
821 } vc; /**< Validate/create arguments. */
825 } destroy; /**< Destroy arguments. */
830 } dump; /**< Dump arguments. */
833 struct rte_flow_action action;
834 } query; /**< Query arguments. */
838 } list; /**< List arguments. */
841 } isolate; /**< Isolated mode arguments. */
844 } aged; /**< Aged arguments. */
847 } policy;/**< Policy arguments. */
848 } args; /**< Command arguments. */
851 /** Private data for pattern items. */
852 struct parse_item_priv {
853 enum rte_flow_item_type type; /**< Item type. */
854 uint32_t size; /**< Size of item specification structure. */
857 #define PRIV_ITEM(t, s) \
858 (&(const struct parse_item_priv){ \
859 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
863 /** Private data for actions. */
864 struct parse_action_priv {
865 enum rte_flow_action_type type; /**< Action type. */
866 uint32_t size; /**< Size of action configuration structure. */
869 #define PRIV_ACTION(t, s) \
870 (&(const struct parse_action_priv){ \
871 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
875 static const enum index next_ia_create_attr[] = {
876 INDIRECT_ACTION_CREATE_ID,
877 INDIRECT_ACTION_INGRESS,
878 INDIRECT_ACTION_EGRESS,
879 INDIRECT_ACTION_TRANSFER,
880 INDIRECT_ACTION_SPEC,
884 static const enum index next_dump_subcmd[] = {
890 static const enum index next_ia_subcmd[] = {
891 INDIRECT_ACTION_CREATE,
892 INDIRECT_ACTION_UPDATE,
893 INDIRECT_ACTION_DESTROY,
894 INDIRECT_ACTION_QUERY,
898 static const enum index next_vc_attr[] = {
910 static const enum index next_destroy_attr[] = {
916 static const enum index next_dump_attr[] = {
922 static const enum index next_list_attr[] = {
928 static const enum index next_aged_attr[] = {
934 static const enum index next_ia_destroy_attr[] = {
935 INDIRECT_ACTION_DESTROY_ID,
940 static const enum index item_param[] = {
949 static const enum index next_item[] = {
986 ITEM_ICMP6_ND_OPT_SLA_ETH,
987 ITEM_ICMP6_ND_OPT_TLA_ETH,
1004 ITEM_PORT_REPRESENTOR,
1009 static const enum index item_fuzzy[] = {
1015 static const enum index item_any[] = {
1021 static const enum index item_vf[] = {
1027 static const enum index item_phy_port[] = {
1028 ITEM_PHY_PORT_INDEX,
1033 static const enum index item_port_id[] = {
1039 static const enum index item_mark[] = {
1045 static const enum index item_raw[] = {
1055 static const enum index item_eth[] = {
1064 static const enum index item_vlan[] = {
1069 ITEM_VLAN_INNER_TYPE,
1070 ITEM_VLAN_HAS_MORE_VLAN,
1075 static const enum index item_ipv4[] = {
1079 ITEM_IPV4_FRAGMENT_OFFSET,
1088 static const enum index item_ipv6[] = {
1095 ITEM_IPV6_HAS_FRAG_EXT,
1100 static const enum index item_icmp[] = {
1109 static const enum index item_udp[] = {
1116 static const enum index item_tcp[] = {
1124 static const enum index item_sctp[] = {
1133 static const enum index item_vxlan[] = {
1135 ITEM_VXLAN_LAST_RSVD,
1140 static const enum index item_e_tag[] = {
1141 ITEM_E_TAG_GRP_ECID_B,
1146 static const enum index item_nvgre[] = {
1152 static const enum index item_mpls[] = {
1160 static const enum index item_gre[] = {
1162 ITEM_GRE_C_RSVD0_VER,
1170 static const enum index item_gre_key[] = {
1176 static const enum index item_gtp[] = {
1184 static const enum index item_geneve[] = {
1192 static const enum index item_vxlan_gpe[] = {
1198 static const enum index item_arp_eth_ipv4[] = {
1199 ITEM_ARP_ETH_IPV4_SHA,
1200 ITEM_ARP_ETH_IPV4_SPA,
1201 ITEM_ARP_ETH_IPV4_THA,
1202 ITEM_ARP_ETH_IPV4_TPA,
1207 static const enum index item_ipv6_ext[] = {
1208 ITEM_IPV6_EXT_NEXT_HDR,
1213 static const enum index item_ipv6_frag_ext[] = {
1214 ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1215 ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1216 ITEM_IPV6_FRAG_EXT_ID,
1221 static const enum index item_icmp6[] = {
1228 static const enum index item_icmp6_nd_ns[] = {
1229 ITEM_ICMP6_ND_NS_TARGET_ADDR,
1234 static const enum index item_icmp6_nd_na[] = {
1235 ITEM_ICMP6_ND_NA_TARGET_ADDR,
1240 static const enum index item_icmp6_nd_opt[] = {
1241 ITEM_ICMP6_ND_OPT_TYPE,
1246 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1247 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1252 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1253 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1258 static const enum index item_meta[] = {
1264 static const enum index item_gtp_psc[] = {
1271 static const enum index item_pppoed[] = {
1277 static const enum index item_pppoes[] = {
1283 static const enum index item_pppoe_proto_id[] = {
1288 static const enum index item_higig2[] = {
1289 ITEM_HIGIG2_CLASSIFICATION,
1295 static const enum index item_esp[] = {
1301 static const enum index item_ah[] = {
1307 static const enum index item_pfcp[] = {
1314 static const enum index next_set_raw[] = {
1320 static const enum index item_tag[] = {
1327 static const enum index item_l2tpv3oip[] = {
1328 ITEM_L2TPV3OIP_SESSION_ID,
1333 static const enum index item_ecpri[] = {
1339 static const enum index item_ecpri_common[] = {
1340 ITEM_ECPRI_COMMON_TYPE,
1344 static const enum index item_ecpri_common_type[] = {
1345 ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1346 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1347 ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1351 static const enum index item_geneve_opt[] = {
1352 ITEM_GENEVE_OPT_CLASS,
1353 ITEM_GENEVE_OPT_TYPE,
1354 ITEM_GENEVE_OPT_LENGTH,
1355 ITEM_GENEVE_OPT_DATA,
1360 static const enum index item_integrity[] = {
1361 ITEM_INTEGRITY_LEVEL,
1362 ITEM_INTEGRITY_VALUE,
1366 static const enum index item_integrity_lv[] = {
1367 ITEM_INTEGRITY_LEVEL,
1368 ITEM_INTEGRITY_VALUE,
1373 static const enum index item_port_representor[] = {
1374 ITEM_PORT_REPRESENTOR_PORT_ID,
1379 static const enum index next_action[] = {
1396 ACTION_OF_SET_MPLS_TTL,
1397 ACTION_OF_DEC_MPLS_TTL,
1398 ACTION_OF_SET_NW_TTL,
1399 ACTION_OF_DEC_NW_TTL,
1400 ACTION_OF_COPY_TTL_OUT,
1401 ACTION_OF_COPY_TTL_IN,
1403 ACTION_OF_PUSH_VLAN,
1404 ACTION_OF_SET_VLAN_VID,
1405 ACTION_OF_SET_VLAN_PCP,
1407 ACTION_OF_PUSH_MPLS,
1414 ACTION_MPLSOGRE_ENCAP,
1415 ACTION_MPLSOGRE_DECAP,
1416 ACTION_MPLSOUDP_ENCAP,
1417 ACTION_MPLSOUDP_DECAP,
1418 ACTION_SET_IPV4_SRC,
1419 ACTION_SET_IPV4_DST,
1420 ACTION_SET_IPV6_SRC,
1421 ACTION_SET_IPV6_DST,
1437 ACTION_SET_IPV4_DSCP,
1438 ACTION_SET_IPV6_DSCP,
1442 ACTION_MODIFY_FIELD,
1444 ACTION_CONNTRACK_UPDATE,
1448 static const enum index action_mark[] = {
1454 static const enum index action_queue[] = {
1460 static const enum index action_count[] = {
1466 static const enum index action_rss[] = {
1477 static const enum index action_vf[] = {
1484 static const enum index action_phy_port[] = {
1485 ACTION_PHY_PORT_ORIGINAL,
1486 ACTION_PHY_PORT_INDEX,
1491 static const enum index action_port_id[] = {
1492 ACTION_PORT_ID_ORIGINAL,
1498 static const enum index action_meter[] = {
1504 static const enum index action_meter_color[] = {
1505 ACTION_METER_COLOR_TYPE,
1510 static const enum index action_of_set_mpls_ttl[] = {
1511 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1516 static const enum index action_of_set_nw_ttl[] = {
1517 ACTION_OF_SET_NW_TTL_NW_TTL,
1522 static const enum index action_of_push_vlan[] = {
1523 ACTION_OF_PUSH_VLAN_ETHERTYPE,
1528 static const enum index action_of_set_vlan_vid[] = {
1529 ACTION_OF_SET_VLAN_VID_VLAN_VID,
1534 static const enum index action_of_set_vlan_pcp[] = {
1535 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1540 static const enum index action_of_pop_mpls[] = {
1541 ACTION_OF_POP_MPLS_ETHERTYPE,
1546 static const enum index action_of_push_mpls[] = {
1547 ACTION_OF_PUSH_MPLS_ETHERTYPE,
1552 static const enum index action_set_ipv4_src[] = {
1553 ACTION_SET_IPV4_SRC_IPV4_SRC,
1558 static const enum index action_set_mac_src[] = {
1559 ACTION_SET_MAC_SRC_MAC_SRC,
1564 static const enum index action_set_ipv4_dst[] = {
1565 ACTION_SET_IPV4_DST_IPV4_DST,
1570 static const enum index action_set_ipv6_src[] = {
1571 ACTION_SET_IPV6_SRC_IPV6_SRC,
1576 static const enum index action_set_ipv6_dst[] = {
1577 ACTION_SET_IPV6_DST_IPV6_DST,
1582 static const enum index action_set_tp_src[] = {
1583 ACTION_SET_TP_SRC_TP_SRC,
1588 static const enum index action_set_tp_dst[] = {
1589 ACTION_SET_TP_DST_TP_DST,
1594 static const enum index action_set_ttl[] = {
1600 static const enum index action_jump[] = {
1606 static const enum index action_set_mac_dst[] = {
1607 ACTION_SET_MAC_DST_MAC_DST,
1612 static const enum index action_inc_tcp_seq[] = {
1613 ACTION_INC_TCP_SEQ_VALUE,
1618 static const enum index action_dec_tcp_seq[] = {
1619 ACTION_DEC_TCP_SEQ_VALUE,
1624 static const enum index action_inc_tcp_ack[] = {
1625 ACTION_INC_TCP_ACK_VALUE,
1630 static const enum index action_dec_tcp_ack[] = {
1631 ACTION_DEC_TCP_ACK_VALUE,
1636 static const enum index action_raw_encap[] = {
1637 ACTION_RAW_ENCAP_INDEX,
1642 static const enum index action_raw_decap[] = {
1643 ACTION_RAW_DECAP_INDEX,
1648 static const enum index action_set_tag[] = {
1649 ACTION_SET_TAG_DATA,
1650 ACTION_SET_TAG_INDEX,
1651 ACTION_SET_TAG_MASK,
1656 static const enum index action_set_meta[] = {
1657 ACTION_SET_META_DATA,
1658 ACTION_SET_META_MASK,
1663 static const enum index action_set_ipv4_dscp[] = {
1664 ACTION_SET_IPV4_DSCP_VALUE,
1669 static const enum index action_set_ipv6_dscp[] = {
1670 ACTION_SET_IPV6_DSCP_VALUE,
1675 static const enum index action_age[] = {
1682 static const enum index action_sample[] = {
1684 ACTION_SAMPLE_RATIO,
1685 ACTION_SAMPLE_INDEX,
1690 static const enum index next_action_sample[] = {
1703 static const enum index action_modify_field_dst[] = {
1704 ACTION_MODIFY_FIELD_DST_LEVEL,
1705 ACTION_MODIFY_FIELD_DST_OFFSET,
1706 ACTION_MODIFY_FIELD_SRC_TYPE,
1710 static const enum index action_modify_field_src[] = {
1711 ACTION_MODIFY_FIELD_SRC_LEVEL,
1712 ACTION_MODIFY_FIELD_SRC_OFFSET,
1713 ACTION_MODIFY_FIELD_SRC_VALUE,
1714 ACTION_MODIFY_FIELD_WIDTH,
1718 static const enum index action_update_conntrack[] = {
1719 ACTION_CONNTRACK_UPDATE_DIR,
1720 ACTION_CONNTRACK_UPDATE_CTX,
1725 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1726 const char *, unsigned int,
1727 void *, unsigned int);
1728 static int parse_set_sample_action(struct context *, const struct token *,
1729 const char *, unsigned int,
1730 void *, unsigned int);
1731 static int parse_set_init(struct context *, const struct token *,
1732 const char *, unsigned int,
1733 void *, unsigned int);
1734 static int parse_init(struct context *, const struct token *,
1735 const char *, unsigned int,
1736 void *, unsigned int);
1737 static int parse_vc(struct context *, const struct token *,
1738 const char *, unsigned int,
1739 void *, unsigned int);
1740 static int parse_vc_spec(struct context *, const struct token *,
1741 const char *, unsigned int, void *, unsigned int);
1742 static int parse_vc_conf(struct context *, const struct token *,
1743 const char *, unsigned int, void *, unsigned int);
1744 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1745 const char *, unsigned int,
1746 void *, unsigned int);
1747 static int parse_vc_action_meter_color_type(struct context *,
1748 const struct token *,
1749 const char *, unsigned int, void *,
1751 static int parse_vc_action_rss(struct context *, const struct token *,
1752 const char *, unsigned int, void *,
1754 static int parse_vc_action_rss_func(struct context *, const struct token *,
1755 const char *, unsigned int, void *,
1757 static int parse_vc_action_rss_type(struct context *, const struct token *,
1758 const char *, unsigned int, void *,
1760 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1761 const char *, unsigned int, void *,
1763 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1764 const char *, unsigned int, void *,
1766 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1767 const char *, unsigned int, void *,
1769 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1770 const char *, unsigned int, void *,
1772 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1773 const char *, unsigned int, void *,
1775 static int parse_vc_action_mplsogre_encap(struct context *,
1776 const struct token *, const char *,
1777 unsigned int, void *, unsigned int);
1778 static int parse_vc_action_mplsogre_decap(struct context *,
1779 const struct token *, const char *,
1780 unsigned int, void *, unsigned int);
1781 static int parse_vc_action_mplsoudp_encap(struct context *,
1782 const struct token *, const char *,
1783 unsigned int, void *, unsigned int);
1784 static int parse_vc_action_mplsoudp_decap(struct context *,
1785 const struct token *, const char *,
1786 unsigned int, void *, unsigned int);
1787 static int parse_vc_action_raw_encap(struct context *,
1788 const struct token *, const char *,
1789 unsigned int, void *, unsigned int);
1790 static int parse_vc_action_raw_decap(struct context *,
1791 const struct token *, const char *,
1792 unsigned int, void *, unsigned int);
1793 static int parse_vc_action_raw_encap_index(struct context *,
1794 const struct token *, const char *,
1795 unsigned int, void *, unsigned int);
1796 static int parse_vc_action_raw_decap_index(struct context *,
1797 const struct token *, const char *,
1798 unsigned int, void *, unsigned int);
1799 static int parse_vc_action_set_meta(struct context *ctx,
1800 const struct token *token, const char *str,
1801 unsigned int len, void *buf,
1803 static int parse_vc_action_sample(struct context *ctx,
1804 const struct token *token, const char *str,
1805 unsigned int len, void *buf,
1808 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
1809 const char *str, unsigned int len, void *buf,
1812 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
1813 const char *str, unsigned int len, void *buf,
1816 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
1817 const char *str, unsigned int len, void *buf,
1820 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
1821 const char *str, unsigned int len, void *buf,
1823 static int parse_destroy(struct context *, const struct token *,
1824 const char *, unsigned int,
1825 void *, unsigned int);
1826 static int parse_flush(struct context *, const struct token *,
1827 const char *, unsigned int,
1828 void *, unsigned int);
1829 static int parse_dump(struct context *, const struct token *,
1830 const char *, unsigned int,
1831 void *, unsigned int);
1832 static int parse_query(struct context *, const struct token *,
1833 const char *, unsigned int,
1834 void *, unsigned int);
1835 static int parse_action(struct context *, const struct token *,
1836 const char *, unsigned int,
1837 void *, unsigned int);
1838 static int parse_list(struct context *, const struct token *,
1839 const char *, unsigned int,
1840 void *, unsigned int);
1841 static int parse_aged(struct context *, const struct token *,
1842 const char *, unsigned int,
1843 void *, unsigned int);
1844 static int parse_isolate(struct context *, const struct token *,
1845 const char *, unsigned int,
1846 void *, unsigned int);
1847 static int parse_tunnel(struct context *, const struct token *,
1848 const char *, unsigned int,
1849 void *, unsigned int);
1850 static int parse_int(struct context *, const struct token *,
1851 const char *, unsigned int,
1852 void *, unsigned int);
1853 static int parse_prefix(struct context *, const struct token *,
1854 const char *, unsigned int,
1855 void *, unsigned int);
1856 static int parse_boolean(struct context *, const struct token *,
1857 const char *, unsigned int,
1858 void *, unsigned int);
1859 static int parse_string(struct context *, const struct token *,
1860 const char *, unsigned int,
1861 void *, unsigned int);
1862 static int parse_hex(struct context *ctx, const struct token *token,
1863 const char *str, unsigned int len,
1864 void *buf, unsigned int size);
1865 static int parse_string0(struct context *, const struct token *,
1866 const char *, unsigned int,
1867 void *, unsigned int);
1868 static int parse_mac_addr(struct context *, const struct token *,
1869 const char *, unsigned int,
1870 void *, unsigned int);
1871 static int parse_ipv4_addr(struct context *, const struct token *,
1872 const char *, unsigned int,
1873 void *, unsigned int);
1874 static int parse_ipv6_addr(struct context *, const struct token *,
1875 const char *, unsigned int,
1876 void *, unsigned int);
1877 static int parse_port(struct context *, const struct token *,
1878 const char *, unsigned int,
1879 void *, unsigned int);
1880 static int parse_ia(struct context *, const struct token *,
1881 const char *, unsigned int,
1882 void *, unsigned int);
1883 static int parse_ia_destroy(struct context *ctx, const struct token *token,
1884 const char *str, unsigned int len,
1885 void *buf, unsigned int size);
1886 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
1887 const char *str, unsigned int len, void *buf,
1889 static int parse_mp(struct context *, const struct token *,
1890 const char *, unsigned int,
1891 void *, unsigned int);
1892 static int comp_none(struct context *, const struct token *,
1893 unsigned int, char *, unsigned int);
1894 static int comp_boolean(struct context *, const struct token *,
1895 unsigned int, char *, unsigned int);
1896 static int comp_action(struct context *, const struct token *,
1897 unsigned int, char *, unsigned int);
1898 static int comp_port(struct context *, const struct token *,
1899 unsigned int, char *, unsigned int);
1900 static int comp_rule_id(struct context *, const struct token *,
1901 unsigned int, char *, unsigned int);
1902 static int comp_vc_action_rss_type(struct context *, const struct token *,
1903 unsigned int, char *, unsigned int);
1904 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1905 unsigned int, char *, unsigned int);
1906 static int comp_set_raw_index(struct context *, const struct token *,
1907 unsigned int, char *, unsigned int);
1908 static int comp_set_sample_index(struct context *, const struct token *,
1909 unsigned int, char *, unsigned int);
1910 static int comp_set_modify_field_op(struct context *, const struct token *,
1911 unsigned int, char *, unsigned int);
1912 static int comp_set_modify_field_id(struct context *, const struct token *,
1913 unsigned int, char *, unsigned int);
1915 /** Token definitions. */
1916 static const struct token token_list[] = {
1917 /* Special tokens. */
1920 .help = "null entry, abused as the entry point",
1921 .next = NEXT(NEXT_ENTRY(FLOW, ADD)),
1926 .help = "command may end here",
1929 .name = "START_SET",
1930 .help = "null entry, abused as the entry point for set",
1931 .next = NEXT(NEXT_ENTRY(SET)),
1936 .help = "set command may end here",
1938 /* Common tokens. */
1939 [COMMON_INTEGER] = {
1942 .help = "integer value",
1946 [COMMON_UNSIGNED] = {
1947 .name = "{unsigned}",
1949 .help = "unsigned integer value",
1956 .help = "prefix length for bit-mask",
1957 .call = parse_prefix,
1960 [COMMON_BOOLEAN] = {
1961 .name = "{boolean}",
1963 .help = "any boolean value",
1964 .call = parse_boolean,
1965 .comp = comp_boolean,
1970 .help = "fixed string",
1971 .call = parse_string,
1977 .help = "fixed string",
1980 [COMMON_FILE_PATH] = {
1981 .name = "{file path}",
1983 .help = "file path",
1984 .call = parse_string0,
1987 [COMMON_MAC_ADDR] = {
1988 .name = "{MAC address}",
1990 .help = "standard MAC address notation",
1991 .call = parse_mac_addr,
1994 [COMMON_IPV4_ADDR] = {
1995 .name = "{IPv4 address}",
1996 .type = "IPV4 ADDRESS",
1997 .help = "standard IPv4 address notation",
1998 .call = parse_ipv4_addr,
2001 [COMMON_IPV6_ADDR] = {
2002 .name = "{IPv6 address}",
2003 .type = "IPV6 ADDRESS",
2004 .help = "standard IPv6 address notation",
2005 .call = parse_ipv6_addr,
2008 [COMMON_RULE_ID] = {
2009 .name = "{rule id}",
2011 .help = "rule identifier",
2013 .comp = comp_rule_id,
2015 [COMMON_PORT_ID] = {
2016 .name = "{port_id}",
2018 .help = "port identifier",
2022 [COMMON_GROUP_ID] = {
2023 .name = "{group_id}",
2025 .help = "group identifier",
2029 [COMMON_PRIORITY_LEVEL] = {
2032 .help = "priority level",
2036 [COMMON_INDIRECT_ACTION_ID] = {
2037 .name = "{indirect_action_id}",
2038 .type = "INDIRECT_ACTION_ID",
2039 .help = "indirect action id",
2043 [COMMON_POLICY_ID] = {
2044 .name = "{policy_id}",
2045 .type = "POLCIY_ID",
2046 .help = "policy id",
2050 /* Top-level command. */
2053 .type = "{command} {port_id} [{arg} [...]]",
2054 .help = "manage ingress/egress flow rules",
2055 .next = NEXT(NEXT_ENTRY
2069 /* Top-level command. */
2070 [INDIRECT_ACTION] = {
2071 .name = "indirect_action",
2072 .type = "{command} {port_id} [{arg} [...]]",
2073 .help = "manage indirect actions",
2074 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2075 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2078 /* Sub-level commands. */
2079 [INDIRECT_ACTION_CREATE] = {
2081 .help = "create indirect action",
2082 .next = NEXT(next_ia_create_attr),
2085 [INDIRECT_ACTION_UPDATE] = {
2087 .help = "update indirect action",
2088 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2089 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2090 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2093 [INDIRECT_ACTION_DESTROY] = {
2095 .help = "destroy indirect action",
2096 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2097 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2098 .call = parse_ia_destroy,
2100 [INDIRECT_ACTION_QUERY] = {
2102 .help = "query indirect action",
2103 .next = NEXT(NEXT_ENTRY(END),
2104 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2105 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2110 .help = "check whether a flow rule can be created",
2111 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2112 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2117 .help = "create a flow rule",
2118 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2119 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2124 .help = "destroy specific flow rules",
2125 .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2126 NEXT_ENTRY(COMMON_PORT_ID)),
2127 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2128 .call = parse_destroy,
2132 .help = "destroy all flow rules",
2133 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2134 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2135 .call = parse_flush,
2139 .help = "dump single/all flow rules to file",
2140 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2141 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2146 .help = "query an existing flow rule",
2147 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
2148 NEXT_ENTRY(COMMON_RULE_ID),
2149 NEXT_ENTRY(COMMON_PORT_ID)),
2150 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
2151 ARGS_ENTRY(struct buffer, args.query.rule),
2152 ARGS_ENTRY(struct buffer, port)),
2153 .call = parse_query,
2157 .help = "list existing flow rules",
2158 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2159 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2164 .help = "list and destroy aged flows",
2165 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2166 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2171 .help = "restrict ingress traffic to the defined flow rules",
2172 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
2173 NEXT_ENTRY(COMMON_PORT_ID)),
2174 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
2175 ARGS_ENTRY(struct buffer, port)),
2176 .call = parse_isolate,
2180 .help = "new tunnel API",
2181 .next = NEXT(NEXT_ENTRY
2182 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
2183 .call = parse_tunnel,
2185 /* Tunnel arguments. */
2188 .help = "create new tunnel object",
2189 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
2190 NEXT_ENTRY(COMMON_PORT_ID)),
2191 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2192 .call = parse_tunnel,
2194 [TUNNEL_CREATE_TYPE] = {
2196 .help = "create new tunnel",
2197 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
2198 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
2199 .call = parse_tunnel,
2201 [TUNNEL_DESTROY] = {
2203 .help = "destroy tunel",
2204 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
2205 NEXT_ENTRY(COMMON_PORT_ID)),
2206 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2207 .call = parse_tunnel,
2209 [TUNNEL_DESTROY_ID] = {
2211 .help = "tunnel identifier to testroy",
2212 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
2213 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2214 .call = parse_tunnel,
2218 .help = "list existing tunnels",
2219 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2220 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
2221 .call = parse_tunnel,
2223 /* Destroy arguments. */
2226 .help = "specify a rule identifier",
2227 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2228 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
2229 .call = parse_destroy,
2231 /* Dump arguments. */
2235 .next = NEXT(next_dump_attr),
2236 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
2241 .help = "dump one rule",
2242 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2243 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
2244 ARGS_ENTRY(struct buffer, args.dump.rule)),
2247 /* Query arguments. */
2251 .help = "action to query, must be part of the rule",
2252 .call = parse_action,
2253 .comp = comp_action,
2255 /* List arguments. */
2258 .help = "specify a group",
2259 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2260 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
2265 .help = "specify aged flows need be destroyed",
2269 /* Validate/create attributes. */
2272 .help = "specify a group",
2273 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2274 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
2279 .help = "specify a priority level",
2280 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2281 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
2286 .help = "affect rule to ingress",
2287 .next = NEXT(next_vc_attr),
2292 .help = "affect rule to egress",
2293 .next = NEXT(next_vc_attr),
2298 .help = "apply rule directly to endpoints found in pattern",
2299 .next = NEXT(next_vc_attr),
2303 .name = "tunnel_set",
2304 .help = "tunnel steer rule",
2305 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2306 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2309 [VC_TUNNEL_MATCH] = {
2310 .name = "tunnel_match",
2311 .help = "tunnel match rule",
2312 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2313 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2316 /* Validate/create pattern. */
2319 .help = "submit a list of pattern items",
2320 .next = NEXT(next_item),
2325 .help = "match value perfectly (with full bit-mask)",
2326 .call = parse_vc_spec,
2328 [ITEM_PARAM_SPEC] = {
2330 .help = "match value according to configured bit-mask",
2331 .call = parse_vc_spec,
2333 [ITEM_PARAM_LAST] = {
2335 .help = "specify upper bound to establish a range",
2336 .call = parse_vc_spec,
2338 [ITEM_PARAM_MASK] = {
2340 .help = "specify bit-mask with relevant bits set to one",
2341 .call = parse_vc_spec,
2343 [ITEM_PARAM_PREFIX] = {
2345 .help = "generate bit-mask from a prefix length",
2346 .call = parse_vc_spec,
2350 .help = "specify next pattern item",
2351 .next = NEXT(next_item),
2355 .help = "end list of pattern items",
2356 .priv = PRIV_ITEM(END, 0),
2357 .next = NEXT(NEXT_ENTRY(ACTIONS)),
2362 .help = "no-op pattern item",
2363 .priv = PRIV_ITEM(VOID, 0),
2364 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2369 .help = "perform actions when pattern does not match",
2370 .priv = PRIV_ITEM(INVERT, 0),
2371 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2376 .help = "match any protocol for the current layer",
2377 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
2378 .next = NEXT(item_any),
2383 .help = "number of layers covered",
2384 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2385 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
2389 .help = "match traffic from/to the physical function",
2390 .priv = PRIV_ITEM(PF, 0),
2391 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2396 .help = "match traffic from/to a virtual function ID",
2397 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
2398 .next = NEXT(item_vf),
2404 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2405 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
2409 .help = "match traffic from/to a specific physical port",
2410 .priv = PRIV_ITEM(PHY_PORT,
2411 sizeof(struct rte_flow_item_phy_port)),
2412 .next = NEXT(item_phy_port),
2415 [ITEM_PHY_PORT_INDEX] = {
2417 .help = "physical port index",
2418 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
2420 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
2424 .help = "match traffic from/to a given DPDK port ID",
2425 .priv = PRIV_ITEM(PORT_ID,
2426 sizeof(struct rte_flow_item_port_id)),
2427 .next = NEXT(item_port_id),
2430 [ITEM_PORT_ID_ID] = {
2432 .help = "DPDK port ID",
2433 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
2435 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
2439 .help = "match traffic against value set in previously matched rule",
2440 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
2441 .next = NEXT(item_mark),
2446 .help = "Integer value to match against",
2447 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
2449 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
2453 .help = "match an arbitrary byte string",
2454 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
2455 .next = NEXT(item_raw),
2458 [ITEM_RAW_RELATIVE] = {
2460 .help = "look for pattern after the previous item",
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_SEARCH] = {
2467 .help = "search pattern from offset (see also limit)",
2468 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2469 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2472 [ITEM_RAW_OFFSET] = {
2474 .help = "absolute or relative offset for pattern",
2475 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
2476 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
2478 [ITEM_RAW_LIMIT] = {
2480 .help = "search area limit for start of pattern",
2481 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2482 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
2484 [ITEM_RAW_PATTERN] = {
2486 .help = "byte string to look for",
2487 .next = NEXT(item_raw,
2488 NEXT_ENTRY(COMMON_STRING),
2489 NEXT_ENTRY(ITEM_PARAM_IS,
2492 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2493 ARGS_ENTRY(struct rte_flow_item_raw, length),
2494 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2495 ITEM_RAW_PATTERN_SIZE)),
2499 .help = "match Ethernet header",
2500 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
2501 .next = NEXT(item_eth),
2506 .help = "destination MAC",
2507 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2508 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
2512 .help = "source MAC",
2513 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2514 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
2518 .help = "EtherType",
2519 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2520 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
2522 [ITEM_ETH_HAS_VLAN] = {
2524 .help = "packet header contains VLAN",
2525 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2526 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
2531 .help = "match 802.1Q/ad VLAN tag",
2532 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
2533 .next = NEXT(item_vlan),
2538 .help = "tag control information",
2539 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2541 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
2545 .help = "priority code point",
2546 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2548 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2553 .help = "drop eligible indicator",
2554 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2556 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2561 .help = "VLAN identifier",
2562 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2564 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2567 [ITEM_VLAN_INNER_TYPE] = {
2568 .name = "inner_type",
2569 .help = "inner EtherType",
2570 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2572 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2575 [ITEM_VLAN_HAS_MORE_VLAN] = {
2576 .name = "has_more_vlan",
2577 .help = "packet header contains another VLAN",
2578 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2580 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
2585 .help = "match IPv4 header",
2586 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
2587 .next = NEXT(item_ipv4),
2590 [ITEM_IPV4_VER_IHL] = {
2591 .name = "version_ihl",
2592 .help = "match header length",
2593 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2595 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
2600 .help = "type of service",
2601 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2603 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2604 hdr.type_of_service)),
2607 .name = "packet_id",
2608 .help = "fragment packet id",
2609 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2611 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2614 [ITEM_IPV4_FRAGMENT_OFFSET] = {
2615 .name = "fragment_offset",
2616 .help = "fragmentation flags and fragment offset",
2617 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2619 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2620 hdr.fragment_offset)),
2624 .help = "time to live",
2625 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2627 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2630 [ITEM_IPV4_PROTO] = {
2632 .help = "next protocol ID",
2633 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2635 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2636 hdr.next_proto_id)),
2640 .help = "source address",
2641 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2643 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2648 .help = "destination address",
2649 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2651 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2656 .help = "match IPv6 header",
2657 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
2658 .next = NEXT(item_ipv6),
2663 .help = "traffic class",
2664 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2666 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2668 "\x0f\xf0\x00\x00")),
2670 [ITEM_IPV6_FLOW] = {
2672 .help = "flow label",
2673 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2675 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2677 "\x00\x0f\xff\xff")),
2679 [ITEM_IPV6_PROTO] = {
2681 .help = "protocol (next header)",
2682 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2684 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2689 .help = "hop limit",
2690 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2692 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2697 .help = "source address",
2698 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2700 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2705 .help = "destination address",
2706 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2708 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2711 [ITEM_IPV6_HAS_FRAG_EXT] = {
2712 .name = "has_frag_ext",
2713 .help = "fragment packet attribute",
2714 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2716 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
2721 .help = "match ICMP header",
2722 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
2723 .next = NEXT(item_icmp),
2726 [ITEM_ICMP_TYPE] = {
2728 .help = "ICMP packet type",
2729 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2731 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2734 [ITEM_ICMP_CODE] = {
2736 .help = "ICMP packet code",
2737 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2739 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2742 [ITEM_ICMP_IDENT] = {
2744 .help = "ICMP packet identifier",
2745 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2747 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2752 .help = "ICMP packet sequence number",
2753 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2755 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2760 .help = "match UDP header",
2761 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
2762 .next = NEXT(item_udp),
2767 .help = "UDP source port",
2768 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
2770 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2775 .help = "UDP destination port",
2776 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2777 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2782 .help = "match TCP header",
2783 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
2784 .next = NEXT(item_tcp),
2789 .help = "TCP source port",
2790 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2791 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2796 .help = "TCP destination port",
2797 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2798 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2801 [ITEM_TCP_FLAGS] = {
2803 .help = "TCP flags",
2804 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2805 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2810 .help = "match SCTP header",
2811 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
2812 .next = NEXT(item_sctp),
2817 .help = "SCTP source port",
2818 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2820 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2825 .help = "SCTP destination port",
2826 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2828 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2833 .help = "validation tag",
2834 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2836 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2839 [ITEM_SCTP_CKSUM] = {
2842 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2844 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2849 .help = "match VXLAN header",
2850 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
2851 .next = NEXT(item_vxlan),
2854 [ITEM_VXLAN_VNI] = {
2856 .help = "VXLAN identifier",
2857 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
2859 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
2861 [ITEM_VXLAN_LAST_RSVD] = {
2862 .name = "last_rsvd",
2863 .help = "VXLAN last reserved bits",
2864 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
2866 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
2871 .help = "match E-Tag header",
2872 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
2873 .next = NEXT(item_e_tag),
2876 [ITEM_E_TAG_GRP_ECID_B] = {
2877 .name = "grp_ecid_b",
2878 .help = "GRP and E-CID base",
2879 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
2881 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
2887 .help = "match NVGRE header",
2888 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
2889 .next = NEXT(item_nvgre),
2892 [ITEM_NVGRE_TNI] = {
2894 .help = "virtual subnet ID",
2895 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
2897 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
2901 .help = "match MPLS header",
2902 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
2903 .next = NEXT(item_mpls),
2906 [ITEM_MPLS_LABEL] = {
2908 .help = "MPLS label",
2909 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2911 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2917 .help = "MPLS Traffic Class",
2918 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2920 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2926 .help = "MPLS Bottom-of-Stack",
2927 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2929 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2935 .help = "match GRE header",
2936 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
2937 .next = NEXT(item_gre),
2940 [ITEM_GRE_PROTO] = {
2942 .help = "GRE protocol type",
2943 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
2945 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2948 [ITEM_GRE_C_RSVD0_VER] = {
2949 .name = "c_rsvd0_ver",
2951 "checksum (1b), undefined (1b), key bit (1b),"
2952 " sequence number (1b), reserved 0 (9b),"
2954 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
2956 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2959 [ITEM_GRE_C_BIT] = {
2961 .help = "checksum bit (C)",
2962 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
2964 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2966 "\x80\x00\x00\x00")),
2968 [ITEM_GRE_S_BIT] = {
2970 .help = "sequence number bit (S)",
2971 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2972 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2974 "\x10\x00\x00\x00")),
2976 [ITEM_GRE_K_BIT] = {
2978 .help = "key bit (K)",
2979 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2980 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2982 "\x20\x00\x00\x00")),
2986 .help = "fuzzy pattern match, expect faster than default",
2987 .priv = PRIV_ITEM(FUZZY,
2988 sizeof(struct rte_flow_item_fuzzy)),
2989 .next = NEXT(item_fuzzy),
2992 [ITEM_FUZZY_THRESH] = {
2994 .help = "match accuracy threshold",
2995 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
2997 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
3002 .help = "match GTP header",
3003 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
3004 .next = NEXT(item_gtp),
3007 [ITEM_GTP_FLAGS] = {
3008 .name = "v_pt_rsv_flags",
3009 .help = "GTP flags",
3010 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3011 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3014 [ITEM_GTP_MSG_TYPE] = {
3016 .help = "GTP message type",
3017 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3018 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3022 .help = "tunnel endpoint identifier",
3023 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3024 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3028 .help = "match GTP header",
3029 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3030 .next = NEXT(item_gtp),
3035 .help = "match GTP header",
3036 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3037 .next = NEXT(item_gtp),
3042 .help = "match GENEVE header",
3043 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3044 .next = NEXT(item_geneve),
3047 [ITEM_GENEVE_VNI] = {
3049 .help = "virtual network identifier",
3050 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3052 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3054 [ITEM_GENEVE_PROTO] = {
3056 .help = "GENEVE protocol type",
3057 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3059 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3062 [ITEM_GENEVE_OPTLEN] = {
3064 .help = "GENEVE options length in dwords",
3065 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3067 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3068 ver_opt_len_o_c_rsvd0,
3071 [ITEM_VXLAN_GPE] = {
3072 .name = "vxlan-gpe",
3073 .help = "match VXLAN-GPE header",
3074 .priv = PRIV_ITEM(VXLAN_GPE,
3075 sizeof(struct rte_flow_item_vxlan_gpe)),
3076 .next = NEXT(item_vxlan_gpe),
3079 [ITEM_VXLAN_GPE_VNI] = {
3081 .help = "VXLAN-GPE identifier",
3082 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3084 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
3087 [ITEM_ARP_ETH_IPV4] = {
3088 .name = "arp_eth_ipv4",
3089 .help = "match ARP header for Ethernet/IPv4",
3090 .priv = PRIV_ITEM(ARP_ETH_IPV4,
3091 sizeof(struct rte_flow_item_arp_eth_ipv4)),
3092 .next = NEXT(item_arp_eth_ipv4),
3095 [ITEM_ARP_ETH_IPV4_SHA] = {
3097 .help = "sender hardware address",
3098 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3100 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3103 [ITEM_ARP_ETH_IPV4_SPA] = {
3105 .help = "sender IPv4 address",
3106 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3108 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3111 [ITEM_ARP_ETH_IPV4_THA] = {
3113 .help = "target hardware address",
3114 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3116 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3119 [ITEM_ARP_ETH_IPV4_TPA] = {
3121 .help = "target IPv4 address",
3122 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3124 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3129 .help = "match presence of any IPv6 extension header",
3130 .priv = PRIV_ITEM(IPV6_EXT,
3131 sizeof(struct rte_flow_item_ipv6_ext)),
3132 .next = NEXT(item_ipv6_ext),
3135 [ITEM_IPV6_EXT_NEXT_HDR] = {
3137 .help = "next header",
3138 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3140 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
3143 [ITEM_IPV6_FRAG_EXT] = {
3144 .name = "ipv6_frag_ext",
3145 .help = "match presence of IPv6 fragment extension header",
3146 .priv = PRIV_ITEM(IPV6_FRAG_EXT,
3147 sizeof(struct rte_flow_item_ipv6_frag_ext)),
3148 .next = NEXT(item_ipv6_frag_ext),
3151 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
3153 .help = "next header",
3154 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3156 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
3159 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
3160 .name = "frag_data",
3161 .help = "fragment flags and offset",
3162 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3164 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3167 [ITEM_IPV6_FRAG_EXT_ID] = {
3168 .name = "packet_id",
3169 .help = "fragment packet id",
3170 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3172 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3177 .help = "match any ICMPv6 header",
3178 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
3179 .next = NEXT(item_icmp6),
3182 [ITEM_ICMP6_TYPE] = {
3184 .help = "ICMPv6 type",
3185 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3187 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3190 [ITEM_ICMP6_CODE] = {
3192 .help = "ICMPv6 code",
3193 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3195 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3198 [ITEM_ICMP6_ND_NS] = {
3199 .name = "icmp6_nd_ns",
3200 .help = "match ICMPv6 neighbor discovery solicitation",
3201 .priv = PRIV_ITEM(ICMP6_ND_NS,
3202 sizeof(struct rte_flow_item_icmp6_nd_ns)),
3203 .next = NEXT(item_icmp6_nd_ns),
3206 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
3207 .name = "target_addr",
3208 .help = "target address",
3209 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
3211 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
3214 [ITEM_ICMP6_ND_NA] = {
3215 .name = "icmp6_nd_na",
3216 .help = "match ICMPv6 neighbor discovery advertisement",
3217 .priv = PRIV_ITEM(ICMP6_ND_NA,
3218 sizeof(struct rte_flow_item_icmp6_nd_na)),
3219 .next = NEXT(item_icmp6_nd_na),
3222 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
3223 .name = "target_addr",
3224 .help = "target address",
3225 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
3227 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
3230 [ITEM_ICMP6_ND_OPT] = {
3231 .name = "icmp6_nd_opt",
3232 .help = "match presence of any ICMPv6 neighbor discovery"
3234 .priv = PRIV_ITEM(ICMP6_ND_OPT,
3235 sizeof(struct rte_flow_item_icmp6_nd_opt)),
3236 .next = NEXT(item_icmp6_nd_opt),
3239 [ITEM_ICMP6_ND_OPT_TYPE] = {
3241 .help = "ND option type",
3242 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3244 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
3247 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
3248 .name = "icmp6_nd_opt_sla_eth",
3249 .help = "match ICMPv6 neighbor discovery source Ethernet"
3250 " link-layer address option",
3252 (ICMP6_ND_OPT_SLA_ETH,
3253 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
3254 .next = NEXT(item_icmp6_nd_opt_sla_eth),
3257 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
3259 .help = "source Ethernet LLA",
3260 .next = NEXT(item_icmp6_nd_opt_sla_eth,
3261 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3262 .args = ARGS(ARGS_ENTRY_HTON
3263 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
3265 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
3266 .name = "icmp6_nd_opt_tla_eth",
3267 .help = "match ICMPv6 neighbor discovery target Ethernet"
3268 " link-layer address option",
3270 (ICMP6_ND_OPT_TLA_ETH,
3271 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
3272 .next = NEXT(item_icmp6_nd_opt_tla_eth),
3275 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
3277 .help = "target Ethernet LLA",
3278 .next = NEXT(item_icmp6_nd_opt_tla_eth,
3279 NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3280 .args = ARGS(ARGS_ENTRY_HTON
3281 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
3285 .help = "match metadata header",
3286 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
3287 .next = NEXT(item_meta),
3290 [ITEM_META_DATA] = {
3292 .help = "metadata value",
3293 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
3295 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
3296 data, "\xff\xff\xff\xff")),
3300 .help = "match GRE key",
3301 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
3302 .next = NEXT(item_gre_key),
3305 [ITEM_GRE_KEY_VALUE] = {
3307 .help = "key value",
3308 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
3310 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3314 .help = "match GTP extension header with type 0x85",
3315 .priv = PRIV_ITEM(GTP_PSC,
3316 sizeof(struct rte_flow_item_gtp_psc)),
3317 .next = NEXT(item_gtp_psc),
3320 [ITEM_GTP_PSC_QFI] = {
3322 .help = "QoS flow identifier",
3323 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3325 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3328 [ITEM_GTP_PSC_PDU_T] = {
3331 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3333 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3338 .help = "match PPPoE session header",
3339 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
3340 .next = NEXT(item_pppoes),
3345 .help = "match PPPoE discovery header",
3346 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
3347 .next = NEXT(item_pppoed),
3350 [ITEM_PPPOE_SEID] = {
3352 .help = "session identifier",
3353 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
3355 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
3358 [ITEM_PPPOE_PROTO_ID] = {
3359 .name = "pppoe_proto_id",
3360 .help = "match PPPoE session protocol identifier",
3361 .priv = PRIV_ITEM(PPPOE_PROTO_ID,
3362 sizeof(struct rte_flow_item_pppoe_proto_id)),
3363 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
3365 .args = ARGS(ARGS_ENTRY_HTON
3366 (struct rte_flow_item_pppoe_proto_id, proto_id)),
3371 .help = "matches higig2 header",
3372 .priv = PRIV_ITEM(HIGIG2,
3373 sizeof(struct rte_flow_item_higig2_hdr)),
3374 .next = NEXT(item_higig2),
3377 [ITEM_HIGIG2_CLASSIFICATION] = {
3378 .name = "classification",
3379 .help = "matches classification of higig2 header",
3380 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3382 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3383 hdr.ppt1.classification)),
3385 [ITEM_HIGIG2_VID] = {
3387 .help = "matches vid of higig2 header",
3388 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3390 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3395 .help = "match tag value",
3396 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
3397 .next = NEXT(item_tag),
3402 .help = "tag value to match",
3403 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3404 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
3406 [ITEM_TAG_INDEX] = {
3408 .help = "index of tag array to match",
3409 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3410 NEXT_ENTRY(ITEM_PARAM_IS)),
3411 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
3413 [ITEM_L2TPV3OIP] = {
3414 .name = "l2tpv3oip",
3415 .help = "match L2TPv3 over IP header",
3416 .priv = PRIV_ITEM(L2TPV3OIP,
3417 sizeof(struct rte_flow_item_l2tpv3oip)),
3418 .next = NEXT(item_l2tpv3oip),
3421 [ITEM_L2TPV3OIP_SESSION_ID] = {
3422 .name = "session_id",
3423 .help = "session identifier",
3424 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
3426 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
3431 .help = "match ESP header",
3432 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
3433 .next = NEXT(item_esp),
3438 .help = "security policy index",
3439 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3440 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
3445 .help = "match AH header",
3446 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
3447 .next = NEXT(item_ah),
3452 .help = "security parameters index",
3453 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3454 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
3458 .help = "match pfcp header",
3459 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
3460 .next = NEXT(item_pfcp),
3463 [ITEM_PFCP_S_FIELD] = {
3466 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3468 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
3471 [ITEM_PFCP_SEID] = {
3473 .help = "session endpoint identifier",
3474 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3476 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
3480 .help = "match eCPRI header",
3481 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
3482 .next = NEXT(item_ecpri),
3485 [ITEM_ECPRI_COMMON] = {
3487 .help = "eCPRI common header",
3488 .next = NEXT(item_ecpri_common),
3490 [ITEM_ECPRI_COMMON_TYPE] = {
3492 .help = "type of common header",
3493 .next = NEXT(item_ecpri_common_type),
3494 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
3496 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
3498 .help = "Type #0: IQ Data",
3499 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3501 .call = parse_vc_item_ecpri_type,
3503 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
3505 .help = "Physical Channel ID",
3506 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3507 ITEM_ECPRI_COMMON, ITEM_NEXT),
3508 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3509 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3512 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
3514 .help = "Type #2: Real-Time Control Data",
3515 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3517 .call = parse_vc_item_ecpri_type,
3519 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
3521 .help = "Real-Time Control Data ID",
3522 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3523 ITEM_ECPRI_COMMON, ITEM_NEXT),
3524 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3525 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3528 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
3529 .name = "delay_measure",
3530 .help = "Type #5: One-Way Delay Measurement",
3531 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3533 .call = parse_vc_item_ecpri_type,
3535 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
3537 .help = "Measurement ID",
3538 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3539 ITEM_ECPRI_COMMON, ITEM_NEXT),
3540 NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3541 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3544 [ITEM_GENEVE_OPT] = {
3545 .name = "geneve-opt",
3546 .help = "GENEVE header option",
3547 .priv = PRIV_ITEM(GENEVE_OPT,
3548 sizeof(struct rte_flow_item_geneve_opt) +
3549 ITEM_GENEVE_OPT_DATA_SIZE),
3550 .next = NEXT(item_geneve_opt),
3553 [ITEM_GENEVE_OPT_CLASS] = {
3555 .help = "GENEVE option class",
3556 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3558 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
3561 [ITEM_GENEVE_OPT_TYPE] = {
3563 .help = "GENEVE option type",
3564 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3566 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
3569 [ITEM_GENEVE_OPT_LENGTH] = {
3571 .help = "GENEVE option data length (in 32b words)",
3572 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3574 .args = ARGS(ARGS_ENTRY_BOUNDED(
3575 struct rte_flow_item_geneve_opt, option_len,
3578 [ITEM_GENEVE_OPT_DATA] = {
3580 .help = "GENEVE option data pattern",
3581 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
3583 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
3584 ARGS_ENTRY_ARB(0, 0),
3586 (sizeof(struct rte_flow_item_geneve_opt),
3587 ITEM_GENEVE_OPT_DATA_SIZE)),
3589 [ITEM_INTEGRITY] = {
3590 .name = "integrity",
3591 .help = "match packet integrity",
3592 .priv = PRIV_ITEM(INTEGRITY,
3593 sizeof(struct rte_flow_item_integrity)),
3594 .next = NEXT(item_integrity),
3597 [ITEM_INTEGRITY_LEVEL] = {
3599 .help = "integrity level",
3600 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3602 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
3604 [ITEM_INTEGRITY_VALUE] = {
3606 .help = "integrity value",
3607 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3609 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
3611 [ITEM_CONNTRACK] = {
3612 .name = "conntrack",
3613 .help = "conntrack state",
3614 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
3616 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
3618 [ITEM_PORT_REPRESENTOR] = {
3619 .name = "port_representor",
3620 .help = "match traffic entering the embedded switch from the given ethdev",
3621 .priv = PRIV_ITEM(PORT_REPRESENTOR,
3622 sizeof(struct rte_flow_item_ethdev)),
3623 .next = NEXT(item_port_representor),
3626 [ITEM_PORT_REPRESENTOR_PORT_ID] = {
3628 .help = "ethdev port ID",
3629 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
3631 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
3633 /* Validate/create actions. */
3636 .help = "submit a list of associated actions",
3637 .next = NEXT(next_action),
3642 .help = "specify next action",
3643 .next = NEXT(next_action),
3647 .help = "end list of actions",
3648 .priv = PRIV_ACTION(END, 0),
3653 .help = "no-op action",
3654 .priv = PRIV_ACTION(VOID, 0),
3655 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3658 [ACTION_PASSTHRU] = {
3660 .help = "let subsequent rule process matched packets",
3661 .priv = PRIV_ACTION(PASSTHRU, 0),
3662 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3667 .help = "redirect traffic to a given group",
3668 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
3669 .next = NEXT(action_jump),
3672 [ACTION_JUMP_GROUP] = {
3674 .help = "group to redirect traffic to",
3675 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
3676 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
3677 .call = parse_vc_conf,
3681 .help = "attach 32 bit value to packets",
3682 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
3683 .next = NEXT(action_mark),
3686 [ACTION_MARK_ID] = {
3688 .help = "32 bit value to return with packets",
3689 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
3690 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
3691 .call = parse_vc_conf,
3695 .help = "flag packets",
3696 .priv = PRIV_ACTION(FLAG, 0),
3697 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3702 .help = "assign packets to a given queue index",
3703 .priv = PRIV_ACTION(QUEUE,
3704 sizeof(struct rte_flow_action_queue)),
3705 .next = NEXT(action_queue),
3708 [ACTION_QUEUE_INDEX] = {
3710 .help = "queue index to use",
3711 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
3712 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
3713 .call = parse_vc_conf,
3717 .help = "drop packets (note: passthru has priority)",
3718 .priv = PRIV_ACTION(DROP, 0),
3719 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3724 .help = "enable counters for this rule",
3725 .priv = PRIV_ACTION(COUNT,
3726 sizeof(struct rte_flow_action_count)),
3727 .next = NEXT(action_count),
3730 [ACTION_COUNT_ID] = {
3731 .name = "identifier",
3732 .help = "counter identifier to use",
3733 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
3734 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
3735 .call = parse_vc_conf,
3739 .help = "spread packets among several queues",
3740 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
3741 .next = NEXT(action_rss),
3742 .call = parse_vc_action_rss,
3744 [ACTION_RSS_FUNC] = {
3746 .help = "RSS hash function to apply",
3747 .next = NEXT(action_rss,
3748 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
3749 ACTION_RSS_FUNC_TOEPLITZ,
3750 ACTION_RSS_FUNC_SIMPLE_XOR,
3751 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
3753 [ACTION_RSS_FUNC_DEFAULT] = {
3755 .help = "default hash function",
3756 .call = parse_vc_action_rss_func,
3758 [ACTION_RSS_FUNC_TOEPLITZ] = {
3760 .help = "Toeplitz hash function",
3761 .call = parse_vc_action_rss_func,
3763 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
3764 .name = "simple_xor",
3765 .help = "simple XOR hash function",
3766 .call = parse_vc_action_rss_func,
3768 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
3769 .name = "symmetric_toeplitz",
3770 .help = "Symmetric Toeplitz hash function",
3771 .call = parse_vc_action_rss_func,
3773 [ACTION_RSS_LEVEL] = {
3775 .help = "encapsulation level for \"types\"",
3776 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
3777 .args = ARGS(ARGS_ENTRY_ARB
3778 (offsetof(struct action_rss_data, conf) +
3779 offsetof(struct rte_flow_action_rss, level),
3780 sizeof(((struct rte_flow_action_rss *)0)->
3783 [ACTION_RSS_TYPES] = {
3785 .help = "specific RSS hash types",
3786 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
3788 [ACTION_RSS_TYPE] = {
3790 .help = "RSS hash type",
3791 .call = parse_vc_action_rss_type,
3792 .comp = comp_vc_action_rss_type,
3794 [ACTION_RSS_KEY] = {
3796 .help = "RSS hash key",
3797 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
3798 .args = ARGS(ARGS_ENTRY_ARB
3799 (offsetof(struct action_rss_data, conf) +
3800 offsetof(struct rte_flow_action_rss, key),
3801 sizeof(((struct rte_flow_action_rss *)0)->key)),
3803 (offsetof(struct action_rss_data, conf) +
3804 offsetof(struct rte_flow_action_rss, key_len),
3805 sizeof(((struct rte_flow_action_rss *)0)->
3807 ARGS_ENTRY(struct action_rss_data, key)),
3809 [ACTION_RSS_KEY_LEN] = {
3811 .help = "RSS hash key length in bytes",
3812 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
3813 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3814 (offsetof(struct action_rss_data, conf) +
3815 offsetof(struct rte_flow_action_rss, key_len),
3816 sizeof(((struct rte_flow_action_rss *)0)->
3819 RSS_HASH_KEY_LENGTH)),
3821 [ACTION_RSS_QUEUES] = {
3823 .help = "queue indices to use",
3824 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
3825 .call = parse_vc_conf,
3827 [ACTION_RSS_QUEUE] = {
3829 .help = "queue index",
3830 .call = parse_vc_action_rss_queue,
3831 .comp = comp_vc_action_rss_queue,
3835 .help = "direct traffic to physical function",
3836 .priv = PRIV_ACTION(PF, 0),
3837 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3842 .help = "direct traffic to a virtual function ID",
3843 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
3844 .next = NEXT(action_vf),
3847 [ACTION_VF_ORIGINAL] = {
3849 .help = "use original VF ID if possible",
3850 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
3851 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
3853 .call = parse_vc_conf,
3858 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
3859 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
3860 .call = parse_vc_conf,
3862 [ACTION_PHY_PORT] = {
3864 .help = "direct packets to physical port index",
3865 .priv = PRIV_ACTION(PHY_PORT,
3866 sizeof(struct rte_flow_action_phy_port)),
3867 .next = NEXT(action_phy_port),
3870 [ACTION_PHY_PORT_ORIGINAL] = {
3872 .help = "use original port index if possible",
3873 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
3874 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
3876 .call = parse_vc_conf,
3878 [ACTION_PHY_PORT_INDEX] = {
3880 .help = "physical port index",
3881 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
3882 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
3884 .call = parse_vc_conf,
3886 [ACTION_PORT_ID] = {
3888 .help = "direct matching traffic to a given DPDK port ID",
3889 .priv = PRIV_ACTION(PORT_ID,
3890 sizeof(struct rte_flow_action_port_id)),
3891 .next = NEXT(action_port_id),
3894 [ACTION_PORT_ID_ORIGINAL] = {
3896 .help = "use original DPDK port ID if possible",
3897 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
3898 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
3900 .call = parse_vc_conf,
3902 [ACTION_PORT_ID_ID] = {
3904 .help = "DPDK port ID",
3905 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
3906 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
3907 .call = parse_vc_conf,
3911 .help = "meter the directed packets at given id",
3912 .priv = PRIV_ACTION(METER,
3913 sizeof(struct rte_flow_action_meter)),
3914 .next = NEXT(action_meter),
3917 [ACTION_METER_COLOR] = {
3919 .help = "meter color for the packets",
3920 .priv = PRIV_ACTION(METER_COLOR,
3921 sizeof(struct rte_flow_action_meter_color)),
3922 .next = NEXT(action_meter_color),
3925 [ACTION_METER_COLOR_TYPE] = {
3927 .help = "specific meter color",
3928 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
3929 NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
3930 ACTION_METER_COLOR_YELLOW,
3931 ACTION_METER_COLOR_RED)),
3933 [ACTION_METER_COLOR_GREEN] = {
3935 .help = "meter color green",
3936 .call = parse_vc_action_meter_color_type,
3938 [ACTION_METER_COLOR_YELLOW] = {
3940 .help = "meter color yellow",
3941 .call = parse_vc_action_meter_color_type,
3943 [ACTION_METER_COLOR_RED] = {
3945 .help = "meter color red",
3946 .call = parse_vc_action_meter_color_type,
3948 [ACTION_METER_ID] = {
3950 .help = "meter id to use",
3951 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
3952 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
3953 .call = parse_vc_conf,
3955 [ACTION_OF_SET_MPLS_TTL] = {
3956 .name = "of_set_mpls_ttl",
3957 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
3960 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
3961 .next = NEXT(action_of_set_mpls_ttl),
3964 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
3967 .next = NEXT(action_of_set_mpls_ttl,
3968 NEXT_ENTRY(COMMON_UNSIGNED)),
3969 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
3971 .call = parse_vc_conf,
3973 [ACTION_OF_DEC_MPLS_TTL] = {
3974 .name = "of_dec_mpls_ttl",
3975 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
3976 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
3977 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3980 [ACTION_OF_SET_NW_TTL] = {
3981 .name = "of_set_nw_ttl",
3982 .help = "OpenFlow's OFPAT_SET_NW_TTL",
3985 sizeof(struct rte_flow_action_of_set_nw_ttl)),
3986 .next = NEXT(action_of_set_nw_ttl),
3989 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
3992 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
3993 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
3995 .call = parse_vc_conf,
3997 [ACTION_OF_DEC_NW_TTL] = {
3998 .name = "of_dec_nw_ttl",
3999 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
4000 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
4001 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4004 [ACTION_OF_COPY_TTL_OUT] = {
4005 .name = "of_copy_ttl_out",
4006 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
4007 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
4008 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4011 [ACTION_OF_COPY_TTL_IN] = {
4012 .name = "of_copy_ttl_in",
4013 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
4014 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
4015 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4018 [ACTION_OF_POP_VLAN] = {
4019 .name = "of_pop_vlan",
4020 .help = "OpenFlow's OFPAT_POP_VLAN",
4021 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
4022 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4025 [ACTION_OF_PUSH_VLAN] = {
4026 .name = "of_push_vlan",
4027 .help = "OpenFlow's OFPAT_PUSH_VLAN",
4030 sizeof(struct rte_flow_action_of_push_vlan)),
4031 .next = NEXT(action_of_push_vlan),
4034 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
4035 .name = "ethertype",
4036 .help = "EtherType",
4037 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
4038 .args = ARGS(ARGS_ENTRY_HTON
4039 (struct rte_flow_action_of_push_vlan,
4041 .call = parse_vc_conf,
4043 [ACTION_OF_SET_VLAN_VID] = {
4044 .name = "of_set_vlan_vid",
4045 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
4048 sizeof(struct rte_flow_action_of_set_vlan_vid)),
4049 .next = NEXT(action_of_set_vlan_vid),
4052 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
4055 .next = NEXT(action_of_set_vlan_vid,
4056 NEXT_ENTRY(COMMON_UNSIGNED)),
4057 .args = ARGS(ARGS_ENTRY_HTON
4058 (struct rte_flow_action_of_set_vlan_vid,
4060 .call = parse_vc_conf,
4062 [ACTION_OF_SET_VLAN_PCP] = {
4063 .name = "of_set_vlan_pcp",
4064 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
4067 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
4068 .next = NEXT(action_of_set_vlan_pcp),
4071 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
4073 .help = "VLAN priority",
4074 .next = NEXT(action_of_set_vlan_pcp,
4075 NEXT_ENTRY(COMMON_UNSIGNED)),
4076 .args = ARGS(ARGS_ENTRY_HTON
4077 (struct rte_flow_action_of_set_vlan_pcp,
4079 .call = parse_vc_conf,
4081 [ACTION_OF_POP_MPLS] = {
4082 .name = "of_pop_mpls",
4083 .help = "OpenFlow's OFPAT_POP_MPLS",
4084 .priv = PRIV_ACTION(OF_POP_MPLS,
4085 sizeof(struct rte_flow_action_of_pop_mpls)),
4086 .next = NEXT(action_of_pop_mpls),
4089 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
4090 .name = "ethertype",
4091 .help = "EtherType",
4092 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4093 .args = ARGS(ARGS_ENTRY_HTON
4094 (struct rte_flow_action_of_pop_mpls,
4096 .call = parse_vc_conf,
4098 [ACTION_OF_PUSH_MPLS] = {
4099 .name = "of_push_mpls",
4100 .help = "OpenFlow's OFPAT_PUSH_MPLS",
4103 sizeof(struct rte_flow_action_of_push_mpls)),
4104 .next = NEXT(action_of_push_mpls),
4107 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
4108 .name = "ethertype",
4109 .help = "EtherType",
4110 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4111 .args = ARGS(ARGS_ENTRY_HTON
4112 (struct rte_flow_action_of_push_mpls,
4114 .call = parse_vc_conf,
4116 [ACTION_VXLAN_ENCAP] = {
4117 .name = "vxlan_encap",
4118 .help = "VXLAN encapsulation, uses configuration set by \"set"
4120 .priv = PRIV_ACTION(VXLAN_ENCAP,
4121 sizeof(struct action_vxlan_encap_data)),
4122 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4123 .call = parse_vc_action_vxlan_encap,
4125 [ACTION_VXLAN_DECAP] = {
4126 .name = "vxlan_decap",
4127 .help = "Performs a decapsulation action by stripping all"
4128 " headers of the VXLAN tunnel network overlay from the"
4130 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
4131 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4134 [ACTION_NVGRE_ENCAP] = {
4135 .name = "nvgre_encap",
4136 .help = "NVGRE encapsulation, uses configuration set by \"set"
4138 .priv = PRIV_ACTION(NVGRE_ENCAP,
4139 sizeof(struct action_nvgre_encap_data)),
4140 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4141 .call = parse_vc_action_nvgre_encap,
4143 [ACTION_NVGRE_DECAP] = {
4144 .name = "nvgre_decap",
4145 .help = "Performs a decapsulation action by stripping all"
4146 " headers of the NVGRE tunnel network overlay from the"
4148 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
4149 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4152 [ACTION_L2_ENCAP] = {
4154 .help = "l2 encap, uses configuration set by"
4155 " \"set l2_encap\"",
4156 .priv = PRIV_ACTION(RAW_ENCAP,
4157 sizeof(struct action_raw_encap_data)),
4158 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4159 .call = parse_vc_action_l2_encap,
4161 [ACTION_L2_DECAP] = {
4163 .help = "l2 decap, uses configuration set by"
4164 " \"set l2_decap\"",
4165 .priv = PRIV_ACTION(RAW_DECAP,
4166 sizeof(struct action_raw_decap_data)),
4167 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4168 .call = parse_vc_action_l2_decap,
4170 [ACTION_MPLSOGRE_ENCAP] = {
4171 .name = "mplsogre_encap",
4172 .help = "mplsogre encapsulation, uses configuration set by"
4173 " \"set mplsogre_encap\"",
4174 .priv = PRIV_ACTION(RAW_ENCAP,
4175 sizeof(struct action_raw_encap_data)),
4176 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4177 .call = parse_vc_action_mplsogre_encap,
4179 [ACTION_MPLSOGRE_DECAP] = {
4180 .name = "mplsogre_decap",
4181 .help = "mplsogre decapsulation, uses configuration set by"
4182 " \"set mplsogre_decap\"",
4183 .priv = PRIV_ACTION(RAW_DECAP,
4184 sizeof(struct action_raw_decap_data)),
4185 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4186 .call = parse_vc_action_mplsogre_decap,
4188 [ACTION_MPLSOUDP_ENCAP] = {
4189 .name = "mplsoudp_encap",
4190 .help = "mplsoudp encapsulation, uses configuration set by"
4191 " \"set mplsoudp_encap\"",
4192 .priv = PRIV_ACTION(RAW_ENCAP,
4193 sizeof(struct action_raw_encap_data)),
4194 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4195 .call = parse_vc_action_mplsoudp_encap,
4197 [ACTION_MPLSOUDP_DECAP] = {
4198 .name = "mplsoudp_decap",
4199 .help = "mplsoudp decapsulation, uses configuration set by"
4200 " \"set mplsoudp_decap\"",
4201 .priv = PRIV_ACTION(RAW_DECAP,
4202 sizeof(struct action_raw_decap_data)),
4203 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4204 .call = parse_vc_action_mplsoudp_decap,
4206 [ACTION_SET_IPV4_SRC] = {
4207 .name = "set_ipv4_src",
4208 .help = "Set a new IPv4 source address in the outermost"
4210 .priv = PRIV_ACTION(SET_IPV4_SRC,
4211 sizeof(struct rte_flow_action_set_ipv4)),
4212 .next = NEXT(action_set_ipv4_src),
4215 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
4216 .name = "ipv4_addr",
4217 .help = "new IPv4 source address to set",
4218 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4219 .args = ARGS(ARGS_ENTRY_HTON
4220 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4221 .call = parse_vc_conf,
4223 [ACTION_SET_IPV4_DST] = {
4224 .name = "set_ipv4_dst",
4225 .help = "Set a new IPv4 destination address in the outermost"
4227 .priv = PRIV_ACTION(SET_IPV4_DST,
4228 sizeof(struct rte_flow_action_set_ipv4)),
4229 .next = NEXT(action_set_ipv4_dst),
4232 [ACTION_SET_IPV4_DST_IPV4_DST] = {
4233 .name = "ipv4_addr",
4234 .help = "new IPv4 destination address to set",
4235 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4236 .args = ARGS(ARGS_ENTRY_HTON
4237 (struct rte_flow_action_set_ipv4, ipv4_addr)),
4238 .call = parse_vc_conf,
4240 [ACTION_SET_IPV6_SRC] = {
4241 .name = "set_ipv6_src",
4242 .help = "Set a new IPv6 source address in the outermost"
4244 .priv = PRIV_ACTION(SET_IPV6_SRC,
4245 sizeof(struct rte_flow_action_set_ipv6)),
4246 .next = NEXT(action_set_ipv6_src),
4249 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
4250 .name = "ipv6_addr",
4251 .help = "new IPv6 source address to set",
4252 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4253 .args = ARGS(ARGS_ENTRY_HTON
4254 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4255 .call = parse_vc_conf,
4257 [ACTION_SET_IPV6_DST] = {
4258 .name = "set_ipv6_dst",
4259 .help = "Set a new IPv6 destination address in the outermost"
4261 .priv = PRIV_ACTION(SET_IPV6_DST,
4262 sizeof(struct rte_flow_action_set_ipv6)),
4263 .next = NEXT(action_set_ipv6_dst),
4266 [ACTION_SET_IPV6_DST_IPV6_DST] = {
4267 .name = "ipv6_addr",
4268 .help = "new IPv6 destination address to set",
4269 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4270 .args = ARGS(ARGS_ENTRY_HTON
4271 (struct rte_flow_action_set_ipv6, ipv6_addr)),
4272 .call = parse_vc_conf,
4274 [ACTION_SET_TP_SRC] = {
4275 .name = "set_tp_src",
4276 .help = "set a new source port number in the outermost"
4278 .priv = PRIV_ACTION(SET_TP_SRC,
4279 sizeof(struct rte_flow_action_set_tp)),
4280 .next = NEXT(action_set_tp_src),
4283 [ACTION_SET_TP_SRC_TP_SRC] = {
4285 .help = "new source port number to set",
4286 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
4287 .args = ARGS(ARGS_ENTRY_HTON
4288 (struct rte_flow_action_set_tp, port)),
4289 .call = parse_vc_conf,
4291 [ACTION_SET_TP_DST] = {
4292 .name = "set_tp_dst",
4293 .help = "set a new destination port number in the outermost"
4295 .priv = PRIV_ACTION(SET_TP_DST,
4296 sizeof(struct rte_flow_action_set_tp)),
4297 .next = NEXT(action_set_tp_dst),
4300 [ACTION_SET_TP_DST_TP_DST] = {
4302 .help = "new destination port number to set",
4303 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
4304 .args = ARGS(ARGS_ENTRY_HTON
4305 (struct rte_flow_action_set_tp, port)),
4306 .call = parse_vc_conf,
4308 [ACTION_MAC_SWAP] = {
4310 .help = "Swap the source and destination MAC addresses"
4311 " in the outermost Ethernet header",
4312 .priv = PRIV_ACTION(MAC_SWAP, 0),
4313 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4316 [ACTION_DEC_TTL] = {
4318 .help = "decrease network TTL if available",
4319 .priv = PRIV_ACTION(DEC_TTL, 0),
4320 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4323 [ACTION_SET_TTL] = {
4325 .help = "set ttl value",
4326 .priv = PRIV_ACTION(SET_TTL,
4327 sizeof(struct rte_flow_action_set_ttl)),
4328 .next = NEXT(action_set_ttl),
4331 [ACTION_SET_TTL_TTL] = {
4332 .name = "ttl_value",
4333 .help = "new ttl value to set",
4334 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4335 .args = ARGS(ARGS_ENTRY_HTON
4336 (struct rte_flow_action_set_ttl, ttl_value)),
4337 .call = parse_vc_conf,
4339 [ACTION_SET_MAC_SRC] = {
4340 .name = "set_mac_src",
4341 .help = "set source mac address",
4342 .priv = PRIV_ACTION(SET_MAC_SRC,
4343 sizeof(struct rte_flow_action_set_mac)),
4344 .next = NEXT(action_set_mac_src),
4347 [ACTION_SET_MAC_SRC_MAC_SRC] = {
4349 .help = "new source mac address",
4350 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
4351 .args = ARGS(ARGS_ENTRY_HTON
4352 (struct rte_flow_action_set_mac, mac_addr)),
4353 .call = parse_vc_conf,
4355 [ACTION_SET_MAC_DST] = {
4356 .name = "set_mac_dst",
4357 .help = "set destination mac address",
4358 .priv = PRIV_ACTION(SET_MAC_DST,
4359 sizeof(struct rte_flow_action_set_mac)),
4360 .next = NEXT(action_set_mac_dst),
4363 [ACTION_SET_MAC_DST_MAC_DST] = {
4365 .help = "new destination mac address to set",
4366 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
4367 .args = ARGS(ARGS_ENTRY_HTON
4368 (struct rte_flow_action_set_mac, mac_addr)),
4369 .call = parse_vc_conf,
4371 [ACTION_INC_TCP_SEQ] = {
4372 .name = "inc_tcp_seq",
4373 .help = "increase TCP sequence number",
4374 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
4375 .next = NEXT(action_inc_tcp_seq),
4378 [ACTION_INC_TCP_SEQ_VALUE] = {
4380 .help = "the value to increase TCP sequence number by",
4381 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4382 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4383 .call = parse_vc_conf,
4385 [ACTION_DEC_TCP_SEQ] = {
4386 .name = "dec_tcp_seq",
4387 .help = "decrease TCP sequence number",
4388 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
4389 .next = NEXT(action_dec_tcp_seq),
4392 [ACTION_DEC_TCP_SEQ_VALUE] = {
4394 .help = "the value to decrease TCP sequence number by",
4395 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4396 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4397 .call = parse_vc_conf,
4399 [ACTION_INC_TCP_ACK] = {
4400 .name = "inc_tcp_ack",
4401 .help = "increase TCP acknowledgment number",
4402 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
4403 .next = NEXT(action_inc_tcp_ack),
4406 [ACTION_INC_TCP_ACK_VALUE] = {
4408 .help = "the value to increase TCP acknowledgment number by",
4409 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4410 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4411 .call = parse_vc_conf,
4413 [ACTION_DEC_TCP_ACK] = {
4414 .name = "dec_tcp_ack",
4415 .help = "decrease TCP acknowledgment number",
4416 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
4417 .next = NEXT(action_dec_tcp_ack),
4420 [ACTION_DEC_TCP_ACK_VALUE] = {
4422 .help = "the value to decrease TCP acknowledgment number by",
4423 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4424 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4425 .call = parse_vc_conf,
4427 [ACTION_RAW_ENCAP] = {
4428 .name = "raw_encap",
4429 .help = "encapsulation data, defined by set raw_encap",
4430 .priv = PRIV_ACTION(RAW_ENCAP,
4431 sizeof(struct action_raw_encap_data)),
4432 .next = NEXT(action_raw_encap),
4433 .call = parse_vc_action_raw_encap,
4435 [ACTION_RAW_ENCAP_INDEX] = {
4437 .help = "the index of raw_encap_confs",
4438 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
4440 [ACTION_RAW_ENCAP_INDEX_VALUE] = {
4443 .help = "unsigned integer value",
4444 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4445 .call = parse_vc_action_raw_encap_index,
4446 .comp = comp_set_raw_index,
4448 [ACTION_RAW_DECAP] = {
4449 .name = "raw_decap",
4450 .help = "decapsulation data, defined by set raw_encap",
4451 .priv = PRIV_ACTION(RAW_DECAP,
4452 sizeof(struct action_raw_decap_data)),
4453 .next = NEXT(action_raw_decap),
4454 .call = parse_vc_action_raw_decap,
4456 [ACTION_RAW_DECAP_INDEX] = {
4458 .help = "the index of raw_encap_confs",
4459 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
4461 [ACTION_RAW_DECAP_INDEX_VALUE] = {
4464 .help = "unsigned integer value",
4465 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4466 .call = parse_vc_action_raw_decap_index,
4467 .comp = comp_set_raw_index,
4469 [ACTION_MODIFY_FIELD] = {
4470 .name = "modify_field",
4471 .help = "modify destination field with data from source field",
4472 .priv = PRIV_ACTION(MODIFY_FIELD,
4473 sizeof(struct rte_flow_action_modify_field)),
4474 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
4477 [ACTION_MODIFY_FIELD_OP] = {
4479 .help = "operation type",
4480 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
4481 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
4482 .call = parse_vc_conf,
4484 [ACTION_MODIFY_FIELD_OP_VALUE] = {
4485 .name = "{operation}",
4486 .help = "operation type value",
4487 .call = parse_vc_modify_field_op,
4488 .comp = comp_set_modify_field_op,
4490 [ACTION_MODIFY_FIELD_DST_TYPE] = {
4492 .help = "destination field type",
4493 .next = NEXT(action_modify_field_dst,
4494 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
4495 .call = parse_vc_conf,
4497 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
4498 .name = "{dst_type}",
4499 .help = "destination field type value",
4500 .call = parse_vc_modify_field_id,
4501 .comp = comp_set_modify_field_id,
4503 [ACTION_MODIFY_FIELD_DST_LEVEL] = {
4504 .name = "dst_level",
4505 .help = "destination field level",
4506 .next = NEXT(action_modify_field_dst,
4507 NEXT_ENTRY(COMMON_UNSIGNED)),
4508 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4510 .call = parse_vc_conf,
4512 [ACTION_MODIFY_FIELD_DST_OFFSET] = {
4513 .name = "dst_offset",
4514 .help = "destination field bit offset",
4515 .next = NEXT(action_modify_field_dst,
4516 NEXT_ENTRY(COMMON_UNSIGNED)),
4517 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4519 .call = parse_vc_conf,
4521 [ACTION_MODIFY_FIELD_SRC_TYPE] = {
4523 .help = "source field type",
4524 .next = NEXT(action_modify_field_src,
4525 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
4526 .call = parse_vc_conf,
4528 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
4529 .name = "{src_type}",
4530 .help = "source field type value",
4531 .call = parse_vc_modify_field_id,
4532 .comp = comp_set_modify_field_id,
4534 [ACTION_MODIFY_FIELD_SRC_LEVEL] = {
4535 .name = "src_level",
4536 .help = "source field level",
4537 .next = NEXT(action_modify_field_src,
4538 NEXT_ENTRY(COMMON_UNSIGNED)),
4539 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4541 .call = parse_vc_conf,
4543 [ACTION_MODIFY_FIELD_SRC_OFFSET] = {
4544 .name = "src_offset",
4545 .help = "source field bit offset",
4546 .next = NEXT(action_modify_field_src,
4547 NEXT_ENTRY(COMMON_UNSIGNED)),
4548 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4550 .call = parse_vc_conf,
4552 [ACTION_MODIFY_FIELD_SRC_VALUE] = {
4553 .name = "src_value",
4554 .help = "source immediate value",
4555 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
4556 NEXT_ENTRY(COMMON_UNSIGNED)),
4557 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4559 .call = parse_vc_conf,
4561 [ACTION_MODIFY_FIELD_WIDTH] = {
4563 .help = "number of bits to copy",
4564 .next = NEXT(NEXT_ENTRY(ACTION_NEXT),
4565 NEXT_ENTRY(COMMON_UNSIGNED)),
4566 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4568 .call = parse_vc_conf,
4570 /* Top level command. */
4573 .help = "set raw encap/decap/sample data",
4574 .type = "set raw_encap|raw_decap <index> <pattern>"
4575 " or set sample_actions <index> <action>",
4576 .next = NEXT(NEXT_ENTRY
4579 SET_SAMPLE_ACTIONS)),
4580 .call = parse_set_init,
4582 /* Sub-level commands. */
4584 .name = "raw_encap",
4585 .help = "set raw encap data",
4586 .next = NEXT(next_set_raw),
4587 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4588 (offsetof(struct buffer, port),
4589 sizeof(((struct buffer *)0)->port),
4590 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
4591 .call = parse_set_raw_encap_decap,
4594 .name = "raw_decap",
4595 .help = "set raw decap data",
4596 .next = NEXT(next_set_raw),
4597 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4598 (offsetof(struct buffer, port),
4599 sizeof(((struct buffer *)0)->port),
4600 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
4601 .call = parse_set_raw_encap_decap,
4605 .type = "COMMON_UNSIGNED",
4606 .help = "index of raw_encap/raw_decap data",
4607 .next = NEXT(next_item),
4610 [SET_SAMPLE_INDEX] = {
4613 .help = "index of sample actions",
4614 .next = NEXT(next_action_sample),
4617 [SET_SAMPLE_ACTIONS] = {
4618 .name = "sample_actions",
4619 .help = "set sample actions list",
4620 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
4621 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4622 (offsetof(struct buffer, port),
4623 sizeof(((struct buffer *)0)->port),
4624 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
4625 .call = parse_set_sample_action,
4627 [ACTION_SET_TAG] = {
4630 .priv = PRIV_ACTION(SET_TAG,
4631 sizeof(struct rte_flow_action_set_tag)),
4632 .next = NEXT(action_set_tag),
4635 [ACTION_SET_TAG_INDEX] = {
4637 .help = "index of tag array",
4638 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4639 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
4640 .call = parse_vc_conf,
4642 [ACTION_SET_TAG_DATA] = {
4644 .help = "tag value",
4645 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4646 .args = ARGS(ARGS_ENTRY
4647 (struct rte_flow_action_set_tag, data)),
4648 .call = parse_vc_conf,
4650 [ACTION_SET_TAG_MASK] = {
4652 .help = "mask for tag value",
4653 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4654 .args = ARGS(ARGS_ENTRY
4655 (struct rte_flow_action_set_tag, mask)),
4656 .call = parse_vc_conf,
4658 [ACTION_SET_META] = {
4660 .help = "set metadata",
4661 .priv = PRIV_ACTION(SET_META,
4662 sizeof(struct rte_flow_action_set_meta)),
4663 .next = NEXT(action_set_meta),
4664 .call = parse_vc_action_set_meta,
4666 [ACTION_SET_META_DATA] = {
4668 .help = "metadata value",
4669 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
4670 .args = ARGS(ARGS_ENTRY
4671 (struct rte_flow_action_set_meta, data)),
4672 .call = parse_vc_conf,
4674 [ACTION_SET_META_MASK] = {
4676 .help = "mask for metadata value",
4677 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
4678 .args = ARGS(ARGS_ENTRY
4679 (struct rte_flow_action_set_meta, mask)),
4680 .call = parse_vc_conf,
4682 [ACTION_SET_IPV4_DSCP] = {
4683 .name = "set_ipv4_dscp",
4684 .help = "set DSCP value",
4685 .priv = PRIV_ACTION(SET_IPV4_DSCP,
4686 sizeof(struct rte_flow_action_set_dscp)),
4687 .next = NEXT(action_set_ipv4_dscp),
4690 [ACTION_SET_IPV4_DSCP_VALUE] = {
4691 .name = "dscp_value",
4692 .help = "new IPv4 DSCP value to set",
4693 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
4694 .args = ARGS(ARGS_ENTRY
4695 (struct rte_flow_action_set_dscp, dscp)),
4696 .call = parse_vc_conf,
4698 [ACTION_SET_IPV6_DSCP] = {
4699 .name = "set_ipv6_dscp",
4700 .help = "set DSCP value",
4701 .priv = PRIV_ACTION(SET_IPV6_DSCP,
4702 sizeof(struct rte_flow_action_set_dscp)),
4703 .next = NEXT(action_set_ipv6_dscp),
4706 [ACTION_SET_IPV6_DSCP_VALUE] = {
4707 .name = "dscp_value",
4708 .help = "new IPv6 DSCP value to set",
4709 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
4710 .args = ARGS(ARGS_ENTRY
4711 (struct rte_flow_action_set_dscp, dscp)),
4712 .call = parse_vc_conf,
4716 .help = "set a specific metadata header",
4717 .next = NEXT(action_age),
4718 .priv = PRIV_ACTION(AGE,
4719 sizeof(struct rte_flow_action_age)),
4722 [ACTION_AGE_TIMEOUT] = {
4724 .help = "flow age timeout value",
4725 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
4727 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
4728 .call = parse_vc_conf,
4732 .help = "set a sample action",
4733 .next = NEXT(action_sample),
4734 .priv = PRIV_ACTION(SAMPLE,
4735 sizeof(struct action_sample_data)),
4736 .call = parse_vc_action_sample,
4738 [ACTION_SAMPLE_RATIO] = {
4740 .help = "flow sample ratio value",
4741 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
4742 .args = ARGS(ARGS_ENTRY_ARB
4743 (offsetof(struct action_sample_data, conf) +
4744 offsetof(struct rte_flow_action_sample, ratio),
4745 sizeof(((struct rte_flow_action_sample *)0)->
4748 [ACTION_SAMPLE_INDEX] = {
4750 .help = "the index of sample actions list",
4751 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
4753 [ACTION_SAMPLE_INDEX_VALUE] = {
4755 .type = "COMMON_UNSIGNED",
4756 .help = "unsigned integer value",
4757 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4758 .call = parse_vc_action_sample_index,
4759 .comp = comp_set_sample_index,
4761 [ACTION_CONNTRACK] = {
4762 .name = "conntrack",
4763 .help = "create a conntrack object",
4764 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4765 .priv = PRIV_ACTION(CONNTRACK,
4766 sizeof(struct rte_flow_action_conntrack)),
4769 [ACTION_CONNTRACK_UPDATE] = {
4770 .name = "conntrack_update",
4771 .help = "update a conntrack object",
4772 .next = NEXT(action_update_conntrack),
4773 .priv = PRIV_ACTION(CONNTRACK,
4774 sizeof(struct rte_flow_modify_conntrack)),
4777 [ACTION_CONNTRACK_UPDATE_DIR] = {
4779 .help = "update a conntrack object direction",
4780 .next = NEXT(action_update_conntrack),
4781 .call = parse_vc_action_conntrack_update,
4783 [ACTION_CONNTRACK_UPDATE_CTX] = {
4785 .help = "update a conntrack object context",
4786 .next = NEXT(action_update_conntrack),
4787 .call = parse_vc_action_conntrack_update,
4789 /* Indirect action destroy arguments. */
4790 [INDIRECT_ACTION_DESTROY_ID] = {
4791 .name = "action_id",
4792 .help = "specify a indirect action id to destroy",
4793 .next = NEXT(next_ia_destroy_attr,
4794 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4795 .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
4796 args.ia_destroy.action_id)),
4797 .call = parse_ia_destroy,
4799 /* Indirect action create arguments. */
4800 [INDIRECT_ACTION_CREATE_ID] = {
4801 .name = "action_id",
4802 .help = "specify a indirect action id to create",
4803 .next = NEXT(next_ia_create_attr,
4804 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4805 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4807 [ACTION_INDIRECT] = {
4809 .help = "apply indirect action by id",
4810 .priv = PRIV_ACTION(INDIRECT, 0),
4811 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
4812 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
4815 [INDIRECT_ACTION_ID2PTR] = {
4816 .name = "{action_id}",
4817 .type = "INDIRECT_ACTION_ID",
4818 .help = "indirect action id",
4819 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4820 .call = parse_ia_id2ptr,
4823 [INDIRECT_ACTION_INGRESS] = {
4825 .help = "affect rule to ingress",
4826 .next = NEXT(next_ia_create_attr),
4829 [INDIRECT_ACTION_EGRESS] = {
4831 .help = "affect rule to egress",
4832 .next = NEXT(next_ia_create_attr),
4835 [INDIRECT_ACTION_TRANSFER] = {
4837 .help = "affect rule to transfer",
4838 .next = NEXT(next_ia_create_attr),
4841 [INDIRECT_ACTION_SPEC] = {
4843 .help = "specify action to create indirect handle",
4844 .next = NEXT(next_action),
4847 .name = "g_actions",
4848 .help = "submit a list of associated actions for green",
4849 .next = NEXT(next_action),
4853 .name = "y_actions",
4854 .help = "submit a list of associated actions for yellow",
4855 .next = NEXT(next_action),
4858 .name = "r_actions",
4859 .help = "submit a list of associated actions for red",
4860 .next = NEXT(next_action),
4863 /* Top-level command. */
4866 .type = "port meter policy {port_id} {arg}",
4867 .help = "add port meter policy",
4868 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
4871 /* Sub-level commands. */
4874 .help = "add port meter policy",
4875 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
4877 [ITEM_POL_METER] = {
4879 .help = "add port meter policy",
4880 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
4882 [ITEM_POL_POLICY] = {
4884 .help = "add port meter policy",
4885 .next = NEXT(NEXT_ENTRY(ACTION_POL_R),
4886 NEXT_ENTRY(ACTION_POL_Y),
4887 NEXT_ENTRY(ACTION_POL_G),
4888 NEXT_ENTRY(COMMON_POLICY_ID),
4889 NEXT_ENTRY(COMMON_PORT_ID)),
4890 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
4891 ARGS_ENTRY(struct buffer, port)),
4896 /** Remove and return last entry from argument stack. */
4897 static const struct arg *
4898 pop_args(struct context *ctx)
4900 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
4903 /** Add entry on top of the argument stack. */
4905 push_args(struct context *ctx, const struct arg *arg)
4907 if (ctx->args_num == CTX_STACK_SIZE)
4909 ctx->args[ctx->args_num++] = arg;
4913 /** Spread value into buffer according to bit-mask. */
4915 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
4917 uint32_t i = arg->size;
4925 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4934 unsigned int shift = 0;
4935 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
4937 for (shift = 0; arg->mask[i] >> shift; ++shift) {
4938 if (!(arg->mask[i] & (1 << shift)))
4943 *buf &= ~(1 << shift);
4944 *buf |= (val & 1) << shift;
4952 /** Compare a string with a partial one of a given length. */
4954 strcmp_partial(const char *full, const char *partial, size_t partial_len)
4956 int r = strncmp(full, partial, partial_len);
4960 if (strlen(full) <= partial_len)
4962 return full[partial_len];
4966 * Parse a prefix length and generate a bit-mask.
4968 * Last argument (ctx->args) is retrieved to determine mask size, storage
4969 * location and whether the result must use network byte ordering.
4972 parse_prefix(struct context *ctx, const struct token *token,
4973 const char *str, unsigned int len,
4974 void *buf, unsigned int size)
4976 const struct arg *arg = pop_args(ctx);
4977 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
4984 /* Argument is expected. */
4988 u = strtoumax(str, &end, 0);
4989 if (errno || (size_t)(end - str) != len)
4994 extra = arg_entry_bf_fill(NULL, 0, arg);
5003 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
5004 !arg_entry_bf_fill(ctx->objmask, -1, arg))
5011 if (bytes > size || bytes + !!extra > size)
5015 buf = (uint8_t *)ctx->object + arg->offset;
5016 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5018 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
5019 memset(buf, 0x00, size - bytes);
5021 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
5025 memset(buf, 0xff, bytes);
5026 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
5028 ((uint8_t *)buf)[bytes] = conv[extra];
5031 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5034 push_args(ctx, arg);
5038 /** Default parsing function for token name matching. */
5040 parse_default(struct context *ctx, const struct token *token,
5041 const char *str, unsigned int len,
5042 void *buf, unsigned int size)
5047 if (strcmp_partial(token->name, str, len))
5052 /** Parse flow command, initialize output buffer for subsequent tokens. */
5054 parse_init(struct context *ctx, const struct token *token,
5055 const char *str, unsigned int len,
5056 void *buf, unsigned int size)
5058 struct buffer *out = buf;
5060 /* Token name must match. */
5061 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5063 /* Nothing else to do if there is no buffer. */
5066 /* Make sure buffer is large enough. */
5067 if (size < sizeof(*out))
5069 /* Initialize buffer. */
5070 memset(out, 0x00, sizeof(*out));
5071 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5074 ctx->objmask = NULL;
5078 /** Parse tokens for indirect action commands. */
5080 parse_ia(struct context *ctx, const struct token *token,
5081 const char *str, unsigned int len,
5082 void *buf, unsigned int size)
5084 struct buffer *out = buf;
5086 /* Token name must match. */
5087 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5089 /* Nothing else to do if there is no buffer. */
5092 if (!out->command) {
5093 if (ctx->curr != INDIRECT_ACTION)
5095 if (sizeof(*out) > size)
5097 out->command = ctx->curr;
5100 ctx->objmask = NULL;
5101 out->args.vc.data = (uint8_t *)out + size;
5104 switch (ctx->curr) {
5105 case INDIRECT_ACTION_CREATE:
5106 case INDIRECT_ACTION_UPDATE:
5107 out->args.vc.actions =
5108 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5110 out->args.vc.attr.group = UINT32_MAX;
5112 case INDIRECT_ACTION_QUERY:
5113 out->command = ctx->curr;
5116 ctx->objmask = NULL;
5118 case INDIRECT_ACTION_EGRESS:
5119 out->args.vc.attr.egress = 1;
5121 case INDIRECT_ACTION_INGRESS:
5122 out->args.vc.attr.ingress = 1;
5124 case INDIRECT_ACTION_TRANSFER:
5125 out->args.vc.attr.transfer = 1;
5133 /** Parse tokens for indirect action destroy command. */
5135 parse_ia_destroy(struct context *ctx, const struct token *token,
5136 const char *str, unsigned int len,
5137 void *buf, unsigned int size)
5139 struct buffer *out = buf;
5140 uint32_t *action_id;
5142 /* Token name must match. */
5143 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5145 /* Nothing else to do if there is no buffer. */
5148 if (!out->command || out->command == INDIRECT_ACTION) {
5149 if (ctx->curr != INDIRECT_ACTION_DESTROY)
5151 if (sizeof(*out) > size)
5153 out->command = ctx->curr;
5156 ctx->objmask = NULL;
5157 out->args.ia_destroy.action_id =
5158 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5162 action_id = out->args.ia_destroy.action_id
5163 + out->args.ia_destroy.action_id_n++;
5164 if ((uint8_t *)action_id > (uint8_t *)out + size)
5167 ctx->object = action_id;
5168 ctx->objmask = NULL;
5172 /** Parse tokens for meter policy action commands. */
5174 parse_mp(struct context *ctx, const struct token *token,
5175 const char *str, unsigned int len,
5176 void *buf, unsigned int size)
5178 struct buffer *out = buf;
5180 /* Token name must match. */
5181 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5183 /* Nothing else to do if there is no buffer. */
5186 if (!out->command) {
5187 if (ctx->curr != ITEM_POL_POLICY)
5189 if (sizeof(*out) > size)
5191 out->command = ctx->curr;
5194 ctx->objmask = NULL;
5195 out->args.vc.data = (uint8_t *)out + size;
5198 switch (ctx->curr) {
5200 out->args.vc.actions =
5201 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5203 out->command = ctx->curr;
5206 ctx->objmask = NULL;
5213 /** Parse tokens for validate/create commands. */
5215 parse_vc(struct context *ctx, const struct token *token,
5216 const char *str, unsigned int len,
5217 void *buf, unsigned int size)
5219 struct buffer *out = buf;
5223 /* Token name must match. */
5224 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5226 /* Nothing else to do if there is no buffer. */
5229 if (!out->command) {
5230 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
5232 if (sizeof(*out) > size)
5234 out->command = ctx->curr;
5237 ctx->objmask = NULL;
5238 out->args.vc.data = (uint8_t *)out + size;
5242 switch (ctx->curr) {
5244 ctx->object = &out->args.vc.attr;
5247 case VC_TUNNEL_MATCH:
5248 ctx->object = &out->args.vc.tunnel_ops;
5251 ctx->objmask = NULL;
5252 switch (ctx->curr) {
5257 out->args.vc.tunnel_ops.enabled = 1;
5258 out->args.vc.tunnel_ops.actions = 1;
5260 case VC_TUNNEL_MATCH:
5261 out->args.vc.tunnel_ops.enabled = 1;
5262 out->args.vc.tunnel_ops.items = 1;
5265 out->args.vc.attr.ingress = 1;
5268 out->args.vc.attr.egress = 1;
5271 out->args.vc.attr.transfer = 1;
5274 out->args.vc.pattern =
5275 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5277 ctx->object = out->args.vc.pattern;
5278 ctx->objmask = NULL;
5281 out->args.vc.actions =
5282 (void *)RTE_ALIGN_CEIL((uintptr_t)
5283 (out->args.vc.pattern +
5284 out->args.vc.pattern_n),
5286 ctx->object = out->args.vc.actions;
5287 ctx->objmask = NULL;
5294 if (!out->args.vc.actions) {
5295 const struct parse_item_priv *priv = token->priv;
5296 struct rte_flow_item *item =
5297 out->args.vc.pattern + out->args.vc.pattern_n;
5299 data_size = priv->size * 3; /* spec, last, mask */
5300 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5301 (out->args.vc.data - data_size),
5303 if ((uint8_t *)item + sizeof(*item) > data)
5305 *item = (struct rte_flow_item){
5308 ++out->args.vc.pattern_n;
5310 ctx->objmask = NULL;
5312 const struct parse_action_priv *priv = token->priv;
5313 struct rte_flow_action *action =
5314 out->args.vc.actions + out->args.vc.actions_n;
5316 data_size = priv->size; /* configuration */
5317 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5318 (out->args.vc.data - data_size),
5320 if ((uint8_t *)action + sizeof(*action) > data)
5322 *action = (struct rte_flow_action){
5324 .conf = data_size ? data : NULL,
5326 ++out->args.vc.actions_n;
5327 ctx->object = action;
5328 ctx->objmask = NULL;
5330 memset(data, 0, data_size);
5331 out->args.vc.data = data;
5332 ctx->objdata = data_size;
5336 /** Parse pattern item parameter type. */
5338 parse_vc_spec(struct context *ctx, const struct token *token,
5339 const char *str, unsigned int len,
5340 void *buf, unsigned int size)
5342 struct buffer *out = buf;
5343 struct rte_flow_item *item;
5349 /* Token name must match. */
5350 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5352 /* Parse parameter types. */
5353 switch (ctx->curr) {
5354 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
5360 case ITEM_PARAM_SPEC:
5363 case ITEM_PARAM_LAST:
5366 case ITEM_PARAM_PREFIX:
5367 /* Modify next token to expect a prefix. */
5368 if (ctx->next_num < 2)
5370 ctx->next[ctx->next_num - 2] = prefix;
5372 case ITEM_PARAM_MASK:
5378 /* Nothing else to do if there is no buffer. */
5381 if (!out->args.vc.pattern_n)
5383 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
5384 data_size = ctx->objdata / 3; /* spec, last, mask */
5385 /* Point to selected object. */
5386 ctx->object = out->args.vc.data + (data_size * index);
5388 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
5389 item->mask = ctx->objmask;
5391 ctx->objmask = NULL;
5392 /* Update relevant item pointer. */
5393 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
5398 /** Parse action configuration field. */
5400 parse_vc_conf(struct context *ctx, const struct token *token,
5401 const char *str, unsigned int len,
5402 void *buf, unsigned int size)
5404 struct buffer *out = buf;
5407 /* Token name must match. */
5408 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5410 /* Nothing else to do if there is no buffer. */
5413 /* Point to selected object. */
5414 ctx->object = out->args.vc.data;
5415 ctx->objmask = NULL;
5419 /** Parse eCPRI common header type field. */
5421 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
5422 const char *str, unsigned int len,
5423 void *buf, unsigned int size)
5425 struct rte_flow_item_ecpri *ecpri;
5426 struct rte_flow_item_ecpri *ecpri_mask;
5427 struct rte_flow_item *item;
5430 struct buffer *out = buf;
5431 const struct arg *arg;
5434 /* Token name must match. */
5435 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5437 switch (ctx->curr) {
5438 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
5439 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
5441 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
5442 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
5444 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
5445 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
5452 arg = pop_args(ctx);
5455 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
5456 ecpri->hdr.common.type = msg_type;
5457 data_size = ctx->objdata / 3; /* spec, last, mask */
5458 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
5460 ecpri_mask->hdr.common.type = 0xFF;
5462 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
5463 ecpri_mask->hdr.common.u32 =
5464 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
5466 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
5468 item->mask = ecpri_mask;
5472 /** Parse meter color action type. */
5474 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
5475 const char *str, unsigned int len,
5476 void *buf, unsigned int size)
5478 struct rte_flow_action *action_data;
5479 struct rte_flow_action_meter_color *conf;
5480 enum rte_color color;
5484 /* Token name must match. */
5485 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5487 switch (ctx->curr) {
5488 case ACTION_METER_COLOR_GREEN:
5489 color = RTE_COLOR_GREEN;
5491 case ACTION_METER_COLOR_YELLOW:
5492 color = RTE_COLOR_YELLOW;
5494 case ACTION_METER_COLOR_RED:
5495 color = RTE_COLOR_RED;
5503 action_data = ctx->object;
5504 conf = (struct rte_flow_action_meter_color *)
5505 (uintptr_t)(action_data->conf);
5506 conf->color = color;
5510 /** Parse RSS action. */
5512 parse_vc_action_rss(struct context *ctx, const struct token *token,
5513 const char *str, unsigned int len,
5514 void *buf, unsigned int size)
5516 struct buffer *out = buf;
5517 struct rte_flow_action *action;
5518 struct action_rss_data *action_rss_data;
5522 ret = parse_vc(ctx, token, str, len, buf, size);
5525 /* Nothing else to do if there is no buffer. */
5528 if (!out->args.vc.actions_n)
5530 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5531 /* Point to selected object. */
5532 ctx->object = out->args.vc.data;
5533 ctx->objmask = NULL;
5534 /* Set up default configuration. */
5535 action_rss_data = ctx->object;
5536 *action_rss_data = (struct action_rss_data){
5537 .conf = (struct rte_flow_action_rss){
5538 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
5542 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
5544 .queue = action_rss_data->queue,
5548 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
5549 action_rss_data->queue[i] = i;
5550 action->conf = &action_rss_data->conf;
5555 * Parse func field for RSS action.
5557 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
5558 * ACTION_RSS_FUNC_* index that called this function.
5561 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
5562 const char *str, unsigned int len,
5563 void *buf, unsigned int size)
5565 struct action_rss_data *action_rss_data;
5566 enum rte_eth_hash_function func;
5570 /* Token name must match. */
5571 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5573 switch (ctx->curr) {
5574 case ACTION_RSS_FUNC_DEFAULT:
5575 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
5577 case ACTION_RSS_FUNC_TOEPLITZ:
5578 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
5580 case ACTION_RSS_FUNC_SIMPLE_XOR:
5581 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
5583 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
5584 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
5591 action_rss_data = ctx->object;
5592 action_rss_data->conf.func = func;
5597 * Parse type field for RSS action.
5599 * Valid tokens are type field names and the "end" token.
5602 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
5603 const char *str, unsigned int len,
5604 void *buf, unsigned int size)
5606 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
5607 struct action_rss_data *action_rss_data;
5613 if (ctx->curr != ACTION_RSS_TYPE)
5615 if (!(ctx->objdata >> 16) && ctx->object) {
5616 action_rss_data = ctx->object;
5617 action_rss_data->conf.types = 0;
5619 if (!strcmp_partial("end", str, len)) {
5620 ctx->objdata &= 0xffff;
5623 for (i = 0; rss_type_table[i].str; ++i)
5624 if (!strcmp_partial(rss_type_table[i].str, str, len))
5626 if (!rss_type_table[i].str)
5628 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
5630 if (ctx->next_num == RTE_DIM(ctx->next))
5632 ctx->next[ctx->next_num++] = next;
5635 action_rss_data = ctx->object;
5636 action_rss_data->conf.types |= rss_type_table[i].rss_type;
5641 * Parse queue field for RSS action.
5643 * Valid tokens are queue indices and the "end" token.
5646 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
5647 const char *str, unsigned int len,
5648 void *buf, unsigned int size)
5650 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
5651 struct action_rss_data *action_rss_data;
5652 const struct arg *arg;
5659 if (ctx->curr != ACTION_RSS_QUEUE)
5661 i = ctx->objdata >> 16;
5662 if (!strcmp_partial("end", str, len)) {
5663 ctx->objdata &= 0xffff;
5666 if (i >= ACTION_RSS_QUEUE_NUM)
5668 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
5669 i * sizeof(action_rss_data->queue[i]),
5670 sizeof(action_rss_data->queue[i]));
5671 if (push_args(ctx, arg))
5673 ret = parse_int(ctx, token, str, len, NULL, 0);
5679 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
5681 if (ctx->next_num == RTE_DIM(ctx->next))
5683 ctx->next[ctx->next_num++] = next;
5687 action_rss_data = ctx->object;
5688 action_rss_data->conf.queue_num = i;
5689 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
5693 /** Setup VXLAN encap configuration. */
5695 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
5697 /* Set up default configuration. */
5698 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
5699 .conf = (struct rte_flow_action_vxlan_encap){
5700 .definition = action_vxlan_encap_data->items,
5704 .type = RTE_FLOW_ITEM_TYPE_ETH,
5705 .spec = &action_vxlan_encap_data->item_eth,
5706 .mask = &rte_flow_item_eth_mask,
5709 .type = RTE_FLOW_ITEM_TYPE_VLAN,
5710 .spec = &action_vxlan_encap_data->item_vlan,
5711 .mask = &rte_flow_item_vlan_mask,
5714 .type = RTE_FLOW_ITEM_TYPE_IPV4,
5715 .spec = &action_vxlan_encap_data->item_ipv4,
5716 .mask = &rte_flow_item_ipv4_mask,
5719 .type = RTE_FLOW_ITEM_TYPE_UDP,
5720 .spec = &action_vxlan_encap_data->item_udp,
5721 .mask = &rte_flow_item_udp_mask,
5724 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
5725 .spec = &action_vxlan_encap_data->item_vxlan,
5726 .mask = &rte_flow_item_vxlan_mask,
5729 .type = RTE_FLOW_ITEM_TYPE_END,
5734 .tci = vxlan_encap_conf.vlan_tci,
5738 .src_addr = vxlan_encap_conf.ipv4_src,
5739 .dst_addr = vxlan_encap_conf.ipv4_dst,
5742 .src_port = vxlan_encap_conf.udp_src,
5743 .dst_port = vxlan_encap_conf.udp_dst,
5745 .item_vxlan.flags = 0,
5747 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
5748 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5749 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
5750 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5751 if (!vxlan_encap_conf.select_ipv4) {
5752 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
5753 &vxlan_encap_conf.ipv6_src,
5754 sizeof(vxlan_encap_conf.ipv6_src));
5755 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
5756 &vxlan_encap_conf.ipv6_dst,
5757 sizeof(vxlan_encap_conf.ipv6_dst));
5758 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
5759 .type = RTE_FLOW_ITEM_TYPE_IPV6,
5760 .spec = &action_vxlan_encap_data->item_ipv6,
5761 .mask = &rte_flow_item_ipv6_mask,
5764 if (!vxlan_encap_conf.select_vlan)
5765 action_vxlan_encap_data->items[1].type =
5766 RTE_FLOW_ITEM_TYPE_VOID;
5767 if (vxlan_encap_conf.select_tos_ttl) {
5768 if (vxlan_encap_conf.select_ipv4) {
5769 static struct rte_flow_item_ipv4 ipv4_mask_tos;
5771 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
5772 sizeof(ipv4_mask_tos));
5773 ipv4_mask_tos.hdr.type_of_service = 0xff;
5774 ipv4_mask_tos.hdr.time_to_live = 0xff;
5775 action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
5776 vxlan_encap_conf.ip_tos;
5777 action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
5778 vxlan_encap_conf.ip_ttl;
5779 action_vxlan_encap_data->items[2].mask =
5782 static struct rte_flow_item_ipv6 ipv6_mask_tos;
5784 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
5785 sizeof(ipv6_mask_tos));
5786 ipv6_mask_tos.hdr.vtc_flow |=
5787 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
5788 ipv6_mask_tos.hdr.hop_limits = 0xff;
5789 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
5791 ((uint32_t)vxlan_encap_conf.ip_tos <<
5792 RTE_IPV6_HDR_TC_SHIFT);
5793 action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
5794 vxlan_encap_conf.ip_ttl;
5795 action_vxlan_encap_data->items[2].mask =
5799 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
5800 RTE_DIM(vxlan_encap_conf.vni));
5804 /** Parse VXLAN encap action. */
5806 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
5807 const char *str, unsigned int len,
5808 void *buf, unsigned int size)
5810 struct buffer *out = buf;
5811 struct rte_flow_action *action;
5812 struct action_vxlan_encap_data *action_vxlan_encap_data;
5815 ret = parse_vc(ctx, token, str, len, buf, size);
5818 /* Nothing else to do if there is no buffer. */
5821 if (!out->args.vc.actions_n)
5823 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5824 /* Point to selected object. */
5825 ctx->object = out->args.vc.data;
5826 ctx->objmask = NULL;
5827 action_vxlan_encap_data = ctx->object;
5828 parse_setup_vxlan_encap_data(action_vxlan_encap_data);
5829 action->conf = &action_vxlan_encap_data->conf;
5833 /** Setup NVGRE encap configuration. */
5835 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
5837 /* Set up default configuration. */
5838 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
5839 .conf = (struct rte_flow_action_nvgre_encap){
5840 .definition = action_nvgre_encap_data->items,
5844 .type = RTE_FLOW_ITEM_TYPE_ETH,
5845 .spec = &action_nvgre_encap_data->item_eth,
5846 .mask = &rte_flow_item_eth_mask,
5849 .type = RTE_FLOW_ITEM_TYPE_VLAN,
5850 .spec = &action_nvgre_encap_data->item_vlan,
5851 .mask = &rte_flow_item_vlan_mask,
5854 .type = RTE_FLOW_ITEM_TYPE_IPV4,
5855 .spec = &action_nvgre_encap_data->item_ipv4,
5856 .mask = &rte_flow_item_ipv4_mask,
5859 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
5860 .spec = &action_nvgre_encap_data->item_nvgre,
5861 .mask = &rte_flow_item_nvgre_mask,
5864 .type = RTE_FLOW_ITEM_TYPE_END,
5869 .tci = nvgre_encap_conf.vlan_tci,
5873 .src_addr = nvgre_encap_conf.ipv4_src,
5874 .dst_addr = nvgre_encap_conf.ipv4_dst,
5876 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
5877 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
5878 .item_nvgre.flow_id = 0,
5880 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
5881 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5882 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
5883 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5884 if (!nvgre_encap_conf.select_ipv4) {
5885 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
5886 &nvgre_encap_conf.ipv6_src,
5887 sizeof(nvgre_encap_conf.ipv6_src));
5888 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
5889 &nvgre_encap_conf.ipv6_dst,
5890 sizeof(nvgre_encap_conf.ipv6_dst));
5891 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
5892 .type = RTE_FLOW_ITEM_TYPE_IPV6,
5893 .spec = &action_nvgre_encap_data->item_ipv6,
5894 .mask = &rte_flow_item_ipv6_mask,
5897 if (!nvgre_encap_conf.select_vlan)
5898 action_nvgre_encap_data->items[1].type =
5899 RTE_FLOW_ITEM_TYPE_VOID;
5900 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
5901 RTE_DIM(nvgre_encap_conf.tni));
5905 /** Parse NVGRE encap action. */
5907 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
5908 const char *str, unsigned int len,
5909 void *buf, unsigned int size)
5911 struct buffer *out = buf;
5912 struct rte_flow_action *action;
5913 struct action_nvgre_encap_data *action_nvgre_encap_data;
5916 ret = parse_vc(ctx, token, str, len, buf, size);
5919 /* Nothing else to do if there is no buffer. */
5922 if (!out->args.vc.actions_n)
5924 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5925 /* Point to selected object. */
5926 ctx->object = out->args.vc.data;
5927 ctx->objmask = NULL;
5928 action_nvgre_encap_data = ctx->object;
5929 parse_setup_nvgre_encap_data(action_nvgre_encap_data);
5930 action->conf = &action_nvgre_encap_data->conf;
5934 /** Parse l2 encap action. */
5936 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
5937 const char *str, unsigned int len,
5938 void *buf, unsigned int size)
5940 struct buffer *out = buf;
5941 struct rte_flow_action *action;
5942 struct action_raw_encap_data *action_encap_data;
5943 struct rte_flow_item_eth eth = { .type = 0, };
5944 struct rte_flow_item_vlan vlan = {
5945 .tci = mplsoudp_encap_conf.vlan_tci,
5951 ret = parse_vc(ctx, token, str, len, buf, size);
5954 /* Nothing else to do if there is no buffer. */
5957 if (!out->args.vc.actions_n)
5959 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5960 /* Point to selected object. */
5961 ctx->object = out->args.vc.data;
5962 ctx->objmask = NULL;
5963 /* Copy the headers to the buffer. */
5964 action_encap_data = ctx->object;
5965 *action_encap_data = (struct action_raw_encap_data) {
5966 .conf = (struct rte_flow_action_raw_encap){
5967 .data = action_encap_data->data,
5971 header = action_encap_data->data;
5972 if (l2_encap_conf.select_vlan)
5973 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5974 else if (l2_encap_conf.select_ipv4)
5975 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5977 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5978 memcpy(eth.dst.addr_bytes,
5979 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5980 memcpy(eth.src.addr_bytes,
5981 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5982 memcpy(header, ð, sizeof(eth));
5983 header += sizeof(eth);
5984 if (l2_encap_conf.select_vlan) {
5985 if (l2_encap_conf.select_ipv4)
5986 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5988 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5989 memcpy(header, &vlan, sizeof(vlan));
5990 header += sizeof(vlan);
5992 action_encap_data->conf.size = header -
5993 action_encap_data->data;
5994 action->conf = &action_encap_data->conf;
5998 /** Parse l2 decap action. */
6000 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
6001 const char *str, unsigned int len,
6002 void *buf, unsigned int size)
6004 struct buffer *out = buf;
6005 struct rte_flow_action *action;
6006 struct action_raw_decap_data *action_decap_data;
6007 struct rte_flow_item_eth eth = { .type = 0, };
6008 struct rte_flow_item_vlan vlan = {
6009 .tci = mplsoudp_encap_conf.vlan_tci,
6015 ret = parse_vc(ctx, token, str, len, buf, size);
6018 /* Nothing else to do if there is no buffer. */
6021 if (!out->args.vc.actions_n)
6023 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6024 /* Point to selected object. */
6025 ctx->object = out->args.vc.data;
6026 ctx->objmask = NULL;
6027 /* Copy the headers to the buffer. */
6028 action_decap_data = ctx->object;
6029 *action_decap_data = (struct action_raw_decap_data) {
6030 .conf = (struct rte_flow_action_raw_decap){
6031 .data = action_decap_data->data,
6035 header = action_decap_data->data;
6036 if (l2_decap_conf.select_vlan)
6037 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6038 memcpy(header, ð, sizeof(eth));
6039 header += sizeof(eth);
6040 if (l2_decap_conf.select_vlan) {
6041 memcpy(header, &vlan, sizeof(vlan));
6042 header += sizeof(vlan);
6044 action_decap_data->conf.size = header -
6045 action_decap_data->data;
6046 action->conf = &action_decap_data->conf;
6050 #define ETHER_TYPE_MPLS_UNICAST 0x8847
6052 /** Parse MPLSOGRE encap action. */
6054 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
6055 const char *str, unsigned int len,
6056 void *buf, unsigned int size)
6058 struct buffer *out = buf;
6059 struct rte_flow_action *action;
6060 struct action_raw_encap_data *action_encap_data;
6061 struct rte_flow_item_eth eth = { .type = 0, };
6062 struct rte_flow_item_vlan vlan = {
6063 .tci = mplsogre_encap_conf.vlan_tci,
6066 struct rte_flow_item_ipv4 ipv4 = {
6068 .src_addr = mplsogre_encap_conf.ipv4_src,
6069 .dst_addr = mplsogre_encap_conf.ipv4_dst,
6070 .next_proto_id = IPPROTO_GRE,
6071 .version_ihl = RTE_IPV4_VHL_DEF,
6072 .time_to_live = IPDEFTTL,
6075 struct rte_flow_item_ipv6 ipv6 = {
6077 .proto = IPPROTO_GRE,
6078 .hop_limits = IPDEFTTL,
6081 struct rte_flow_item_gre gre = {
6082 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6084 struct rte_flow_item_mpls mpls = {
6090 ret = parse_vc(ctx, token, str, len, buf, size);
6093 /* Nothing else to do if there is no buffer. */
6096 if (!out->args.vc.actions_n)
6098 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6099 /* Point to selected object. */
6100 ctx->object = out->args.vc.data;
6101 ctx->objmask = NULL;
6102 /* Copy the headers to the buffer. */
6103 action_encap_data = ctx->object;
6104 *action_encap_data = (struct action_raw_encap_data) {
6105 .conf = (struct rte_flow_action_raw_encap){
6106 .data = action_encap_data->data,
6111 header = action_encap_data->data;
6112 if (mplsogre_encap_conf.select_vlan)
6113 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6114 else if (mplsogre_encap_conf.select_ipv4)
6115 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6117 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6118 memcpy(eth.dst.addr_bytes,
6119 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6120 memcpy(eth.src.addr_bytes,
6121 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6122 memcpy(header, ð, sizeof(eth));
6123 header += sizeof(eth);
6124 if (mplsogre_encap_conf.select_vlan) {
6125 if (mplsogre_encap_conf.select_ipv4)
6126 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6128 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6129 memcpy(header, &vlan, sizeof(vlan));
6130 header += sizeof(vlan);
6132 if (mplsogre_encap_conf.select_ipv4) {
6133 memcpy(header, &ipv4, sizeof(ipv4));
6134 header += sizeof(ipv4);
6136 memcpy(&ipv6.hdr.src_addr,
6137 &mplsogre_encap_conf.ipv6_src,
6138 sizeof(mplsogre_encap_conf.ipv6_src));
6139 memcpy(&ipv6.hdr.dst_addr,
6140 &mplsogre_encap_conf.ipv6_dst,
6141 sizeof(mplsogre_encap_conf.ipv6_dst));
6142 memcpy(header, &ipv6, sizeof(ipv6));
6143 header += sizeof(ipv6);
6145 memcpy(header, &gre, sizeof(gre));
6146 header += sizeof(gre);
6147 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
6148 RTE_DIM(mplsogre_encap_conf.label));
6149 mpls.label_tc_s[2] |= 0x1;
6150 memcpy(header, &mpls, sizeof(mpls));
6151 header += sizeof(mpls);
6152 action_encap_data->conf.size = header -
6153 action_encap_data->data;
6154 action->conf = &action_encap_data->conf;
6158 /** Parse MPLSOGRE decap action. */
6160 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
6161 const char *str, unsigned int len,
6162 void *buf, unsigned int size)
6164 struct buffer *out = buf;
6165 struct rte_flow_action *action;
6166 struct action_raw_decap_data *action_decap_data;
6167 struct rte_flow_item_eth eth = { .type = 0, };
6168 struct rte_flow_item_vlan vlan = {.tci = 0};
6169 struct rte_flow_item_ipv4 ipv4 = {
6171 .next_proto_id = IPPROTO_GRE,
6174 struct rte_flow_item_ipv6 ipv6 = {
6176 .proto = IPPROTO_GRE,
6179 struct rte_flow_item_gre gre = {
6180 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6182 struct rte_flow_item_mpls mpls;
6186 ret = parse_vc(ctx, token, str, len, buf, size);
6189 /* Nothing else to do if there is no buffer. */
6192 if (!out->args.vc.actions_n)
6194 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6195 /* Point to selected object. */
6196 ctx->object = out->args.vc.data;
6197 ctx->objmask = NULL;
6198 /* Copy the headers to the buffer. */
6199 action_decap_data = ctx->object;
6200 *action_decap_data = (struct action_raw_decap_data) {
6201 .conf = (struct rte_flow_action_raw_decap){
6202 .data = action_decap_data->data,
6206 header = action_decap_data->data;
6207 if (mplsogre_decap_conf.select_vlan)
6208 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6209 else if (mplsogre_encap_conf.select_ipv4)
6210 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6212 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6213 memcpy(eth.dst.addr_bytes,
6214 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6215 memcpy(eth.src.addr_bytes,
6216 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6217 memcpy(header, ð, sizeof(eth));
6218 header += sizeof(eth);
6219 if (mplsogre_encap_conf.select_vlan) {
6220 if (mplsogre_encap_conf.select_ipv4)
6221 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6223 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6224 memcpy(header, &vlan, sizeof(vlan));
6225 header += sizeof(vlan);
6227 if (mplsogre_encap_conf.select_ipv4) {
6228 memcpy(header, &ipv4, sizeof(ipv4));
6229 header += sizeof(ipv4);
6231 memcpy(header, &ipv6, sizeof(ipv6));
6232 header += sizeof(ipv6);
6234 memcpy(header, &gre, sizeof(gre));
6235 header += sizeof(gre);
6236 memset(&mpls, 0, sizeof(mpls));
6237 memcpy(header, &mpls, sizeof(mpls));
6238 header += sizeof(mpls);
6239 action_decap_data->conf.size = header -
6240 action_decap_data->data;
6241 action->conf = &action_decap_data->conf;
6245 /** Parse MPLSOUDP encap action. */
6247 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
6248 const char *str, unsigned int len,
6249 void *buf, unsigned int size)
6251 struct buffer *out = buf;
6252 struct rte_flow_action *action;
6253 struct action_raw_encap_data *action_encap_data;
6254 struct rte_flow_item_eth eth = { .type = 0, };
6255 struct rte_flow_item_vlan vlan = {
6256 .tci = mplsoudp_encap_conf.vlan_tci,
6259 struct rte_flow_item_ipv4 ipv4 = {
6261 .src_addr = mplsoudp_encap_conf.ipv4_src,
6262 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
6263 .next_proto_id = IPPROTO_UDP,
6264 .version_ihl = RTE_IPV4_VHL_DEF,
6265 .time_to_live = IPDEFTTL,
6268 struct rte_flow_item_ipv6 ipv6 = {
6270 .proto = IPPROTO_UDP,
6271 .hop_limits = IPDEFTTL,
6274 struct rte_flow_item_udp udp = {
6276 .src_port = mplsoudp_encap_conf.udp_src,
6277 .dst_port = mplsoudp_encap_conf.udp_dst,
6280 struct rte_flow_item_mpls mpls;
6284 ret = parse_vc(ctx, token, str, len, buf, size);
6287 /* Nothing else to do if there is no buffer. */
6290 if (!out->args.vc.actions_n)
6292 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6293 /* Point to selected object. */
6294 ctx->object = out->args.vc.data;
6295 ctx->objmask = NULL;
6296 /* Copy the headers to the buffer. */
6297 action_encap_data = ctx->object;
6298 *action_encap_data = (struct action_raw_encap_data) {
6299 .conf = (struct rte_flow_action_raw_encap){
6300 .data = action_encap_data->data,
6305 header = action_encap_data->data;
6306 if (mplsoudp_encap_conf.select_vlan)
6307 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6308 else if (mplsoudp_encap_conf.select_ipv4)
6309 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6311 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6312 memcpy(eth.dst.addr_bytes,
6313 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6314 memcpy(eth.src.addr_bytes,
6315 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6316 memcpy(header, ð, sizeof(eth));
6317 header += sizeof(eth);
6318 if (mplsoudp_encap_conf.select_vlan) {
6319 if (mplsoudp_encap_conf.select_ipv4)
6320 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6322 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6323 memcpy(header, &vlan, sizeof(vlan));
6324 header += sizeof(vlan);
6326 if (mplsoudp_encap_conf.select_ipv4) {
6327 memcpy(header, &ipv4, sizeof(ipv4));
6328 header += sizeof(ipv4);
6330 memcpy(&ipv6.hdr.src_addr,
6331 &mplsoudp_encap_conf.ipv6_src,
6332 sizeof(mplsoudp_encap_conf.ipv6_src));
6333 memcpy(&ipv6.hdr.dst_addr,
6334 &mplsoudp_encap_conf.ipv6_dst,
6335 sizeof(mplsoudp_encap_conf.ipv6_dst));
6336 memcpy(header, &ipv6, sizeof(ipv6));
6337 header += sizeof(ipv6);
6339 memcpy(header, &udp, sizeof(udp));
6340 header += sizeof(udp);
6341 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
6342 RTE_DIM(mplsoudp_encap_conf.label));
6343 mpls.label_tc_s[2] |= 0x1;
6344 memcpy(header, &mpls, sizeof(mpls));
6345 header += sizeof(mpls);
6346 action_encap_data->conf.size = header -
6347 action_encap_data->data;
6348 action->conf = &action_encap_data->conf;
6352 /** Parse MPLSOUDP decap action. */
6354 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
6355 const char *str, unsigned int len,
6356 void *buf, unsigned int size)
6358 struct buffer *out = buf;
6359 struct rte_flow_action *action;
6360 struct action_raw_decap_data *action_decap_data;
6361 struct rte_flow_item_eth eth = { .type = 0, };
6362 struct rte_flow_item_vlan vlan = {.tci = 0};
6363 struct rte_flow_item_ipv4 ipv4 = {
6365 .next_proto_id = IPPROTO_UDP,
6368 struct rte_flow_item_ipv6 ipv6 = {
6370 .proto = IPPROTO_UDP,
6373 struct rte_flow_item_udp udp = {
6375 .dst_port = rte_cpu_to_be_16(6635),
6378 struct rte_flow_item_mpls mpls;
6382 ret = parse_vc(ctx, token, str, len, buf, size);
6385 /* Nothing else to do if there is no buffer. */
6388 if (!out->args.vc.actions_n)
6390 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6391 /* Point to selected object. */
6392 ctx->object = out->args.vc.data;
6393 ctx->objmask = NULL;
6394 /* Copy the headers to the buffer. */
6395 action_decap_data = ctx->object;
6396 *action_decap_data = (struct action_raw_decap_data) {
6397 .conf = (struct rte_flow_action_raw_decap){
6398 .data = action_decap_data->data,
6402 header = action_decap_data->data;
6403 if (mplsoudp_decap_conf.select_vlan)
6404 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6405 else if (mplsoudp_encap_conf.select_ipv4)
6406 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6408 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6409 memcpy(eth.dst.addr_bytes,
6410 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6411 memcpy(eth.src.addr_bytes,
6412 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6413 memcpy(header, ð, sizeof(eth));
6414 header += sizeof(eth);
6415 if (mplsoudp_encap_conf.select_vlan) {
6416 if (mplsoudp_encap_conf.select_ipv4)
6417 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6419 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6420 memcpy(header, &vlan, sizeof(vlan));
6421 header += sizeof(vlan);
6423 if (mplsoudp_encap_conf.select_ipv4) {
6424 memcpy(header, &ipv4, sizeof(ipv4));
6425 header += sizeof(ipv4);
6427 memcpy(header, &ipv6, sizeof(ipv6));
6428 header += sizeof(ipv6);
6430 memcpy(header, &udp, sizeof(udp));
6431 header += sizeof(udp);
6432 memset(&mpls, 0, sizeof(mpls));
6433 memcpy(header, &mpls, sizeof(mpls));
6434 header += sizeof(mpls);
6435 action_decap_data->conf.size = header -
6436 action_decap_data->data;
6437 action->conf = &action_decap_data->conf;
6442 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
6443 const char *str, unsigned int len, void *buf,
6446 struct action_raw_decap_data *action_raw_decap_data;
6447 struct rte_flow_action *action;
6448 const struct arg *arg;
6449 struct buffer *out = buf;
6453 RTE_SET_USED(token);
6456 arg = ARGS_ENTRY_ARB_BOUNDED
6457 (offsetof(struct action_raw_decap_data, idx),
6458 sizeof(((struct action_raw_decap_data *)0)->idx),
6459 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
6460 if (push_args(ctx, arg))
6462 ret = parse_int(ctx, token, str, len, NULL, 0);
6469 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6470 action_raw_decap_data = ctx->object;
6471 idx = action_raw_decap_data->idx;
6472 action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
6473 action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
6474 action->conf = &action_raw_decap_data->conf;
6480 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
6481 const char *str, unsigned int len, void *buf,
6484 struct action_raw_encap_data *action_raw_encap_data;
6485 struct rte_flow_action *action;
6486 const struct arg *arg;
6487 struct buffer *out = buf;
6491 RTE_SET_USED(token);
6494 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
6496 arg = ARGS_ENTRY_ARB_BOUNDED
6497 (offsetof(struct action_raw_encap_data, idx),
6498 sizeof(((struct action_raw_encap_data *)0)->idx),
6499 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
6500 if (push_args(ctx, arg))
6502 ret = parse_int(ctx, token, str, len, NULL, 0);
6509 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6510 action_raw_encap_data = ctx->object;
6511 idx = action_raw_encap_data->idx;
6512 action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
6513 action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
6514 action_raw_encap_data->conf.preserve = NULL;
6515 action->conf = &action_raw_encap_data->conf;
6520 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
6521 const char *str, unsigned int len, void *buf,
6524 struct buffer *out = buf;
6525 struct rte_flow_action *action;
6526 struct action_raw_encap_data *action_raw_encap_data = NULL;
6529 ret = parse_vc(ctx, token, str, len, buf, size);
6532 /* Nothing else to do if there is no buffer. */
6535 if (!out->args.vc.actions_n)
6537 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6538 /* Point to selected object. */
6539 ctx->object = out->args.vc.data;
6540 ctx->objmask = NULL;
6541 /* Copy the headers to the buffer. */
6542 action_raw_encap_data = ctx->object;
6543 action_raw_encap_data->conf.data = raw_encap_confs[0].data;
6544 action_raw_encap_data->conf.preserve = NULL;
6545 action_raw_encap_data->conf.size = raw_encap_confs[0].size;
6546 action->conf = &action_raw_encap_data->conf;
6551 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
6552 const char *str, unsigned int len, void *buf,
6555 struct buffer *out = buf;
6556 struct rte_flow_action *action;
6557 struct action_raw_decap_data *action_raw_decap_data = NULL;
6560 ret = parse_vc(ctx, token, str, len, buf, size);
6563 /* Nothing else to do if there is no buffer. */
6566 if (!out->args.vc.actions_n)
6568 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6569 /* Point to selected object. */
6570 ctx->object = out->args.vc.data;
6571 ctx->objmask = NULL;
6572 /* Copy the headers to the buffer. */
6573 action_raw_decap_data = ctx->object;
6574 action_raw_decap_data->conf.data = raw_decap_confs[0].data;
6575 action_raw_decap_data->conf.size = raw_decap_confs[0].size;
6576 action->conf = &action_raw_decap_data->conf;
6581 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
6582 const char *str, unsigned int len, void *buf,
6587 ret = parse_vc(ctx, token, str, len, buf, size);
6590 ret = rte_flow_dynf_metadata_register();
6597 parse_vc_action_sample(struct context *ctx, const struct token *token,
6598 const char *str, unsigned int len, void *buf,
6601 struct buffer *out = buf;
6602 struct rte_flow_action *action;
6603 struct action_sample_data *action_sample_data = NULL;
6604 static struct rte_flow_action end_action = {
6605 RTE_FLOW_ACTION_TYPE_END, 0
6609 ret = parse_vc(ctx, token, str, len, buf, size);
6612 /* Nothing else to do if there is no buffer. */
6615 if (!out->args.vc.actions_n)
6617 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6618 /* Point to selected object. */
6619 ctx->object = out->args.vc.data;
6620 ctx->objmask = NULL;
6621 /* Copy the headers to the buffer. */
6622 action_sample_data = ctx->object;
6623 action_sample_data->conf.actions = &end_action;
6624 action->conf = &action_sample_data->conf;
6629 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
6630 const char *str, unsigned int len, void *buf,
6633 struct action_sample_data *action_sample_data;
6634 struct rte_flow_action *action;
6635 const struct arg *arg;
6636 struct buffer *out = buf;
6640 RTE_SET_USED(token);
6643 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
6645 arg = ARGS_ENTRY_ARB_BOUNDED
6646 (offsetof(struct action_sample_data, idx),
6647 sizeof(((struct action_sample_data *)0)->idx),
6648 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
6649 if (push_args(ctx, arg))
6651 ret = parse_int(ctx, token, str, len, NULL, 0);
6658 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6659 action_sample_data = ctx->object;
6660 idx = action_sample_data->idx;
6661 action_sample_data->conf.actions = raw_sample_confs[idx].data;
6662 action->conf = &action_sample_data->conf;
6666 /** Parse operation for modify_field command. */
6668 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
6669 const char *str, unsigned int len, void *buf,
6672 struct rte_flow_action_modify_field *action_modify_field;
6678 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
6680 for (i = 0; modify_field_ops[i]; ++i)
6681 if (!strcmp_partial(modify_field_ops[i], str, len))
6683 if (!modify_field_ops[i])
6687 action_modify_field = ctx->object;
6688 action_modify_field->operation = (enum rte_flow_modify_op)i;
6692 /** Parse id for modify_field command. */
6694 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
6695 const char *str, unsigned int len, void *buf,
6698 struct rte_flow_action_modify_field *action_modify_field;
6704 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
6705 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
6707 for (i = 0; modify_field_ids[i]; ++i)
6708 if (!strcmp_partial(modify_field_ids[i], str, len))
6710 if (!modify_field_ids[i])
6714 action_modify_field = ctx->object;
6715 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
6716 action_modify_field->dst.field = (enum rte_flow_field_id)i;
6718 action_modify_field->src.field = (enum rte_flow_field_id)i;
6722 /** Parse the conntrack update, not a rte_flow_action. */
6724 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
6725 const char *str, unsigned int len, void *buf,
6728 struct buffer *out = buf;
6729 struct rte_flow_modify_conntrack *ct_modify = NULL;
6732 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
6733 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
6735 /* Token name must match. */
6736 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6738 /* Nothing else to do if there is no buffer. */
6741 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
6742 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
6743 ct_modify->new_ct.is_original_dir =
6744 conntrack_context.is_original_dir;
6745 ct_modify->direction = 1;
6749 old_dir = ct_modify->new_ct.is_original_dir;
6750 memcpy(&ct_modify->new_ct, &conntrack_context,
6751 sizeof(conntrack_context));
6752 ct_modify->new_ct.is_original_dir = old_dir;
6753 ct_modify->state = 1;
6758 /** Parse tokens for destroy command. */
6760 parse_destroy(struct context *ctx, const struct token *token,
6761 const char *str, unsigned int len,
6762 void *buf, unsigned int size)
6764 struct buffer *out = buf;
6766 /* Token name must match. */
6767 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6769 /* Nothing else to do if there is no buffer. */
6772 if (!out->command) {
6773 if (ctx->curr != DESTROY)
6775 if (sizeof(*out) > size)
6777 out->command = ctx->curr;
6780 ctx->objmask = NULL;
6781 out->args.destroy.rule =
6782 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6786 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
6787 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
6790 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
6791 ctx->objmask = NULL;
6795 /** Parse tokens for flush command. */
6797 parse_flush(struct context *ctx, const struct token *token,
6798 const char *str, unsigned int len,
6799 void *buf, unsigned int size)
6801 struct buffer *out = buf;
6803 /* Token name must match. */
6804 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6806 /* Nothing else to do if there is no buffer. */
6809 if (!out->command) {
6810 if (ctx->curr != FLUSH)
6812 if (sizeof(*out) > size)
6814 out->command = ctx->curr;
6817 ctx->objmask = NULL;
6822 /** Parse tokens for dump command. */
6824 parse_dump(struct context *ctx, const struct token *token,
6825 const char *str, unsigned int len,
6826 void *buf, unsigned int size)
6828 struct buffer *out = buf;
6830 /* Token name must match. */
6831 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6833 /* Nothing else to do if there is no buffer. */
6836 if (!out->command) {
6837 if (ctx->curr != DUMP)
6839 if (sizeof(*out) > size)
6841 out->command = ctx->curr;
6844 ctx->objmask = NULL;
6847 switch (ctx->curr) {
6850 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
6851 out->command = ctx->curr;
6854 ctx->objmask = NULL;
6861 /** Parse tokens for query command. */
6863 parse_query(struct context *ctx, const struct token *token,
6864 const char *str, unsigned int len,
6865 void *buf, unsigned int size)
6867 struct buffer *out = buf;
6869 /* Token name must match. */
6870 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6872 /* Nothing else to do if there is no buffer. */
6875 if (!out->command) {
6876 if (ctx->curr != QUERY)
6878 if (sizeof(*out) > size)
6880 out->command = ctx->curr;
6883 ctx->objmask = NULL;
6888 /** Parse action names. */
6890 parse_action(struct context *ctx, const struct token *token,
6891 const char *str, unsigned int len,
6892 void *buf, unsigned int size)
6894 struct buffer *out = buf;
6895 const struct arg *arg = pop_args(ctx);
6899 /* Argument is expected. */
6902 /* Parse action name. */
6903 for (i = 0; next_action[i]; ++i) {
6904 const struct parse_action_priv *priv;
6906 token = &token_list[next_action[i]];
6907 if (strcmp_partial(token->name, str, len))
6913 memcpy((uint8_t *)ctx->object + arg->offset,
6919 push_args(ctx, arg);
6923 /** Parse tokens for list command. */
6925 parse_list(struct context *ctx, const struct token *token,
6926 const char *str, unsigned int len,
6927 void *buf, unsigned int size)
6929 struct buffer *out = buf;
6931 /* Token name must match. */
6932 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6934 /* Nothing else to do if there is no buffer. */
6937 if (!out->command) {
6938 if (ctx->curr != LIST)
6940 if (sizeof(*out) > size)
6942 out->command = ctx->curr;
6945 ctx->objmask = NULL;
6946 out->args.list.group =
6947 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6951 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
6952 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
6955 ctx->object = out->args.list.group + out->args.list.group_n++;
6956 ctx->objmask = NULL;
6960 /** Parse tokens for list all aged flows command. */
6962 parse_aged(struct context *ctx, const struct token *token,
6963 const char *str, unsigned int len,
6964 void *buf, unsigned int size)
6966 struct buffer *out = buf;
6968 /* Token name must match. */
6969 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6971 /* Nothing else to do if there is no buffer. */
6974 if (!out->command) {
6975 if (ctx->curr != AGED)
6977 if (sizeof(*out) > size)
6979 out->command = ctx->curr;
6982 ctx->objmask = NULL;
6984 if (ctx->curr == AGED_DESTROY)
6985 out->args.aged.destroy = 1;
6989 /** Parse tokens for isolate command. */
6991 parse_isolate(struct context *ctx, const struct token *token,
6992 const char *str, unsigned int len,
6993 void *buf, unsigned int size)
6995 struct buffer *out = buf;
6997 /* Token name must match. */
6998 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7000 /* Nothing else to do if there is no buffer. */
7003 if (!out->command) {
7004 if (ctx->curr != ISOLATE)
7006 if (sizeof(*out) > size)
7008 out->command = ctx->curr;
7011 ctx->objmask = NULL;
7017 parse_tunnel(struct context *ctx, const struct token *token,
7018 const char *str, unsigned int len,
7019 void *buf, unsigned int size)
7021 struct buffer *out = buf;
7023 /* Token name must match. */
7024 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7026 /* Nothing else to do if there is no buffer. */
7029 if (!out->command) {
7030 if (ctx->curr != TUNNEL)
7032 if (sizeof(*out) > size)
7034 out->command = ctx->curr;
7037 ctx->objmask = NULL;
7039 switch (ctx->curr) {
7043 case TUNNEL_DESTROY:
7045 out->command = ctx->curr;
7047 case TUNNEL_CREATE_TYPE:
7048 case TUNNEL_DESTROY_ID:
7049 ctx->object = &out->args.vc.tunnel_ops;
7058 * Parse signed/unsigned integers 8 to 64-bit long.
7060 * Last argument (ctx->args) is retrieved to determine integer type and
7064 parse_int(struct context *ctx, const struct token *token,
7065 const char *str, unsigned int len,
7066 void *buf, unsigned int size)
7068 const struct arg *arg = pop_args(ctx);
7073 /* Argument is expected. */
7078 (uintmax_t)strtoimax(str, &end, 0) :
7079 strtoumax(str, &end, 0);
7080 if (errno || (size_t)(end - str) != len)
7083 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
7084 (intmax_t)u > (intmax_t)arg->max)) ||
7085 (!arg->sign && (u < arg->min || u > arg->max))))
7090 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
7091 !arg_entry_bf_fill(ctx->objmask, -1, arg))
7095 buf = (uint8_t *)ctx->object + arg->offset;
7097 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
7101 case sizeof(uint8_t):
7102 *(uint8_t *)buf = u;
7104 case sizeof(uint16_t):
7105 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
7107 case sizeof(uint8_t [3]):
7108 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7110 ((uint8_t *)buf)[0] = u;
7111 ((uint8_t *)buf)[1] = u >> 8;
7112 ((uint8_t *)buf)[2] = u >> 16;
7116 ((uint8_t *)buf)[0] = u >> 16;
7117 ((uint8_t *)buf)[1] = u >> 8;
7118 ((uint8_t *)buf)[2] = u;
7120 case sizeof(uint32_t):
7121 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
7123 case sizeof(uint64_t):
7124 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
7129 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
7131 buf = (uint8_t *)ctx->objmask + arg->offset;
7136 push_args(ctx, arg);
7143 * Three arguments (ctx->args) are retrieved from the stack to store data,
7144 * its actual length and address (in that order).
7147 parse_string(struct context *ctx, const struct token *token,
7148 const char *str, unsigned int len,
7149 void *buf, unsigned int size)
7151 const struct arg *arg_data = pop_args(ctx);
7152 const struct arg *arg_len = pop_args(ctx);
7153 const struct arg *arg_addr = pop_args(ctx);
7154 char tmp[16]; /* Ought to be enough. */
7157 /* Arguments are expected. */
7161 push_args(ctx, arg_data);
7165 push_args(ctx, arg_len);
7166 push_args(ctx, arg_data);
7169 size = arg_data->size;
7170 /* Bit-mask fill is not supported. */
7171 if (arg_data->mask || size < len)
7175 /* Let parse_int() fill length information first. */
7176 ret = snprintf(tmp, sizeof(tmp), "%u", len);
7179 push_args(ctx, arg_len);
7180 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7185 buf = (uint8_t *)ctx->object + arg_data->offset;
7186 /* Output buffer is not necessarily NUL-terminated. */
7187 memcpy(buf, str, len);
7188 memset((uint8_t *)buf + len, 0x00, size - len);
7190 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7191 /* Save address if requested. */
7192 if (arg_addr->size) {
7193 memcpy((uint8_t *)ctx->object + arg_addr->offset,
7195 (uint8_t *)ctx->object + arg_data->offset
7199 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7201 (uint8_t *)ctx->objmask + arg_data->offset
7207 push_args(ctx, arg_addr);
7208 push_args(ctx, arg_len);
7209 push_args(ctx, arg_data);
7214 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
7220 /* Check input parameters */
7221 if ((src == NULL) ||
7227 /* Convert chars to bytes */
7228 for (i = 0, len = 0; i < *size; i += 2) {
7229 snprintf(tmp, 3, "%s", src + i);
7230 dst[len++] = strtoul(tmp, &c, 16);
7245 parse_hex(struct context *ctx, const struct token *token,
7246 const char *str, unsigned int len,
7247 void *buf, unsigned int size)
7249 const struct arg *arg_data = pop_args(ctx);
7250 const struct arg *arg_len = pop_args(ctx);
7251 const struct arg *arg_addr = pop_args(ctx);
7252 char tmp[16]; /* Ought to be enough. */
7254 unsigned int hexlen = len;
7255 unsigned int length = 256;
7256 uint8_t hex_tmp[length];
7258 /* Arguments are expected. */
7262 push_args(ctx, arg_data);
7266 push_args(ctx, arg_len);
7267 push_args(ctx, arg_data);
7270 size = arg_data->size;
7271 /* Bit-mask fill is not supported. */
7277 /* translate bytes string to array. */
7278 if (str[0] == '0' && ((str[1] == 'x') ||
7283 if (hexlen > length)
7285 ret = parse_hex_string(str, hex_tmp, &hexlen);
7288 /* Let parse_int() fill length information first. */
7289 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
7292 /* Save length if requested. */
7293 if (arg_len->size) {
7294 push_args(ctx, arg_len);
7295 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7301 buf = (uint8_t *)ctx->object + arg_data->offset;
7302 /* Output buffer is not necessarily NUL-terminated. */
7303 memcpy(buf, hex_tmp, hexlen);
7304 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
7306 memset((uint8_t *)ctx->objmask + arg_data->offset,
7308 /* Save address if requested. */
7309 if (arg_addr->size) {
7310 memcpy((uint8_t *)ctx->object + arg_addr->offset,
7312 (uint8_t *)ctx->object + arg_data->offset
7316 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7318 (uint8_t *)ctx->objmask + arg_data->offset
7324 push_args(ctx, arg_addr);
7325 push_args(ctx, arg_len);
7326 push_args(ctx, arg_data);
7332 * Parse a zero-ended string.
7335 parse_string0(struct context *ctx, const struct token *token __rte_unused,
7336 const char *str, unsigned int len,
7337 void *buf, unsigned int size)
7339 const struct arg *arg_data = pop_args(ctx);
7341 /* Arguments are expected. */
7344 size = arg_data->size;
7345 /* Bit-mask fill is not supported. */
7346 if (arg_data->mask || size < len + 1)
7350 buf = (uint8_t *)ctx->object + arg_data->offset;
7351 strncpy(buf, str, len);
7353 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7356 push_args(ctx, arg_data);
7361 * Parse a MAC address.
7363 * Last argument (ctx->args) is retrieved to determine storage size and
7367 parse_mac_addr(struct context *ctx, const struct token *token,
7368 const char *str, unsigned int len,
7369 void *buf, unsigned int size)
7371 const struct arg *arg = pop_args(ctx);
7372 struct rte_ether_addr tmp;
7376 /* Argument is expected. */
7380 /* Bit-mask fill is not supported. */
7381 if (arg->mask || size != sizeof(tmp))
7383 /* Only network endian is supported. */
7386 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
7387 if (ret < 0 || (unsigned int)ret != len)
7391 buf = (uint8_t *)ctx->object + arg->offset;
7392 memcpy(buf, &tmp, size);
7394 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7397 push_args(ctx, arg);
7402 * Parse an IPv4 address.
7404 * Last argument (ctx->args) is retrieved to determine storage size and
7408 parse_ipv4_addr(struct context *ctx, const struct token *token,
7409 const char *str, unsigned int len,
7410 void *buf, unsigned int size)
7412 const struct arg *arg = pop_args(ctx);
7417 /* Argument is expected. */
7421 /* Bit-mask fill is not supported. */
7422 if (arg->mask || size != sizeof(tmp))
7424 /* Only network endian is supported. */
7427 memcpy(str2, str, len);
7429 ret = inet_pton(AF_INET, str2, &tmp);
7431 /* Attempt integer parsing. */
7432 push_args(ctx, arg);
7433 return parse_int(ctx, token, str, len, buf, size);
7437 buf = (uint8_t *)ctx->object + arg->offset;
7438 memcpy(buf, &tmp, size);
7440 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7443 push_args(ctx, arg);
7448 * Parse an IPv6 address.
7450 * Last argument (ctx->args) is retrieved to determine storage size and
7454 parse_ipv6_addr(struct context *ctx, const struct token *token,
7455 const char *str, unsigned int len,
7456 void *buf, unsigned int size)
7458 const struct arg *arg = pop_args(ctx);
7460 struct in6_addr tmp;
7464 /* Argument is expected. */
7468 /* Bit-mask fill is not supported. */
7469 if (arg->mask || size != sizeof(tmp))
7471 /* Only network endian is supported. */
7474 memcpy(str2, str, len);
7476 ret = inet_pton(AF_INET6, str2, &tmp);
7481 buf = (uint8_t *)ctx->object + arg->offset;
7482 memcpy(buf, &tmp, size);
7484 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7487 push_args(ctx, arg);
7491 /** Boolean values (even indices stand for false). */
7492 static const char *const boolean_name[] = {
7502 * Parse a boolean value.
7504 * Last argument (ctx->args) is retrieved to determine storage size and
7508 parse_boolean(struct context *ctx, const struct token *token,
7509 const char *str, unsigned int len,
7510 void *buf, unsigned int size)
7512 const struct arg *arg = pop_args(ctx);
7516 /* Argument is expected. */
7519 for (i = 0; boolean_name[i]; ++i)
7520 if (!strcmp_partial(boolean_name[i], str, len))
7522 /* Process token as integer. */
7523 if (boolean_name[i])
7524 str = i & 1 ? "1" : "0";
7525 push_args(ctx, arg);
7526 ret = parse_int(ctx, token, str, strlen(str), buf, size);
7527 return ret > 0 ? (int)len : ret;
7530 /** Parse port and update context. */
7532 parse_port(struct context *ctx, const struct token *token,
7533 const char *str, unsigned int len,
7534 void *buf, unsigned int size)
7536 struct buffer *out = &(struct buffer){ .port = 0 };
7544 ctx->objmask = NULL;
7545 size = sizeof(*out);
7547 ret = parse_int(ctx, token, str, len, out, size);
7549 ctx->port = out->port;
7556 parse_ia_id2ptr(struct context *ctx, const struct token *token,
7557 const char *str, unsigned int len,
7558 void *buf, unsigned int size)
7560 struct rte_flow_action *action = ctx->object;
7568 ctx->objmask = NULL;
7569 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
7570 ctx->object = action;
7571 if (ret != (int)len)
7573 /* set indirect action */
7575 action->conf = port_action_handle_get_by_id(ctx->port, id);
7576 ret = (action->conf) ? ret : -1;
7581 /** Parse set command, initialize output buffer for subsequent tokens. */
7583 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
7584 const char *str, unsigned int len,
7585 void *buf, unsigned int size)
7587 struct buffer *out = buf;
7589 /* Token name must match. */
7590 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7592 /* Nothing else to do if there is no buffer. */
7595 /* Make sure buffer is large enough. */
7596 if (size < sizeof(*out))
7599 ctx->objmask = NULL;
7603 out->command = ctx->curr;
7604 /* For encap/decap we need is pattern */
7605 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7610 /** Parse set command, initialize output buffer for subsequent tokens. */
7612 parse_set_sample_action(struct context *ctx, const struct token *token,
7613 const char *str, unsigned int len,
7614 void *buf, unsigned int size)
7616 struct buffer *out = buf;
7618 /* Token name must match. */
7619 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7621 /* Nothing else to do if there is no buffer. */
7624 /* Make sure buffer is large enough. */
7625 if (size < sizeof(*out))
7628 ctx->objmask = NULL;
7632 out->command = ctx->curr;
7633 /* For sampler we need is actions */
7634 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7640 * Parse set raw_encap/raw_decap command,
7641 * initialize output buffer for subsequent tokens.
7644 parse_set_init(struct context *ctx, const struct token *token,
7645 const char *str, unsigned int len,
7646 void *buf, unsigned int size)
7648 struct buffer *out = buf;
7650 /* Token name must match. */
7651 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7653 /* Nothing else to do if there is no buffer. */
7656 /* Make sure buffer is large enough. */
7657 if (size < sizeof(*out))
7659 /* Initialize buffer. */
7660 memset(out, 0x00, sizeof(*out));
7661 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
7664 ctx->objmask = NULL;
7665 if (!out->command) {
7666 if (ctx->curr != SET)
7668 if (sizeof(*out) > size)
7670 out->command = ctx->curr;
7671 out->args.vc.data = (uint8_t *)out + size;
7672 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7678 /** No completion. */
7680 comp_none(struct context *ctx, const struct token *token,
7681 unsigned int ent, char *buf, unsigned int size)
7691 /** Complete boolean values. */
7693 comp_boolean(struct context *ctx, const struct token *token,
7694 unsigned int ent, char *buf, unsigned int size)
7700 for (i = 0; boolean_name[i]; ++i)
7701 if (buf && i == ent)
7702 return strlcpy(buf, boolean_name[i], size);
7708 /** Complete action names. */
7710 comp_action(struct context *ctx, const struct token *token,
7711 unsigned int ent, char *buf, unsigned int size)
7717 for (i = 0; next_action[i]; ++i)
7718 if (buf && i == ent)
7719 return strlcpy(buf, token_list[next_action[i]].name,
7726 /** Complete available ports. */
7728 comp_port(struct context *ctx, const struct token *token,
7729 unsigned int ent, char *buf, unsigned int size)
7736 RTE_ETH_FOREACH_DEV(p) {
7737 if (buf && i == ent)
7738 return snprintf(buf, size, "%u", p);
7746 /** Complete available rule IDs. */
7748 comp_rule_id(struct context *ctx, const struct token *token,
7749 unsigned int ent, char *buf, unsigned int size)
7752 struct rte_port *port;
7753 struct port_flow *pf;
7756 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
7757 ctx->port == (portid_t)RTE_PORT_ALL)
7759 port = &ports[ctx->port];
7760 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
7761 if (buf && i == ent)
7762 return snprintf(buf, size, "%u", pf->id);
7770 /** Complete type field for RSS action. */
7772 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
7773 unsigned int ent, char *buf, unsigned int size)
7779 for (i = 0; rss_type_table[i].str; ++i)
7784 return strlcpy(buf, rss_type_table[ent].str, size);
7786 return snprintf(buf, size, "end");
7790 /** Complete queue field for RSS action. */
7792 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
7793 unsigned int ent, char *buf, unsigned int size)
7800 return snprintf(buf, size, "%u", ent);
7802 return snprintf(buf, size, "end");
7806 /** Complete index number for set raw_encap/raw_decap commands. */
7808 comp_set_raw_index(struct context *ctx, const struct token *token,
7809 unsigned int ent, char *buf, unsigned int size)
7815 RTE_SET_USED(token);
7816 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
7817 if (buf && idx == ent)
7818 return snprintf(buf, size, "%u", idx);
7824 /** Complete index number for set raw_encap/raw_decap commands. */
7826 comp_set_sample_index(struct context *ctx, const struct token *token,
7827 unsigned int ent, char *buf, unsigned int size)
7833 RTE_SET_USED(token);
7834 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
7835 if (buf && idx == ent)
7836 return snprintf(buf, size, "%u", idx);
7842 /** Complete operation for modify_field command. */
7844 comp_set_modify_field_op(struct context *ctx, const struct token *token,
7845 unsigned int ent, char *buf, unsigned int size)
7850 RTE_SET_USED(token);
7851 for (idx = 0; modify_field_ops[idx]; ++idx)
7856 return strlcpy(buf, modify_field_ops[ent], size);
7860 /** Complete field id for modify_field command. */
7862 comp_set_modify_field_id(struct context *ctx, const struct token *token,
7863 unsigned int ent, char *buf, unsigned int size)
7868 RTE_SET_USED(token);
7869 for (idx = 0; modify_field_ids[idx]; ++idx)
7874 return strlcpy(buf, modify_field_ids[ent], size);
7878 /** Internal context. */
7879 static struct context cmd_flow_context;
7881 /** Global parser instance (cmdline API). */
7882 cmdline_parse_inst_t cmd_flow;
7883 cmdline_parse_inst_t cmd_set_raw;
7885 /** Initialize context. */
7887 cmd_flow_context_init(struct context *ctx)
7889 /* A full memset() is not necessary. */
7899 ctx->objmask = NULL;
7902 /** Parse a token (cmdline API). */
7904 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
7907 struct context *ctx = &cmd_flow_context;
7908 const struct token *token;
7909 const enum index *list;
7914 token = &token_list[ctx->curr];
7915 /* Check argument length. */
7918 for (len = 0; src[len]; ++len)
7919 if (src[len] == '#' || isspace(src[len]))
7923 /* Last argument and EOL detection. */
7924 for (i = len; src[i]; ++i)
7925 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
7927 else if (!isspace(src[i])) {
7932 if (src[i] == '\r' || src[i] == '\n') {
7936 /* Initialize context if necessary. */
7937 if (!ctx->next_num) {
7940 ctx->next[ctx->next_num++] = token->next[0];
7942 /* Process argument through candidates. */
7943 ctx->prev = ctx->curr;
7944 list = ctx->next[ctx->next_num - 1];
7945 for (i = 0; list[i]; ++i) {
7946 const struct token *next = &token_list[list[i]];
7949 ctx->curr = list[i];
7951 tmp = next->call(ctx, next, src, len, result, size);
7953 tmp = parse_default(ctx, next, src, len, result, size);
7954 if (tmp == -1 || tmp != len)
7962 /* Push subsequent tokens if any. */
7964 for (i = 0; token->next[i]; ++i) {
7965 if (ctx->next_num == RTE_DIM(ctx->next))
7967 ctx->next[ctx->next_num++] = token->next[i];
7969 /* Push arguments if any. */
7971 for (i = 0; token->args[i]; ++i) {
7972 if (ctx->args_num == RTE_DIM(ctx->args))
7974 ctx->args[ctx->args_num++] = token->args[i];
7979 /** Return number of completion entries (cmdline API). */
7981 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
7983 struct context *ctx = &cmd_flow_context;
7984 const struct token *token = &token_list[ctx->curr];
7985 const enum index *list;
7989 /* Count number of tokens in current list. */
7991 list = ctx->next[ctx->next_num - 1];
7993 list = token->next[0];
7994 for (i = 0; list[i]; ++i)
7999 * If there is a single token, use its completion callback, otherwise
8000 * return the number of entries.
8002 token = &token_list[list[0]];
8003 if (i == 1 && token->comp) {
8004 /* Save index for cmd_flow_get_help(). */
8005 ctx->prev = list[0];
8006 return token->comp(ctx, token, 0, NULL, 0);
8011 /** Return a completion entry (cmdline API). */
8013 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
8014 char *dst, unsigned int size)
8016 struct context *ctx = &cmd_flow_context;
8017 const struct token *token = &token_list[ctx->curr];
8018 const enum index *list;
8022 /* Count number of tokens in current list. */
8024 list = ctx->next[ctx->next_num - 1];
8026 list = token->next[0];
8027 for (i = 0; list[i]; ++i)
8031 /* If there is a single token, use its completion callback. */
8032 token = &token_list[list[0]];
8033 if (i == 1 && token->comp) {
8034 /* Save index for cmd_flow_get_help(). */
8035 ctx->prev = list[0];
8036 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
8038 /* Otherwise make sure the index is valid and use defaults. */
8041 token = &token_list[list[index]];
8042 strlcpy(dst, token->name, size);
8043 /* Save index for cmd_flow_get_help(). */
8044 ctx->prev = list[index];
8048 /** Populate help strings for current token (cmdline API). */
8050 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
8052 struct context *ctx = &cmd_flow_context;
8053 const struct token *token = &token_list[ctx->prev];
8058 /* Set token type and update global help with details. */
8059 strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
8061 cmd_flow.help_str = token->help;
8063 cmd_flow.help_str = token->name;
8067 /** Token definition template (cmdline API). */
8068 static struct cmdline_token_hdr cmd_flow_token_hdr = {
8069 .ops = &(struct cmdline_token_ops){
8070 .parse = cmd_flow_parse,
8071 .complete_get_nb = cmd_flow_complete_get_nb,
8072 .complete_get_elt = cmd_flow_complete_get_elt,
8073 .get_help = cmd_flow_get_help,
8078 /** Populate the next dynamic token. */
8080 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
8081 cmdline_parse_token_hdr_t **hdr_inst)
8083 struct context *ctx = &cmd_flow_context;
8085 /* Always reinitialize context before requesting the first token. */
8086 if (!(hdr_inst - cmd_flow.tokens))
8087 cmd_flow_context_init(ctx);
8088 /* Return NULL when no more tokens are expected. */
8089 if (!ctx->next_num && ctx->curr) {
8093 /* Determine if command should end here. */
8094 if (ctx->eol && ctx->last && ctx->next_num) {
8095 const enum index *list = ctx->next[ctx->next_num - 1];
8098 for (i = 0; list[i]; ++i) {
8105 *hdr = &cmd_flow_token_hdr;
8108 /** Dispatch parsed buffer to function calls. */
8110 cmd_flow_parsed(const struct buffer *in)
8112 switch (in->command) {
8113 case INDIRECT_ACTION_CREATE:
8114 port_action_handle_create(
8115 in->port, in->args.vc.attr.group,
8116 &((const struct rte_flow_indir_action_conf) {
8117 .ingress = in->args.vc.attr.ingress,
8118 .egress = in->args.vc.attr.egress,
8119 .transfer = in->args.vc.attr.transfer,
8121 in->args.vc.actions);
8123 case INDIRECT_ACTION_DESTROY:
8124 port_action_handle_destroy(in->port,
8125 in->args.ia_destroy.action_id_n,
8126 in->args.ia_destroy.action_id);
8128 case INDIRECT_ACTION_UPDATE:
8129 port_action_handle_update(in->port, in->args.vc.attr.group,
8130 in->args.vc.actions);
8132 case INDIRECT_ACTION_QUERY:
8133 port_action_handle_query(in->port, in->args.ia.action_id);
8136 port_flow_validate(in->port, &in->args.vc.attr,
8137 in->args.vc.pattern, in->args.vc.actions,
8138 &in->args.vc.tunnel_ops);
8141 port_flow_create(in->port, &in->args.vc.attr,
8142 in->args.vc.pattern, in->args.vc.actions,
8143 &in->args.vc.tunnel_ops);
8146 port_flow_destroy(in->port, in->args.destroy.rule_n,
8147 in->args.destroy.rule);
8150 port_flow_flush(in->port);
8154 port_flow_dump(in->port, in->args.dump.mode,
8155 in->args.dump.rule, in->args.dump.file);
8158 port_flow_query(in->port, in->args.query.rule,
8159 &in->args.query.action);
8162 port_flow_list(in->port, in->args.list.group_n,
8163 in->args.list.group);
8166 port_flow_isolate(in->port, in->args.isolate.set);
8169 port_flow_aged(in->port, in->args.aged.destroy);
8172 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
8174 case TUNNEL_DESTROY:
8175 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
8178 port_flow_tunnel_list(in->port);
8181 port_meter_policy_add(in->port, in->args.policy.policy_id,
8182 in->args.vc.actions);
8189 /** Token generator and output processing callback (cmdline API). */
8191 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
8194 cmd_flow_tok(arg0, arg2);
8196 cmd_flow_parsed(arg0);
8199 /** Global parser instance (cmdline API). */
8200 cmdline_parse_inst_t cmd_flow = {
8202 .data = NULL, /**< Unused. */
8203 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
8206 }, /**< Tokens are returned by cmd_flow_tok(). */
8209 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
8212 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
8214 struct rte_ipv4_hdr *ipv4;
8215 struct rte_ether_hdr *eth;
8216 struct rte_ipv6_hdr *ipv6;
8217 struct rte_vxlan_hdr *vxlan;
8218 struct rte_vxlan_gpe_hdr *gpe;
8219 struct rte_flow_item_nvgre *nvgre;
8220 uint32_t ipv6_vtc_flow;
8222 switch (item->type) {
8223 case RTE_FLOW_ITEM_TYPE_ETH:
8224 eth = (struct rte_ether_hdr *)buf;
8226 eth->ether_type = rte_cpu_to_be_16(next_proto);
8228 case RTE_FLOW_ITEM_TYPE_IPV4:
8229 ipv4 = (struct rte_ipv4_hdr *)buf;
8230 if (!ipv4->version_ihl)
8231 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
8232 if (next_proto && ipv4->next_proto_id == 0)
8233 ipv4->next_proto_id = (uint8_t)next_proto;
8235 case RTE_FLOW_ITEM_TYPE_IPV6:
8236 ipv6 = (struct rte_ipv6_hdr *)buf;
8237 if (next_proto && ipv6->proto == 0)
8238 ipv6->proto = (uint8_t)next_proto;
8239 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
8240 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
8241 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
8242 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
8244 case RTE_FLOW_ITEM_TYPE_VXLAN:
8245 vxlan = (struct rte_vxlan_hdr *)buf;
8246 vxlan->vx_flags = 0x08;
8248 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8249 gpe = (struct rte_vxlan_gpe_hdr *)buf;
8250 gpe->vx_flags = 0x0C;
8252 case RTE_FLOW_ITEM_TYPE_NVGRE:
8253 nvgre = (struct rte_flow_item_nvgre *)buf;
8254 nvgre->protocol = rte_cpu_to_be_16(0x6558);
8255 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
8262 /** Helper of get item's default mask. */
8264 flow_item_default_mask(const struct rte_flow_item *item)
8266 const void *mask = NULL;
8267 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
8269 switch (item->type) {
8270 case RTE_FLOW_ITEM_TYPE_ANY:
8271 mask = &rte_flow_item_any_mask;
8273 case RTE_FLOW_ITEM_TYPE_VF:
8274 mask = &rte_flow_item_vf_mask;
8276 case RTE_FLOW_ITEM_TYPE_PORT_ID:
8277 mask = &rte_flow_item_port_id_mask;
8279 case RTE_FLOW_ITEM_TYPE_RAW:
8280 mask = &rte_flow_item_raw_mask;
8282 case RTE_FLOW_ITEM_TYPE_ETH:
8283 mask = &rte_flow_item_eth_mask;
8285 case RTE_FLOW_ITEM_TYPE_VLAN:
8286 mask = &rte_flow_item_vlan_mask;
8288 case RTE_FLOW_ITEM_TYPE_IPV4:
8289 mask = &rte_flow_item_ipv4_mask;
8291 case RTE_FLOW_ITEM_TYPE_IPV6:
8292 mask = &rte_flow_item_ipv6_mask;
8294 case RTE_FLOW_ITEM_TYPE_ICMP:
8295 mask = &rte_flow_item_icmp_mask;
8297 case RTE_FLOW_ITEM_TYPE_UDP:
8298 mask = &rte_flow_item_udp_mask;
8300 case RTE_FLOW_ITEM_TYPE_TCP:
8301 mask = &rte_flow_item_tcp_mask;
8303 case RTE_FLOW_ITEM_TYPE_SCTP:
8304 mask = &rte_flow_item_sctp_mask;
8306 case RTE_FLOW_ITEM_TYPE_VXLAN:
8307 mask = &rte_flow_item_vxlan_mask;
8309 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8310 mask = &rte_flow_item_vxlan_gpe_mask;
8312 case RTE_FLOW_ITEM_TYPE_E_TAG:
8313 mask = &rte_flow_item_e_tag_mask;
8315 case RTE_FLOW_ITEM_TYPE_NVGRE:
8316 mask = &rte_flow_item_nvgre_mask;
8318 case RTE_FLOW_ITEM_TYPE_MPLS:
8319 mask = &rte_flow_item_mpls_mask;
8321 case RTE_FLOW_ITEM_TYPE_GRE:
8322 mask = &rte_flow_item_gre_mask;
8324 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
8325 mask = &gre_key_default_mask;
8327 case RTE_FLOW_ITEM_TYPE_META:
8328 mask = &rte_flow_item_meta_mask;
8330 case RTE_FLOW_ITEM_TYPE_FUZZY:
8331 mask = &rte_flow_item_fuzzy_mask;
8333 case RTE_FLOW_ITEM_TYPE_GTP:
8334 mask = &rte_flow_item_gtp_mask;
8336 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
8337 mask = &rte_flow_item_gtp_psc_mask;
8339 case RTE_FLOW_ITEM_TYPE_GENEVE:
8340 mask = &rte_flow_item_geneve_mask;
8342 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
8343 mask = &rte_flow_item_geneve_opt_mask;
8345 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
8346 mask = &rte_flow_item_pppoe_proto_id_mask;
8348 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
8349 mask = &rte_flow_item_l2tpv3oip_mask;
8351 case RTE_FLOW_ITEM_TYPE_ESP:
8352 mask = &rte_flow_item_esp_mask;
8354 case RTE_FLOW_ITEM_TYPE_AH:
8355 mask = &rte_flow_item_ah_mask;
8357 case RTE_FLOW_ITEM_TYPE_PFCP:
8358 mask = &rte_flow_item_pfcp_mask;
8360 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
8361 mask = &rte_flow_item_ethdev_mask;
8369 /** Dispatch parsed buffer to function calls. */
8371 cmd_set_raw_parsed_sample(const struct buffer *in)
8373 uint32_t n = in->args.vc.actions_n;
8375 struct rte_flow_action *action = NULL;
8376 struct rte_flow_action *data = NULL;
8377 const struct rte_flow_action_rss *rss = NULL;
8379 uint16_t idx = in->port; /* We borrow port field as index */
8380 uint32_t max_size = sizeof(struct rte_flow_action) *
8381 ACTION_SAMPLE_ACTIONS_NUM;
8383 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
8384 data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
8385 memset(data, 0x00, max_size);
8386 for (; i <= n - 1; i++) {
8387 action = in->args.vc.actions + i;
8388 if (action->type == RTE_FLOW_ACTION_TYPE_END)
8390 switch (action->type) {
8391 case RTE_FLOW_ACTION_TYPE_MARK:
8392 size = sizeof(struct rte_flow_action_mark);
8393 rte_memcpy(&sample_mark[idx],
8394 (const void *)action->conf, size);
8395 action->conf = &sample_mark[idx];
8397 case RTE_FLOW_ACTION_TYPE_COUNT:
8398 size = sizeof(struct rte_flow_action_count);
8399 rte_memcpy(&sample_count[idx],
8400 (const void *)action->conf, size);
8401 action->conf = &sample_count[idx];
8403 case RTE_FLOW_ACTION_TYPE_QUEUE:
8404 size = sizeof(struct rte_flow_action_queue);
8405 rte_memcpy(&sample_queue[idx],
8406 (const void *)action->conf, size);
8407 action->conf = &sample_queue[idx];
8409 case RTE_FLOW_ACTION_TYPE_RSS:
8410 size = sizeof(struct rte_flow_action_rss);
8412 rte_memcpy(&sample_rss_data[idx].conf,
8413 (const void *)rss, size);
8414 if (rss->key_len && rss->key) {
8415 sample_rss_data[idx].conf.key =
8416 sample_rss_data[idx].key;
8417 rte_memcpy((void *)((uintptr_t)
8418 sample_rss_data[idx].conf.key),
8419 (const void *)rss->key,
8420 sizeof(uint8_t) * rss->key_len);
8422 if (rss->queue_num && rss->queue) {
8423 sample_rss_data[idx].conf.queue =
8424 sample_rss_data[idx].queue;
8425 rte_memcpy((void *)((uintptr_t)
8426 sample_rss_data[idx].conf.queue),
8427 (const void *)rss->queue,
8428 sizeof(uint16_t) * rss->queue_num);
8430 action->conf = &sample_rss_data[idx].conf;
8432 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
8433 size = sizeof(struct rte_flow_action_raw_encap);
8434 rte_memcpy(&sample_encap[idx],
8435 (const void *)action->conf, size);
8436 action->conf = &sample_encap[idx];
8438 case RTE_FLOW_ACTION_TYPE_PORT_ID:
8439 size = sizeof(struct rte_flow_action_port_id);
8440 rte_memcpy(&sample_port_id[idx],
8441 (const void *)action->conf, size);
8442 action->conf = &sample_port_id[idx];
8444 case RTE_FLOW_ACTION_TYPE_PF:
8446 case RTE_FLOW_ACTION_TYPE_VF:
8447 size = sizeof(struct rte_flow_action_vf);
8448 rte_memcpy(&sample_vf[idx],
8449 (const void *)action->conf, size);
8450 action->conf = &sample_vf[idx];
8452 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
8453 size = sizeof(struct rte_flow_action_vxlan_encap);
8454 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
8455 action->conf = &sample_vxlan_encap[idx].conf;
8457 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
8458 size = sizeof(struct rte_flow_action_nvgre_encap);
8459 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
8460 action->conf = &sample_nvgre_encap[idx];
8463 fprintf(stderr, "Error - Not supported action\n");
8466 rte_memcpy(data, action, sizeof(struct rte_flow_action));
8471 /** Dispatch parsed buffer to function calls. */
8473 cmd_set_raw_parsed(const struct buffer *in)
8475 uint32_t n = in->args.vc.pattern_n;
8477 struct rte_flow_item *item = NULL;
8479 uint8_t *data = NULL;
8480 uint8_t *data_tail = NULL;
8481 size_t *total_size = NULL;
8482 uint16_t upper_layer = 0;
8484 uint16_t idx = in->port; /* We borrow port field as index */
8485 int gtp_psc = -1; /* GTP PSC option index. */
8487 if (in->command == SET_SAMPLE_ACTIONS)
8488 return cmd_set_raw_parsed_sample(in);
8489 RTE_ASSERT(in->command == SET_RAW_ENCAP ||
8490 in->command == SET_RAW_DECAP);
8491 if (in->command == SET_RAW_ENCAP) {
8492 total_size = &raw_encap_confs[idx].size;
8493 data = (uint8_t *)&raw_encap_confs[idx].data;
8495 total_size = &raw_decap_confs[idx].size;
8496 data = (uint8_t *)&raw_decap_confs[idx].data;
8499 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
8500 /* process hdr from upper layer to low layer (L3/L4 -> L2). */
8501 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
8502 for (i = n - 1 ; i >= 0; --i) {
8503 const struct rte_flow_item_gtp *gtp;
8504 const struct rte_flow_item_geneve_opt *opt;
8506 item = in->args.vc.pattern + i;
8507 if (item->spec == NULL)
8508 item->spec = flow_item_default_mask(item);
8509 switch (item->type) {
8510 case RTE_FLOW_ITEM_TYPE_ETH:
8511 size = sizeof(struct rte_ether_hdr);
8513 case RTE_FLOW_ITEM_TYPE_VLAN:
8514 size = sizeof(struct rte_vlan_hdr);
8515 proto = RTE_ETHER_TYPE_VLAN;
8517 case RTE_FLOW_ITEM_TYPE_IPV4:
8518 size = sizeof(struct rte_ipv4_hdr);
8519 proto = RTE_ETHER_TYPE_IPV4;
8521 case RTE_FLOW_ITEM_TYPE_IPV6:
8522 size = sizeof(struct rte_ipv6_hdr);
8523 proto = RTE_ETHER_TYPE_IPV6;
8525 case RTE_FLOW_ITEM_TYPE_UDP:
8526 size = sizeof(struct rte_udp_hdr);
8529 case RTE_FLOW_ITEM_TYPE_TCP:
8530 size = sizeof(struct rte_tcp_hdr);
8533 case RTE_FLOW_ITEM_TYPE_VXLAN:
8534 size = sizeof(struct rte_vxlan_hdr);
8536 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8537 size = sizeof(struct rte_vxlan_gpe_hdr);
8539 case RTE_FLOW_ITEM_TYPE_GRE:
8540 size = sizeof(struct rte_gre_hdr);
8543 case RTE_FLOW_ITEM_TYPE_GRE_KEY:
8544 size = sizeof(rte_be32_t);
8547 case RTE_FLOW_ITEM_TYPE_MPLS:
8548 size = sizeof(struct rte_mpls_hdr);
8551 case RTE_FLOW_ITEM_TYPE_NVGRE:
8552 size = sizeof(struct rte_flow_item_nvgre);
8555 case RTE_FLOW_ITEM_TYPE_GENEVE:
8556 size = sizeof(struct rte_geneve_hdr);
8558 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
8559 opt = (const struct rte_flow_item_geneve_opt *)
8561 size = offsetof(struct rte_flow_item_geneve_opt, data);
8562 if (opt->option_len && opt->data) {
8563 *total_size += opt->option_len *
8565 rte_memcpy(data_tail - (*total_size),
8567 opt->option_len * sizeof(uint32_t));
8570 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
8571 size = sizeof(rte_be32_t);
8574 case RTE_FLOW_ITEM_TYPE_ESP:
8575 size = sizeof(struct rte_esp_hdr);
8578 case RTE_FLOW_ITEM_TYPE_AH:
8579 size = sizeof(struct rte_flow_item_ah);
8582 case RTE_FLOW_ITEM_TYPE_GTP:
8584 size = sizeof(struct rte_gtp_hdr);
8587 if (gtp_psc != i + 1) {
8589 "Error - GTP PSC does not follow GTP\n");
8593 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
8594 /* Only E flag should be set. */
8596 "Error - GTP unsupported flags\n");
8599 struct rte_gtp_hdr_ext_word ext_word = {
8603 /* We have to add GTP header extra word. */
8604 *total_size += sizeof(ext_word);
8605 rte_memcpy(data_tail - (*total_size),
8606 &ext_word, sizeof(ext_word));
8608 size = sizeof(struct rte_gtp_hdr);
8610 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
8613 "Error - Multiple GTP PSC items\n");
8616 const struct rte_flow_item_gtp_psc
8624 psc.len = sizeof(psc);
8625 psc.pdu_type = opt->hdr.type;
8626 psc.qfi = opt->hdr.qfi;
8628 *total_size += sizeof(psc);
8629 rte_memcpy(data_tail - (*total_size),
8635 case RTE_FLOW_ITEM_TYPE_PFCP:
8636 size = sizeof(struct rte_flow_item_pfcp);
8639 fprintf(stderr, "Error - Not supported item\n");
8642 *total_size += size;
8643 rte_memcpy(data_tail - (*total_size), item->spec, size);
8644 /* update some fields which cannot be set by cmdline */
8645 update_fields((data_tail - (*total_size)), item,
8647 upper_layer = proto;
8649 if (verbose_level & 0x1)
8650 printf("total data size is %zu\n", (*total_size));
8651 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
8652 memmove(data, (data_tail - (*total_size)), *total_size);
8657 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
8660 /** Populate help strings for current token (cmdline API). */
8662 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
8665 struct context *ctx = &cmd_flow_context;
8666 const struct token *token = &token_list[ctx->prev];
8671 /* Set token type and update global help with details. */
8672 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
8674 cmd_set_raw.help_str = token->help;
8676 cmd_set_raw.help_str = token->name;
8680 /** Token definition template (cmdline API). */
8681 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
8682 .ops = &(struct cmdline_token_ops){
8683 .parse = cmd_flow_parse,
8684 .complete_get_nb = cmd_flow_complete_get_nb,
8685 .complete_get_elt = cmd_flow_complete_get_elt,
8686 .get_help = cmd_set_raw_get_help,
8691 /** Populate the next dynamic token. */
8693 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
8694 cmdline_parse_token_hdr_t **hdr_inst)
8696 struct context *ctx = &cmd_flow_context;
8698 /* Always reinitialize context before requesting the first token. */
8699 if (!(hdr_inst - cmd_set_raw.tokens)) {
8700 cmd_flow_context_init(ctx);
8701 ctx->curr = START_SET;
8703 /* Return NULL when no more tokens are expected. */
8704 if (!ctx->next_num && (ctx->curr != START_SET)) {
8708 /* Determine if command should end here. */
8709 if (ctx->eol && ctx->last && ctx->next_num) {
8710 const enum index *list = ctx->next[ctx->next_num - 1];
8713 for (i = 0; list[i]; ++i) {
8720 *hdr = &cmd_set_raw_token_hdr;
8723 /** Token generator and output processing callback (cmdline API). */
8725 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
8728 cmd_set_raw_tok(arg0, arg2);
8730 cmd_set_raw_parsed(arg0);
8733 /** Global parser instance (cmdline API). */
8734 cmdline_parse_inst_t cmd_set_raw = {
8735 .f = cmd_set_raw_cb,
8736 .data = NULL, /**< Unused. */
8737 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
8740 }, /**< Tokens are returned by cmd_flow_tok(). */
8743 /* *** display raw_encap/raw_decap buf */
8744 struct cmd_show_set_raw_result {
8745 cmdline_fixed_string_t cmd_show;
8746 cmdline_fixed_string_t cmd_what;
8747 cmdline_fixed_string_t cmd_all;
8752 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
8754 struct cmd_show_set_raw_result *res = parsed_result;
8755 uint16_t index = res->cmd_index;
8757 uint8_t *raw_data = NULL;
8758 size_t raw_size = 0;
8759 char title[16] = {0};
8763 if (!strcmp(res->cmd_all, "all")) {
8766 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
8767 fprintf(stderr, "index should be 0-%u\n",
8768 RAW_ENCAP_CONFS_MAX_NUM - 1);
8772 if (!strcmp(res->cmd_what, "raw_encap")) {
8773 raw_data = (uint8_t *)&raw_encap_confs[index].data;
8774 raw_size = raw_encap_confs[index].size;
8775 snprintf(title, 16, "\nindex: %u", index);
8776 rte_hexdump(stdout, title, raw_data, raw_size);
8778 raw_data = (uint8_t *)&raw_decap_confs[index].data;
8779 raw_size = raw_decap_confs[index].size;
8780 snprintf(title, 16, "\nindex: %u", index);
8781 rte_hexdump(stdout, title, raw_data, raw_size);
8783 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
8786 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
8787 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8789 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
8790 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8791 cmd_what, "raw_encap#raw_decap");
8792 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
8793 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
8794 cmd_index, RTE_UINT16);
8795 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
8796 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8798 cmdline_parse_inst_t cmd_show_set_raw = {
8799 .f = cmd_show_set_raw_parsed,
8801 .help_str = "show <raw_encap|raw_decap> <index>",
8803 (void *)&cmd_show_set_raw_cmd_show,
8804 (void *)&cmd_show_set_raw_cmd_what,
8805 (void *)&cmd_show_set_raw_cmd_index,
8809 cmdline_parse_inst_t cmd_show_set_raw_all = {
8810 .f = cmd_show_set_raw_parsed,
8812 .help_str = "show <raw_encap|raw_decap> all",
8814 (void *)&cmd_show_set_raw_cmd_show,
8815 (void *)&cmd_show_set_raw_cmd_what,
8816 (void *)&cmd_show_set_raw_cmd_all,