Hi Awal, > -----Original Message----- > From: Awal, Mohammad Abdul > Sent: Friday, May 11, 2018 6:14 PM > To: dev@dpdk.org; Iremonger, Bernard <bernard.iremon...@intel.com>; > adrien.mazarg...@6wind.com > Subject: [PATCH v2 1/2] app/testpmd: enabled vxlan and nvgre encap/decap > support for rte_flow > > We have enabled testpmd application with ability to create a flow with > vxlan/nvgre tunnel types and with encapsulation/decapsulation functionalities. > > Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.a...@intel.com> > --- > app/test-pmd/cmdline_flow.c | 937 > ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 937 insertions(+) > > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index > 5754e78..5ffc127 100644 > --- a/app/test-pmd/cmdline_flow.c > +++ b/app/test-pmd/cmdline_flow.c > @@ -237,6 +237,48 @@ 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_VLAN_TCI, > + ACTION_VXLAN_ENCAP_VLAN_TCI_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, > + 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_VLAN_TCI, > + ACTION_NVGRE_ENCAP_VLAN_TCI_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, > + ACTION_NVGRE_DECAP, > }; > > /** Maximum size for pattern in struct rte_flow_item_raw. */ @@ -256,6 > +298,30 @@ 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_vlan vlan; > + 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_vlan vlan; > + 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 +449,13 @@ struct token { > .size = (s), \ > }) > > +#define ARGS_ENTRY_ARB_HTON(o, s) \ > + (&(const struct arg){ \ > + .hton = 1, \ > + .offset = (o), \ > + .size = (s), \ > + }) > +
The ARGS_ENTRY_ARB_HTON macro does not seem to be used in the code. Should it be removed? > /** Same as ARGS_ENTRY_ARB() with bounded values. */ #define > ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \ > (&(const struct arg){ \ > @@ -773,6 +846,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 +951,46 @@ 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_VLAN_TCI, > + 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_VLAN_TCI, > + 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 +1013,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 +2515,282 @@ 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_VLAN_TCI, > + 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_VLAN_TCI] = { > + .name = "vlan_tci", > + .help = "vlan tci for vxlan tunnel", > + .next = NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_VLAN_TCI_VALUE)), > + .call = parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_VLAN_TCI_VALUE] = { > + .name = "vlan_tci_value", > + .help = "vlan tci 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, > + }, > + [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_VLAN_TCI, > + 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_VLAN_TCI] = { > + .name = "vlan_tci", > + .help = "vlan tci for nvgre tunnel", > + .next = NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_VLAN_TCI_VALUE)), > + .call = parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_VLAN_TCI_VALUE] = { > + .name = "vlan_tci_value", > + .help = "vlan tci 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, > + }, > }; > > /** Remove and return last entry from argument stack. */ @@ -2924,6 > +3353,514 @@ parse_vc_action_rss_queue(struct context *ctx, const struct > token *token, > return len; > } > > +/** Parse VXLAN_ENCAP action. */ > +static int __rte_unused > +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 __rte_unused > +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_VLAN_TCI: > + data = ctx->object; > + data->hdr_flags |= RTE_PTYPE_L2_ETHER_VLAN; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec = &data->vlan; > + data->pattern[p_index].mask = &rte_flow_item_vlan_mask; > + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_VLAN; > + 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 > +__rte_unused 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_VLAN_TCI_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val1 = strtoul(str2, NULL, 0); > + if (val1 == 0) > + return -1; > + data->vlan.tci = 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 __rte_unused > +parse_vc_action_vxlan_encap_end(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->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 __rte_unused > +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 __rte_unused > +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 __rte_unused > +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_VLAN_TCI: > + data = ctx->object; > + data->hdr_flags |= RTE_PTYPE_L2_ETHER_VLAN; > + p_index = get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec = &data->vlan; > + data->pattern[p_index].mask = &rte_flow_item_vlan_mask; > + data->pattern[p_index].type = RTE_FLOW_ITEM_TYPE_VLAN; > + 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 > +__rte_unused 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_VLAN_TCI_VALUE: > + memcpy(str2, str, len); > + str2[len] = '\0'; > + val1 = strtoul(str2, NULL, 0); > + if (val1 == 0) > + return -1; > + data->vlan.tci = 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 __rte_unused > +parse_vc_action_nvgre_encap_end(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->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, > -- > 2.7.4 Regards, Bernard.