[dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow

Iremonger, Bernard bernard.iremonger at intel.com
Thu May 10 14:47:14 CEST 2018


Hi Awal,

> -----Original Message-----
> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Mohammad Abdul
> Awal
> Sent: Wednesday, May 9, 2018 5:57 PM
> To: dev at dpdk.org
> Cc: Awal, Mohammad Abdul <mohammad.abdul.awal at intel.com>
> Subject: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap
> support for rte_flow

The commit message should not be empty, it should contain a description of the changes

> 
> Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal at intel.com>
> ---
>  app/test-pmd/cmdline_flow.c | 872
> ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 872 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index
> 5754e78..7d80f2a 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -237,6 +237,44 @@ enum index {
>  	ACTION_OF_POP_MPLS_ETHERTYPE,
>  	ACTION_OF_PUSH_MPLS,
>  	ACTION_OF_PUSH_MPLS_ETHERTYPE,
> +	ACTION_VXLAN_ENCAP,
> +	ACTION_VXLAN_ENCAP_ETH_DST,
> +	ACTION_VXLAN_ENCAP_ETH_DST_VALUE,
> +	ACTION_VXLAN_ENCAP_ETH_SRC,
> +	ACTION_VXLAN_ENCAP_ETH_SRC_VALUE,
> +	ACTION_VXLAN_ENCAP_ETH_TYPE,
> +	ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE,
> +	ACTION_VXLAN_ENCAP_IPV4_DST,
> +	ACTION_VXLAN_ENCAP_IPV4_DST_VALUE,
> +	ACTION_VXLAN_ENCAP_IPV4_SRC,
> +	ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE,
> +	ACTION_VXLAN_ENCAP_IPV4_PROTO,
> +	ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE,
> +	ACTION_VXLAN_ENCAP_UDP_SRC,
> +	ACTION_VXLAN_ENCAP_UDP_SRC_VALUE,
> +	ACTION_VXLAN_ENCAP_UDP_DST,
> +	ACTION_VXLAN_ENCAP_UDP_DST_VALUE,
> +	ACTION_VXLAN_ENCAP_VXLAN_VNI,
> +	ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE,
> +	ACTION_VXLAN_ENCAP_END,

Is ACTION_VXLAN_ENCAP_END necessary, could ACTION_END be used instead?

> +	ACTION_VXLAN_DECAP,
> +	ACTION_NVGRE_ENCAP,
> +	ACTION_NVGRE_ENCAP_ETH_DST,
> +	ACTION_NVGRE_ENCAP_ETH_DST_VALUE,
> +	ACTION_NVGRE_ENCAP_ETH_SRC,
> +	ACTION_NVGRE_ENCAP_ETH_SRC_VALUE,
> +	ACTION_NVGRE_ENCAP_ETH_TYPE,
> +	ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE,
> +	ACTION_NVGRE_ENCAP_IPV4_DST,
> +	ACTION_NVGRE_ENCAP_IPV4_DST_VALUE,
> +	ACTION_NVGRE_ENCAP_IPV4_SRC,
> +	ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE,
> +	ACTION_NVGRE_ENCAP_IPV4_PROTO,
> +	ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE,
> +	ACTION_NVGRE_ENCAP_NVGRE_VSNI,
> +	ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE,
> +	ACTION_NVGRE_ENCAP_END,

Is ACTION_NVGRE_ENCAP_END necessary, could ACTION_END be used instead?

> +	ACTION_NVGRE_DECAP,
>  };
> 
>  /** Maximum size for pattern in struct rte_flow_item_raw. */ @@ -256,6
> +294,28 @@ struct action_rss_data {
>  	uint16_t queue[ACTION_RSS_QUEUE_NUM];
>  };
> 
> +#define ACTION_VXLAN_ENCAP_MAX_PATTERN 5 #define
> +ACTION_NVGRE_ENCAP_MAX_PATTERN 4
> +
> +struct action_vxlan_encap_data {
> +	struct rte_flow_action_vxlan_encap conf;
> +	struct rte_flow_item pattern[ACTION_VXLAN_ENCAP_MAX_PATTERN];
> +	struct rte_flow_item_eth eth;
> +	struct rte_flow_item_ipv4 ipv4;
> +	struct rte_flow_item_udp udp;
> +	struct rte_flow_item_vxlan vxlan;
> +	uint32_t hdr_flags;
> +};
> +
> +struct action_nvgre_encap_data {
> +	struct rte_flow_action_nvgre_encap conf;
> +	struct rte_flow_item pattern[ACTION_NVGRE_ENCAP_MAX_PATTERN];
> +	struct rte_flow_item_eth eth;
> +	struct rte_flow_item_ipv4 ipv4;
> +	struct rte_flow_item_nvgre nvgre;
> +	uint32_t hdr_flags;
> +};
> +
>  /** Maximum number of subsequent tokens and arguments on the stack. */
> #define CTX_STACK_SIZE 16
> 
> @@ -383,6 +443,13 @@ struct token {
>  		.size = (s), \
>  	})
> 
> +#define ARGS_ENTRY_ARB_HTON(o, s) \
> +	(&(const struct arg){ \
> +		.hton = 1, \
> +		.offset = (o), \
> +		.size = (s), \
> +	})
> +
>  /** Same as ARGS_ENTRY_ARB() with bounded values. */  #define
> ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
>  	(&(const struct arg){ \
> @@ -773,6 +840,10 @@ static const enum index next_action[] = {
>  	ACTION_OF_SET_VLAN_PCP,
>  	ACTION_OF_POP_MPLS,
>  	ACTION_OF_PUSH_MPLS,
> +	ACTION_VXLAN_ENCAP,
> +	ACTION_VXLAN_DECAP,
> +	ACTION_NVGRE_ENCAP,
> +	ACTION_NVGRE_DECAP,
>  	ZERO,
>  };
> 
> @@ -874,6 +945,44 @@ static const enum index action_jump[] = {
>  	ZERO,
>  };
> 
> +static const enum index action_vxlan_encap[] = {
> +	ACTION_VXLAN_ENCAP_ETH_DST,
> +	ACTION_VXLAN_ENCAP_ETH_SRC,
> +	ACTION_VXLAN_ENCAP_ETH_TYPE,
> +	ACTION_VXLAN_ENCAP_IPV4_DST,
> +	ACTION_VXLAN_ENCAP_IPV4_SRC,
> +	ACTION_VXLAN_ENCAP_IPV4_PROTO,
> +	ACTION_VXLAN_ENCAP_UDP_DST,
> +	ACTION_VXLAN_ENCAP_UDP_SRC,
> +	ACTION_VXLAN_ENCAP_VXLAN_VNI,
> +	ACTION_VXLAN_ENCAP_END,
> +	ACTION_NEXT,
> +	ZERO,
> +};
> +
> +static const enum index action_vxlan_decap[] = {
> +	ACTION_NEXT,
> +	ZERO,
> +};
> +
> +static const enum index action_nvgre_encap[] = {
> +	ACTION_NVGRE_ENCAP_ETH_DST,
> +	ACTION_NVGRE_ENCAP_ETH_SRC,
> +	ACTION_NVGRE_ENCAP_ETH_TYPE,
> +	ACTION_NVGRE_ENCAP_IPV4_DST,
> +	ACTION_NVGRE_ENCAP_IPV4_SRC,
> +	ACTION_NVGRE_ENCAP_IPV4_PROTO,
> +	ACTION_NVGRE_ENCAP_NVGRE_VSNI,
> +	ACTION_NVGRE_ENCAP_END,
> +	ACTION_NEXT,
> +	ZERO,
> +};
> +
> +static const enum index action_nvgre_decap[] = {
> +	ACTION_NEXT,
> +	ZERO,
> +};
> +
>  static int parse_init(struct context *, const struct token *,
>  		      const char *, unsigned int,
>  		      void *, unsigned int);
> @@ -896,6 +1005,42 @@ static int parse_vc_action_rss_type(struct context *,
> const struct token *,  static int parse_vc_action_rss_queue(struct context *,
> const struct token *,
>  				     const char *, unsigned int, void *,
>  				     unsigned int);
> +static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
> +				       const char *, unsigned int, void *,
> +				       unsigned int);
> +static int parse_vc_action_vxlan_decap(struct context *, const struct token *,
> +				       const char *, unsigned int, void *,
> +				       unsigned int);
> +static int parse_vc_action_vxlan_encap_fields(struct context *,
> +					      const struct token *,
> +					      const char *, unsigned int,
> +					      void *, unsigned int);
> +static int parse_vc_action_vxlan_encap_fields_value(struct context *,
> +						    const struct token *,
> +						    const char *, unsigned int,
> +						    void *, unsigned int);
> +static int parse_vc_action_vxlan_encap_end(struct context *,
> +					   const struct token *,
> +					   const char *, unsigned int,
> +					   void *, unsigned int);
> +static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
> +				       const char *, unsigned int, void *,
> +				       unsigned int);
> +static int parse_vc_action_nvgre_decap(struct context *, const struct token *,
> +				       const char *, unsigned int, void *,
> +				       unsigned int);
> +static int parse_vc_action_nvgre_encap_fields(struct context *,
> +					      const struct token *,
> +					      const char *, unsigned int,
> +					      void *, unsigned int);
> +static int parse_vc_action_nvgre_encap_fields_value(struct context *,
> +						    const struct token *,
> +						    const char *, unsigned int,
> +						    void *, unsigned int);
> +static int parse_vc_action_nvgre_encap_end(struct context *,
> +					   const struct token *,
> +					   const char *, unsigned int,
> +					   void *, unsigned int);
>  static int parse_destroy(struct context *, const struct token *,
>  			 const char *, unsigned int,
>  			 void *, unsigned int);
> @@ -2362,6 +2507,256 @@ static const struct token token_list[] = {
>  			      ethertype)),
>  		.call = parse_vc_conf,
>  	},
> +	[ACTION_VXLAN_ENCAP] = {
> +		.name = "vxlan_encap",
> +		.help = "encap flow with vxlan tunnel definition",
> +		.priv = PRIV_ACTION(VXLAN_ENCAP,
> +				    sizeof(struct action_vxlan_encap_data)),
> +		.next = NEXT(action_vxlan_encap,
> +
> 	NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST,
> +					ACTION_VXLAN_ENCAP_ETH_SRC,
> +					ACTION_VXLAN_ENCAP_ETH_TYPE,
> +					ACTION_VXLAN_ENCAP_IPV4_DST,
> +					ACTION_VXLAN_ENCAP_IPV4_SRC,
> +					ACTION_VXLAN_ENCAP_IPV4_PROTO,
> +					ACTION_VXLAN_ENCAP_UDP_DST,
> +					ACTION_VXLAN_ENCAP_UDP_SRC,
> +					ACTION_VXLAN_ENCAP_VXLAN_VNI,
> +					ACTION_VXLAN_ENCAP_END)),
> +		.call = parse_vc_action_vxlan_encap,
> +	},
> +	[ACTION_VXLAN_DECAP] = {
> +		.name = "vxlan_decap",
> +		.help = "decap flow with vxlan tunnel definition",
> +		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
> +		.next = NEXT(action_vxlan_decap),
> +		.call = parse_vc_action_vxlan_decap,
> +	},
> +	[ACTION_VXLAN_ENCAP_ETH_DST] = {
> +		.name = "eth_dst",
> +		.help = "destination MAC for vxlan tunnel",
> +		.next = NEXT(action_vxlan_encap,
> +
> NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST_VALUE)),
> +		.call = parse_vc_action_vxlan_encap_fields,
> +	},
> +	[ACTION_VXLAN_ENCAP_ETH_DST_VALUE] = {
> +		.name = "eth_dst_value",
> +		.help = "destination MAC for vxlan tunnel",
> +		.call = parse_vc_action_vxlan_encap_fields_value,
> +	},
> +	[ACTION_VXLAN_ENCAP_ETH_SRC] = {
> +		.name = "eth_src",
> +		.help = "source MAC for vxlan tunnel",
> +		.next = NEXT(action_vxlan_encap,
> +
> NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_SRC_VALUE)),
> +		.call = parse_vc_action_vxlan_encap_fields,
> +	},
> +	[ACTION_VXLAN_ENCAP_ETH_SRC_VALUE] = {
> +		.name = "eth_src_value",
> +		.help = "source MAC for vxlan tunnel",
> +		.call = parse_vc_action_vxlan_encap_fields_value,
> +	},
> +	[ACTION_VXLAN_ENCAP_ETH_TYPE] = {
> +		.name = "eth_type",
> +		.help = "eth type for vxlan tunnel",
> +		.next = NEXT(action_vxlan_encap,
> +
> NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE)),
> +		.call = parse_vc_action_vxlan_encap_fields,
> +	},
> +	[ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE] = {
> +		.name = "eth_type_value",
> +		.help = "eth type for vxlan tunnel",
> +		.call = parse_vc_action_vxlan_encap_fields_value,
> +	},
> +	[ACTION_VXLAN_ENCAP_IPV4_DST] = {
> +		.name = "ipv4_dst",
> +		.help = "destination ipv4 IP for vxlan tunnel",
> +		.next = NEXT(action_vxlan_encap,
> +
> NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_DST_VALUE)),
> +		.call = parse_vc_action_vxlan_encap_fields,
> +	},
> +	[ACTION_VXLAN_ENCAP_IPV4_DST_VALUE] = {
> +		.name = "ipv4_dst_value",
> +		.help = "destination ipv4 IP for vxlan tunnel",
> +		.call = parse_vc_action_vxlan_encap_fields_value,
> +	},
> +	[ACTION_VXLAN_ENCAP_IPV4_SRC] = {
> +		.name = "ipv4_src",
> +		.help = "source ipv4 IP for vxlan tunnel",
> +		.next = NEXT(action_vxlan_encap,
> +
> NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE)),
> +		.call = parse_vc_action_vxlan_encap_fields,
> +	},
> +	[ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE] = {
> +		.name = "ipv4_src_value",
> +		.help = "source ipv4 IP for vxlan tunnel",
> +		.call = parse_vc_action_vxlan_encap_fields_value,
> +	},
> +	[ACTION_VXLAN_ENCAP_IPV4_PROTO] = {
> +		.name = "ipv4_proto",
> +		.help = "ipv4 proto for vxlan tunnel",
> +		.next = NEXT(action_vxlan_encap,
> +
> NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE)),
> +		.call = parse_vc_action_vxlan_encap_fields,
> +	},
> +	[ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE] = {
> +		.name = "ipv4_proto_value",
> +		.help = "ipv4 proto for vxlan tunnel",
> +		.call = parse_vc_action_vxlan_encap_fields_value,
> +	},
> +	[ACTION_VXLAN_ENCAP_UDP_DST] = {
> +		.name = "udp_dst",
> +		.help = "udp destination port for vxlan tunnel",
> +		.next = NEXT(action_vxlan_encap,
> +
> NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_DST_VALUE)),
> +		.call = parse_vc_action_vxlan_encap_fields,
> +	},
> +	[ACTION_VXLAN_ENCAP_UDP_DST_VALUE] = {
> +		.name = "udp_dst_value",
> +		.help = "udp destination port for vxlan tunnel",
> +		.call = parse_vc_action_vxlan_encap_fields_value,
> +	},
> +	[ACTION_VXLAN_ENCAP_UDP_SRC] = {
> +		.name = "udp_src",
> +		.help = "udp source port for vxlan tunnel",
> +		.next = NEXT(action_vxlan_encap,
> +
> NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_SRC_VALUE)),
> +		.call = parse_vc_action_vxlan_encap_fields,
> +	},
> +	[ACTION_VXLAN_ENCAP_UDP_SRC_VALUE] = {
> +		.name = "udp_src_value",
> +		.help = "udp source port for vxlan tunnel",
> +		.call = parse_vc_action_vxlan_encap_fields_value,
> +	},
> +	[ACTION_VXLAN_ENCAP_VXLAN_VNI] = {
> +		.name = "vxlan_vni",
> +		.help = "vxlan vni for vxlan tunnel",
> +		.next = NEXT(action_vxlan_encap,
> +
> NEXT_ENTRY(ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE)),
> +		.call = parse_vc_action_vxlan_encap_fields,
> +	},
> +	[ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE] = {
> +		.name = "vxlan_vni_value",
> +		.help = "vxlan vni for vxlan tunnel",
> +		.call = parse_vc_action_vxlan_encap_fields_value,
> +	},
> +	[ACTION_VXLAN_ENCAP_END] = {
> +		.name = "end",
> +		.help = "end of the pattern for vxlan encap",
> +		.call = parse_vc_action_vxlan_encap_end,

"end" only is being parsed, could ACTION_END be used instead?

> +	},
> +	[ACTION_NVGRE_ENCAP] = {
> +		.name = "nvgre_encap",
> +		.help = "encap flow with nvgre tunnel definition",
> +		.priv = PRIV_ACTION(NVGRE_ENCAP,
> +				    sizeof(struct action_nvgre_encap_data)),
> +		.next = NEXT(action_nvgre_encap,
> +
> 	NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST,
> +					ACTION_NVGRE_ENCAP_ETH_SRC,
> +					ACTION_NVGRE_ENCAP_ETH_TYPE,
> +					ACTION_NVGRE_ENCAP_IPV4_DST,
> +					ACTION_NVGRE_ENCAP_IPV4_SRC,
> +					ACTION_NVGRE_ENCAP_IPV4_PROTO,
> +					ACTION_NVGRE_ENCAP_NVGRE_VSNI,
> +					ACTION_NVGRE_ENCAP_END)),
> +		.call = parse_vc_action_nvgre_encap,
> +	},
> +	[ACTION_NVGRE_DECAP] = {
> +		.name = "nvgre_decap",
> +		.help = "decap flow with nvgre tunnel definition",
> +		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
> +		.next = NEXT(action_nvgre_decap),
> +		.call = parse_vc_action_nvgre_decap,
> +	},
> +	[ACTION_NVGRE_ENCAP_ETH_DST] = {
> +		.name = "eth_dst",
> +		.help = "destination MAC for nvgre tunnel",
> +		.next = NEXT(action_nvgre_encap,
> +
> NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST_VALUE)),
> +		.call = parse_vc_action_nvgre_encap_fields,
> +	},
> +	[ACTION_NVGRE_ENCAP_ETH_DST_VALUE] = {
> +		.name = "eth_dst_value",
> +		.help = "destination MAC for nvgre tunnel",
> +		.call = parse_vc_action_nvgre_encap_fields_value,
> +	},
> +	[ACTION_NVGRE_ENCAP_ETH_SRC] = {
> +		.name = "eth_src",
> +		.help = "source MAC for nvgre tunnel",
> +		.next = NEXT(action_nvgre_encap,
> +
> NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_SRC_VALUE)),
> +		.call = parse_vc_action_nvgre_encap_fields,
> +	},
> +	[ACTION_NVGRE_ENCAP_ETH_SRC_VALUE] = {
> +		.name = "eth_src_value",
> +		.help = "source MAC for nvgre tunnel",
> +		.call = parse_vc_action_nvgre_encap_fields_value,
> +	},
> +	[ACTION_NVGRE_ENCAP_ETH_TYPE] = {
> +		.name = "eth_type",
> +		.help = "eth type for nvgre tunnel",
> +		.next = NEXT(action_nvgre_encap,
> +
> NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE)),
> +		.call = parse_vc_action_nvgre_encap_fields,
> +	},
> +	[ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE] = {
> +		.name = "eth_type_value",
> +		.help = "eth type for nvgre tunnel",
> +		.call = parse_vc_action_nvgre_encap_fields_value,
> +	},
> +	[ACTION_NVGRE_ENCAP_IPV4_DST] = {
> +		.name = "ipv4_dst",
> +		.help = "destination ipv4 IP for nvgre tunnel",
> +		.next = NEXT(action_nvgre_encap,
> +
> NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_DST_VALUE)),
> +		.call = parse_vc_action_nvgre_encap_fields,
> +	},
> +	[ACTION_NVGRE_ENCAP_IPV4_DST_VALUE] = {
> +		.name = "ipv4_dst_value",
> +		.help = "destination ipv4 IP for nvgre tunnel",
> +		.call = parse_vc_action_nvgre_encap_fields_value,
> +	},
> +	[ACTION_NVGRE_ENCAP_IPV4_SRC] = {
> +		.name = "ipv4_src",
> +		.help = "source ipv4 IP for nvgre tunnel",
> +		.next = NEXT(action_nvgre_encap,
> +
> NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE)),
> +		.call = parse_vc_action_nvgre_encap_fields,
> +	},
> +	[ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE] = {
> +		.name = "ipv4_src_value",
> +		.help = "source ipv4 IP for nvgre tunnel",
> +		.call = parse_vc_action_nvgre_encap_fields_value,
> +	},
> +	[ACTION_NVGRE_ENCAP_IPV4_PROTO] = {
> +		.name = "ipv4_proto",
> +		.help = "ipv4 proto for nvgre tunnel",
> +		.next = NEXT(action_nvgre_encap,
> +
> NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE)),
> +		.call = parse_vc_action_nvgre_encap_fields,
> +	},
> +	[ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE] = {
> +		.name = "ipv4_proto_value",
> +		.help = "ipv4 proto for nvgre tunnel",
> +		.call = parse_vc_action_nvgre_encap_fields_value,
> +	},
> +	[ACTION_NVGRE_ENCAP_NVGRE_VSNI] = {
> +		.name = "nvgre_vsni",
> +		.help = "nvgre vsni for NVGRE tunnel",
> +		.next = NEXT(action_nvgre_encap,
> +
> NEXT_ENTRY(ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE)),
> +		.call = parse_vc_action_nvgre_encap_fields,
> +	},
> +	[ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE] = {
> +		.name = "nvgre_vsni_value",
> +		.help = "nvgre vsni for nvgre tunnel",
> +		.call = parse_vc_action_nvgre_encap_fields_value,
> +	},
> +	[ACTION_NVGRE_ENCAP_END] = {
> +		.name = "end",
> +		.help = "end of the pattern for nvgre encap",
> +		.call = parse_vc_action_nvgre_encap_end,

"end" only is being parsed, could ACTION_END be used instead?

> +	},
>  };
> 
>  /** Remove and return last entry from argument stack. */ @@ -2924,6
> +3319,482 @@ parse_vc_action_rss_queue(struct context *ctx, const struct
> token *token,
>  	return len;
>  }
> 
> +/** Parse VXLAN_ENCAP action. */
> +static int
> +parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
> +			    const char *str, unsigned int len,
> +			    void *buf, unsigned int size)
> +{
> +	struct buffer *out = buf;
> +	struct rte_flow_action *action;
> +	struct action_vxlan_encap_data *data;
> +	int ret;
> +
> +	ret = parse_vc(ctx, token, str, len, buf, size);
> +	if (ret < 0)
> +		return ret;
> +	/* Nothing else to do if there is no buffer. */
> +	if (!out)
> +		return ret;
> +	if (!out->args.vc.actions_n)
> +		return -1;
> +	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
> +	/* Point to selected object. */
> +	ctx->object = out->args.vc.data;
> +	ctx->objmask = NULL;
> +	/* Set up default configuration. */
> +	data = ctx->object;
> +	data->conf.definition = data->pattern;
> +	action->conf = &data->conf;
> +
> +	return ret;
> +}
> +
> +/** Parse VXLAN_DECAP action. */
> +static int
> +parse_vc_action_vxlan_decap(struct context *ctx, const struct token *token,
> +			    const char *str, unsigned int len,
> +			    void *buf, unsigned int size)
> +{
> +	struct buffer *out = buf;
> +	int ret;
> +
> +	ret = parse_vc(ctx, token, str, len, buf, size);
> +	if (ret < 0)
> +		return ret;
> +	/* Nothing else to do if there is no buffer. */
> +	if (!out)
> +		return ret;
> +	if (!out->args.vc.actions_n)
> +		return -1;
> +	/* Point to selected object. */
> +	ctx->object = out->args.vc.data;
> +	ctx->objmask = NULL;
> +	return ret;
> +}
> +
> +static uint32_t get_proto_index_using_flag(uint32_t flag) {
> +	uint32_t c = 0, i = 0;
> +	uint32_t supported_ptypes[] = {
> +					RTE_PTYPE_L2_ETHER,
> +					RTE_PTYPE_L2_ETHER_VLAN,
> +					RTE_PTYPE_L3_IPV4,
> +					RTE_PTYPE_L4_UDP,
> +					RTE_PTYPE_TUNNEL_VXLAN,
> +					RTE_PTYPE_TUNNEL_NVGRE
> +				       };
> +
> +	for (i = 0; i != RTE_DIM(supported_ptypes); i++) {
> +		if (supported_ptypes[i] & flag)
> +			c++;
> +	}
> +	c = (c > 0) ? (c - 1) : 0;
> +
> +	return c;
> +}
> +
> +/** Parse VXLAN_ENCAP action pattern fields. */ static int
> +parse_vc_action_vxlan_encap_fields(struct context *ctx,
> +				   const struct token *token,
> +				   const char *str, unsigned int len,
> +				   void *buf, unsigned int size)
> +{
> +	struct action_vxlan_encap_data *data;
> +	uint32_t p_index;
> +
> +	(void)buf;
> +	(void)size;
> +	/* Token name must match. */
> +	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
> +		return -1;
> +	if (!ctx->object)
> +		return len;
> +	switch (ctx->curr) {
> +	case ACTION_VXLAN_ENCAP_ETH_DST:
> +	case ACTION_VXLAN_ENCAP_ETH_SRC:
> +	case ACTION_VXLAN_ENCAP_ETH_TYPE:
> +		data = ctx->object;
> +		data->hdr_flags |= RTE_PTYPE_L2_ETHER;
> +		p_index = get_proto_index_using_flag(data->hdr_flags);
> +		data->pattern[p_index].spec = &data->eth;
> +		data->pattern[p_index].mask = &rte_flow_item_eth_mask;
> +		data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH;
> +		break;
> +	case ACTION_VXLAN_ENCAP_IPV4_DST:
> +	case ACTION_VXLAN_ENCAP_IPV4_SRC:
> +	case ACTION_VXLAN_ENCAP_IPV4_PROTO:
> +		data = ctx->object;
> +		data->hdr_flags |= RTE_PTYPE_L3_IPV4;
> +		p_index = get_proto_index_using_flag(data->hdr_flags);
> +		data->pattern[p_index].spec = &data->ipv4;
> +		data->pattern[p_index].mask = &rte_flow_item_ipv4_mask;
> +		data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		break;
> +	case ACTION_VXLAN_ENCAP_UDP_DST:
> +	case ACTION_VXLAN_ENCAP_UDP_SRC:
> +		data = ctx->object;
> +		data->hdr_flags |= RTE_PTYPE_L4_UDP;
> +		p_index = get_proto_index_using_flag(data->hdr_flags);
> +		data->pattern[p_index].spec = &data->udp;
> +		data->pattern[p_index].mask = &rte_flow_item_udp_mask;
> +		data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_UDP;
> +		break;
> +	case ACTION_VXLAN_ENCAP_VXLAN_VNI:
> +		data = ctx->object;
> +		data->hdr_flags |= RTE_PTYPE_TUNNEL_VXLAN;
> +		p_index = get_proto_index_using_flag(data->hdr_flags);
> +		data->pattern[p_index].spec = &data->vxlan;
> +		data->pattern[p_index].mask = &rte_flow_item_vxlan_mask;
> +		data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_VXLAN;
> +		break;
> +	default:
> +		return -1;
> +	}
> +
> +	return len;
> +}
> +
> +/** Parse VXLAN_ENCAP action pattern fields value. */ static int
> +parse_vc_action_vxlan_encap_fields_value(struct context *ctx,
> +					 const struct token *token,
> +					 const char *str, unsigned int len,
> +					 void *buf, unsigned int size)
> +{
> +	struct action_vxlan_encap_data *data;
> +	struct ether_addr mac;
> +	char str2[len + 1];
> +	struct in_addr ip4;
> +	uint16_t val1;
> +	uint32_t val2;
> +	int ret;
> +
> +	(void)token;
> +	(void)buf;
> +	if (!ctx->object)
> +		return len;
> +	data = ctx->object;
> +	switch (ctx->curr) {
> +	case ACTION_VXLAN_ENCAP_ETH_DST_VALUE:
> +		ret = cmdline_parse_etheraddr(NULL, str, &mac, size);
> +		if (ret < 0 || (unsigned int)ret != len)
> +			return -1;
> +		memcpy(&data->eth.dst, &mac, sizeof(mac));
> +		break;
> +	case ACTION_VXLAN_ENCAP_ETH_SRC_VALUE:
> +		ret = cmdline_parse_etheraddr(NULL, str, &mac, size);
> +		if (ret < 0 || (unsigned int)ret != len)
> +			return -1;
> +		memcpy(&data->eth.src, &mac, sizeof(mac));
> +		break;
> +	case ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		val1 = strtoul(str2, NULL, 0);
> +		if (val1 == 0)
> +			return -1;
> +		data->eth.type = htons(val1);
> +		break;
> +	case ACTION_VXLAN_ENCAP_IPV4_DST_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		ret = inet_pton(AF_INET, str2, &ip4);
> +		if (ret != 1)
> +			return -1;
> +		memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4));
> +		break;
> +	case ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		ret = inet_pton(AF_INET, str2, &ip4);
> +		if (ret != 1)
> +			return -1;
> +		memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4));
> +		break;
> +	case ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		val1 = strtoul(str2, NULL, 0);
> +		if (val1 == 0)
> +			return -1;
> +		data->ipv4.hdr.next_proto_id = val1;
> +		break;
> +	case ACTION_VXLAN_ENCAP_UDP_DST_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		val1 = strtoul(str2, NULL, 0);
> +		if (val1 == 0)
> +			return -1;
> +		data->udp.hdr.dst_port = htons(val1);
> +		break;
> +	case ACTION_VXLAN_ENCAP_UDP_SRC_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		val1 = strtoul(str2, NULL, 0);
> +		if (val1 == 0)
> +			return -1;
> +		data->udp.hdr.src_port = htons(val1);
> +		break;
> +	case ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		val2 = strtoul(str2, NULL, 0);
> +		if (val2 == 0)
> +			return -1;
> +		data->vxlan.vni[0] = (uint8_t)((val2 >> 16) & 0xff);
> +		data->vxlan.vni[1] = (uint8_t)((val2 >> 8) & 0xff);
> +		data->vxlan.vni[2] = (uint8_t)(val2 & 0xff);
> +		break;
> +	default:
> +		return -1;
> +	}
> +
> +	return len;
> +}
> +
> +/** Parse VXLAN_ENCAP action pattern end. */ static int
> +parse_vc_action_vxlan_encap_end(struct context *ctx,
> +				const struct token *token,
> +				const char *str, unsigned int len,
> +				void *buf, unsigned int size)
> +{

This function should not be necessary if ACTION_END be used instead?

> +	struct action_vxlan_encap_data *data;
> +	uint32_t p_index;
> +
> +	(void)buf;
> +	(void)size;
> +	/* Token name must match. */
> +	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
> +		return -1;
> +	if (ctx->curr != ACTION_VXLAN_ENCAP_END)
> +		return -1;
> +	if (!ctx->object)
> +		return len;
> +	data = ctx->object;
> +	p_index = get_proto_index_using_flag(data->hdr_flags);
> +	data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END;
> +
> +	return len;
> +}
> +
> +/** Parse NVGRE_ENCAP action. */
> +static int
> +parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
> +			    const char *str, unsigned int len,
> +			    void *buf, unsigned int size)
> +{
> +	struct buffer *out = buf;
> +	struct rte_flow_action *action;
> +	struct action_nvgre_encap_data *data;
> +	int ret;
> +
> +	ret = parse_vc(ctx, token, str, len, buf, size);
> +	if (ret < 0)
> +		return ret;
> +	/* Nothing else to do if there is no buffer. */
> +	if (!out)
> +		return ret;
> +	if (!out->args.vc.actions_n)
> +		return -1;
> +	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
> +	/* Point to selected object. */
> +	ctx->object = out->args.vc.data;
> +	ctx->objmask = NULL;
> +	/* Set up default configuration. */
> +	data = ctx->object;
> +	data->conf.definition = data->pattern;
> +	action->conf = &data->conf;
> +
> +	return ret;
> +}
> +
> +/** Parse NVGRE_DECAP action. */
> +static int
> +parse_vc_action_nvgre_decap(struct context *ctx, const struct token *token,
> +			    const char *str, unsigned int len,
> +			    void *buf, unsigned int size)
> +{
> +	struct buffer *out = buf;
> +	int ret;
> +
> +	ret = parse_vc(ctx, token, str, len, buf, size);
> +	if (ret < 0)
> +		return ret;
> +	/* Nothing else to do if there is no buffer. */
> +	if (!out)
> +		return ret;
> +	if (!out->args.vc.actions_n)
> +		return -1;
> +	/* Point to selected object. */
> +	ctx->object = out->args.vc.data;
> +	ctx->objmask = NULL;
> +	return ret;
> +}
> +
> +/** Parse NVGRE_ENCAP action pattern fields. */ static int
> +parse_vc_action_nvgre_encap_fields(struct context *ctx,
> +				   const struct token *token,
> +				   const char *str, unsigned int len,
> +				   void *buf, unsigned int size)
> +{
> +	struct action_nvgre_encap_data *data;
> +	uint32_t p_index;
> +
> +	(void)buf;
> +	(void)size;
> +	/* Token name must match. */
> +	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
> +		return -1;
> +	if (!ctx->object)
> +		return len;
> +	switch (ctx->curr) {
> +	case ACTION_NVGRE_ENCAP_ETH_DST:
> +	case ACTION_NVGRE_ENCAP_ETH_SRC:
> +	case ACTION_NVGRE_ENCAP_ETH_TYPE:
> +		data = ctx->object;
> +		data->hdr_flags |= RTE_PTYPE_L2_ETHER;
> +		p_index = get_proto_index_using_flag(data->hdr_flags);
> +		data->pattern[p_index].spec = &data->eth;
> +		data->pattern[p_index].mask = &rte_flow_item_eth_mask;
> +		data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_ETH;
> +		break;
> +	case ACTION_NVGRE_ENCAP_IPV4_DST:
> +	case ACTION_NVGRE_ENCAP_IPV4_SRC:
> +	case ACTION_NVGRE_ENCAP_IPV4_PROTO:
> +		data = ctx->object;
> +		data->hdr_flags |= RTE_PTYPE_L3_IPV4;
> +		p_index = get_proto_index_using_flag(data->hdr_flags);
> +		data->pattern[p_index].spec = &data->ipv4;
> +		data->pattern[p_index].mask = &rte_flow_item_ipv4_mask;
> +		data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		break;
> +	case ACTION_NVGRE_ENCAP_NVGRE_VSNI:
> +		data = ctx->object;
> +		data->hdr_flags |= RTE_PTYPE_TUNNEL_NVGRE;
> +		p_index = get_proto_index_using_flag(data->hdr_flags);
> +		data->pattern[p_index].spec = &data->nvgre;
> +		data->pattern[p_index].mask = &rte_flow_item_nvgre_mask;
> +		data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_NVGRE;
> +		break;
> +	default:
> +		return -1;
> +	}
> +
> +	return len;
> +}
> +
> +/** Parse NVGRE_ENCAP action pattern fields value. */ static int
> +parse_vc_action_nvgre_encap_fields_value(struct context *ctx,
> +					 const struct token *token,
> +					 const char *str, unsigned int len,
> +					 void *buf, unsigned int size)
> +{
> +	struct action_nvgre_encap_data *data;
> +	struct ether_addr mac;
> +	char str2[len + 1];
> +	struct in_addr ip4;
> +	uint16_t val1;
> +	uint32_t val2;
> +	int ret;
> +
> +	(void)token;
> +	(void)buf;
> +	if (!ctx->object)
> +		return len;
> +	data = ctx->object;
> +	switch (ctx->curr) {
> +	case ACTION_NVGRE_ENCAP_ETH_DST_VALUE:
> +		ret = cmdline_parse_etheraddr(NULL, str, &mac, size);
> +		if (ret < 0 || (unsigned int)ret != len)
> +			return -1;
> +		memcpy(&data->eth.dst, &mac, sizeof(mac));
> +		break;
> +	case ACTION_NVGRE_ENCAP_ETH_SRC_VALUE:
> +		ret = cmdline_parse_etheraddr(NULL, str, &mac, size);
> +		if (ret < 0 || (unsigned int)ret != len)
> +			return -1;
> +		memcpy(&data->eth.src, &mac, sizeof(mac));
> +		break;
> +	case ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		val1 = strtoul(str2, NULL, 0);
> +		if (val1 == 0)
> +			return -1;
> +		data->eth.type = htons(val1);
> +		break;
> +	case ACTION_NVGRE_ENCAP_IPV4_DST_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		ret = inet_pton(AF_INET, str2, &ip4);
> +		if (ret != 1)
> +			return -1;
> +		memcpy(&data->ipv4.hdr.dst_addr, &ip4, sizeof(ip4));
> +		break;
> +	case ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		ret = inet_pton(AF_INET, str2, &ip4);
> +		if (ret != 1)
> +			return -1;
> +		memcpy(&data->ipv4.hdr.src_addr, &ip4, sizeof(ip4));
> +		break;
> +	case ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		val1 = strtoul(str2, NULL, 0);
> +		if (val1 == 0)
> +			return -1;
> +		data->ipv4.hdr.next_proto_id = val1;
> +		break;
> +	case ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE:
> +		memcpy(str2, str, len);
> +		str2[len] = '\0';
> +		val2 = strtoul(str2, NULL, 0);
> +		if (val2 == 0)
> +			return -1;
> +		data->nvgre.tni[0] = (uint8_t)((val2 >> 16) & 0xff);
> +		data->nvgre.tni[1] = (uint8_t)((val2 >> 8) & 0xff);
> +		data->nvgre.tni[2] = (uint8_t)(val2 & 0xff);
> +		break;
> +	default:
> +		return -1;
> +	}
> +
> +	return len;
> +}
> +
> +/** Parse NVGRE_ENCAP action pattern end. */ static int
> +parse_vc_action_nvgre_encap_end(struct context *ctx,
> +				const struct token *token,
> +				const char *str, unsigned int len,
> +				void *buf, unsigned int size)
> +{

This function should not be necessary if ACTION_END be used instead?

> +	struct action_nvgre_encap_data *data;
> +	uint32_t p_index;
> +
> +	(void)buf;
> +	(void)size;
> +	/* Token name must match. */
> +	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
> +		return -1;
> +	if (ctx->curr != ACTION_NVGRE_ENCAP_END)
> +		return -1;
> +	if (!ctx->object)
> +		return len;
> +	data = ctx->object;
> +	p_index = get_proto_index_using_flag(data->hdr_flags);
> +	data->pattern[p_index + 1].type = RTE_FLOW_ITEM_TYPE_END;
> +
> +	return len;
> +}
> +
>  /** Parse tokens for destroy command. */  static int  parse_destroy(struct
> context *ctx, const struct token *token, @@ -2961,6 +3832,7 @@
> parse_destroy(struct context *ctx, const struct token *token,
>  	return len;
>  }
> 
> +

Extra blank line should be removed.

>  /** Parse tokens for flush command. */
>  static int
>  parse_flush(struct context *ctx, const struct token *token,
> --
> 2.7.4

In the Testpmd  Application/User Guide, there is section 4.12. Flow rules management.
dpdk/build/doc/html/guides/testpmd_app_ug/index.html

As the encap and decap flows are fairly complex, It might be worth adding sections on Sample Encap flow rules and Sample Decap flow rules.

Regards,

Bernard.



More information about the dev mailing list