From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 2C5F2239 for ; Thu, 10 May 2018 14:47:19 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 May 2018 05:47:17 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,385,1520924400"; d="scan'208";a="54025069" Received: from irsmsx107.ger.corp.intel.com ([163.33.3.99]) by fmsmga001.fm.intel.com with ESMTP; 10 May 2018 05:47:15 -0700 Received: from irsmsx108.ger.corp.intel.com ([169.254.11.150]) by IRSMSX107.ger.corp.intel.com ([169.254.10.141]) with mapi id 14.03.0319.002; Thu, 10 May 2018 13:47:15 +0100 From: "Iremonger, Bernard" To: "Awal, Mohammad Abdul" , "dev@dpdk.org" , Adrien Mazarguil CC: "Awal, Mohammad Abdul" Thread-Topic: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow Thread-Index: AQHT57bCPC1mnfxH1kSH57NOPk8wNqQo5NGQ Date: Thu, 10 May 2018 12:47:14 +0000 Message-ID: <8CEF83825BEC744B83065625E567D7C24E0C9955@IRSMSX108.ger.corp.intel.com> References: <1525884992-24390-1-git-send-email-mohammad.abdul.awal@intel.com> In-Reply-To: <1525884992-24390-1-git-send-email-mohammad.abdul.awal@intel.com> Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiNDM5Y2U5ZmEtMDM1ZS00NmNkLThhNjgtNzZmM2E1MjJmNGU5IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjIuNS4xOCIsIlRydXN0ZWRMYWJlbEhhc2giOiJKSW9rWGx0aG12Z1NNcG1FTTZHU2hRYXQ2OUdcLzIxOW5ZNmZDb2RveW9PSnJyRUpZeXNkMFM1UkljTFdrMmFMMiJ9 x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.0.200.100 dlp-reaction: no-action x-originating-ip: [163.33.239.180] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/decap support for rte_flow X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 10 May 2018 12:47:21 -0000 Hi Awal, > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Mohammad Abdul > Awal > Sent: Wednesday, May 9, 2018 5:57 PM > To: dev@dpdk.org > Cc: Awal, Mohammad Abdul > Subject: [dpdk-dev] [PATCH] app/testpmd: enabled vxlan and nvgre encap/de= cap > support for rte_flow The commit message should not be empty, it should contain a description of = the changes >=20 > Signed-off-by: Mohammad Abdul Awal > --- > app/test-pmd/cmdline_flow.c | 872 > ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 872 insertions(+) >=20 > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c in= dex > 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, > }; >=20 > /** 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]; > }; >=20 > +#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 >=20 > @@ -383,6 +443,13 @@ struct token { > .size =3D (s), \ > }) >=20 > +#define ARGS_ENTRY_ARB_HTON(o, s) \ > + (&(const struct arg){ \ > + .hton =3D 1, \ > + .offset =3D (o), \ > + .size =3D (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[] =3D { > 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, > }; >=20 > @@ -874,6 +945,44 @@ static const enum index action_jump[] =3D { > ZERO, > }; >=20 > +static const enum index action_vxlan_encap[] =3D { > + 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[] =3D { > + ACTION_NEXT, > + ZERO, > +}; > + > +static const enum index action_nvgre_encap[] =3D { > + 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[] =3D { > + 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 contex= t *, > const struct token *, > const char *, unsigned int, void *, > unsigned int); > +static int parse_vc_action_vxlan_encap(struct context *, const struct to= ken *, > + const char *, unsigned int, void *, > + unsigned int); > +static int parse_vc_action_vxlan_decap(struct context *, const struct to= ken *, > + 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 to= ken *, > + const char *, unsigned int, void *, > + unsigned int); > +static int parse_vc_action_nvgre_decap(struct context *, const struct to= ken *, > + 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[] =3D { > ethertype)), > .call =3D parse_vc_conf, > }, > + [ACTION_VXLAN_ENCAP] =3D { > + .name =3D "vxlan_encap", > + .help =3D "encap flow with vxlan tunnel definition", > + .priv =3D PRIV_ACTION(VXLAN_ENCAP, > + sizeof(struct action_vxlan_encap_data)), > + .next =3D 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 =3D parse_vc_action_vxlan_encap, > + }, > + [ACTION_VXLAN_DECAP] =3D { > + .name =3D "vxlan_decap", > + .help =3D "decap flow with vxlan tunnel definition", > + .priv =3D PRIV_ACTION(VXLAN_DECAP, 0), > + .next =3D NEXT(action_vxlan_decap), > + .call =3D parse_vc_action_vxlan_decap, > + }, > + [ACTION_VXLAN_ENCAP_ETH_DST] =3D { > + .name =3D "eth_dst", > + .help =3D "destination MAC for vxlan tunnel", > + .next =3D NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_DST_VALUE)), > + .call =3D parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_ETH_DST_VALUE] =3D { > + .name =3D "eth_dst_value", > + .help =3D "destination MAC for vxlan tunnel", > + .call =3D parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_ETH_SRC] =3D { > + .name =3D "eth_src", > + .help =3D "source MAC for vxlan tunnel", > + .next =3D NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_SRC_VALUE)), > + .call =3D parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_ETH_SRC_VALUE] =3D { > + .name =3D "eth_src_value", > + .help =3D "source MAC for vxlan tunnel", > + .call =3D parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_ETH_TYPE] =3D { > + .name =3D "eth_type", > + .help =3D "eth type for vxlan tunnel", > + .next =3D NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE)), > + .call =3D parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE] =3D { > + .name =3D "eth_type_value", > + .help =3D "eth type for vxlan tunnel", > + .call =3D parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_DST] =3D { > + .name =3D "ipv4_dst", > + .help =3D "destination ipv4 IP for vxlan tunnel", > + .next =3D NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_DST_VALUE)), > + .call =3D parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_DST_VALUE] =3D { > + .name =3D "ipv4_dst_value", > + .help =3D "destination ipv4 IP for vxlan tunnel", > + .call =3D parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_SRC] =3D { > + .name =3D "ipv4_src", > + .help =3D "source ipv4 IP for vxlan tunnel", > + .next =3D NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE)), > + .call =3D parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_SRC_VALUE] =3D { > + .name =3D "ipv4_src_value", > + .help =3D "source ipv4 IP for vxlan tunnel", > + .call =3D parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_PROTO] =3D { > + .name =3D "ipv4_proto", > + .help =3D "ipv4 proto for vxlan tunnel", > + .next =3D NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE)), > + .call =3D parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_IPV4_PROTO_VALUE] =3D { > + .name =3D "ipv4_proto_value", > + .help =3D "ipv4 proto for vxlan tunnel", > + .call =3D parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_UDP_DST] =3D { > + .name =3D "udp_dst", > + .help =3D "udp destination port for vxlan tunnel", > + .next =3D NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_DST_VALUE)), > + .call =3D parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_UDP_DST_VALUE] =3D { > + .name =3D "udp_dst_value", > + .help =3D "udp destination port for vxlan tunnel", > + .call =3D parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_UDP_SRC] =3D { > + .name =3D "udp_src", > + .help =3D "udp source port for vxlan tunnel", > + .next =3D NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_UDP_SRC_VALUE)), > + .call =3D parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_UDP_SRC_VALUE] =3D { > + .name =3D "udp_src_value", > + .help =3D "udp source port for vxlan tunnel", > + .call =3D parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_VXLAN_VNI] =3D { > + .name =3D "vxlan_vni", > + .help =3D "vxlan vni for vxlan tunnel", > + .next =3D NEXT(action_vxlan_encap, > + > NEXT_ENTRY(ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE)), > + .call =3D parse_vc_action_vxlan_encap_fields, > + }, > + [ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE] =3D { > + .name =3D "vxlan_vni_value", > + .help =3D "vxlan vni for vxlan tunnel", > + .call =3D parse_vc_action_vxlan_encap_fields_value, > + }, > + [ACTION_VXLAN_ENCAP_END] =3D { > + .name =3D "end", > + .help =3D "end of the pattern for vxlan encap", > + .call =3D parse_vc_action_vxlan_encap_end, "end" only is being parsed, could ACTION_END be used instead? > + }, > + [ACTION_NVGRE_ENCAP] =3D { > + .name =3D "nvgre_encap", > + .help =3D "encap flow with nvgre tunnel definition", > + .priv =3D PRIV_ACTION(NVGRE_ENCAP, > + sizeof(struct action_nvgre_encap_data)), > + .next =3D 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 =3D parse_vc_action_nvgre_encap, > + }, > + [ACTION_NVGRE_DECAP] =3D { > + .name =3D "nvgre_decap", > + .help =3D "decap flow with nvgre tunnel definition", > + .priv =3D PRIV_ACTION(NVGRE_DECAP, 0), > + .next =3D NEXT(action_nvgre_decap), > + .call =3D parse_vc_action_nvgre_decap, > + }, > + [ACTION_NVGRE_ENCAP_ETH_DST] =3D { > + .name =3D "eth_dst", > + .help =3D "destination MAC for nvgre tunnel", > + .next =3D NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_DST_VALUE)), > + .call =3D parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_ETH_DST_VALUE] =3D { > + .name =3D "eth_dst_value", > + .help =3D "destination MAC for nvgre tunnel", > + .call =3D parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_ETH_SRC] =3D { > + .name =3D "eth_src", > + .help =3D "source MAC for nvgre tunnel", > + .next =3D NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_SRC_VALUE)), > + .call =3D parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_ETH_SRC_VALUE] =3D { > + .name =3D "eth_src_value", > + .help =3D "source MAC for nvgre tunnel", > + .call =3D parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_ETH_TYPE] =3D { > + .name =3D "eth_type", > + .help =3D "eth type for nvgre tunnel", > + .next =3D NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE)), > + .call =3D parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE] =3D { > + .name =3D "eth_type_value", > + .help =3D "eth type for nvgre tunnel", > + .call =3D parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_DST] =3D { > + .name =3D "ipv4_dst", > + .help =3D "destination ipv4 IP for nvgre tunnel", > + .next =3D NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_DST_VALUE)), > + .call =3D parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_DST_VALUE] =3D { > + .name =3D "ipv4_dst_value", > + .help =3D "destination ipv4 IP for nvgre tunnel", > + .call =3D parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_SRC] =3D { > + .name =3D "ipv4_src", > + .help =3D "source ipv4 IP for nvgre tunnel", > + .next =3D NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE)), > + .call =3D parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_SRC_VALUE] =3D { > + .name =3D "ipv4_src_value", > + .help =3D "source ipv4 IP for nvgre tunnel", > + .call =3D parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_PROTO] =3D { > + .name =3D "ipv4_proto", > + .help =3D "ipv4 proto for nvgre tunnel", > + .next =3D NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE)), > + .call =3D parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_IPV4_PROTO_VALUE] =3D { > + .name =3D "ipv4_proto_value", > + .help =3D "ipv4 proto for nvgre tunnel", > + .call =3D parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_NVGRE_VSNI] =3D { > + .name =3D "nvgre_vsni", > + .help =3D "nvgre vsni for NVGRE tunnel", > + .next =3D NEXT(action_nvgre_encap, > + > NEXT_ENTRY(ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE)), > + .call =3D parse_vc_action_nvgre_encap_fields, > + }, > + [ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE] =3D { > + .name =3D "nvgre_vsni_value", > + .help =3D "nvgre vsni for nvgre tunnel", > + .call =3D parse_vc_action_nvgre_encap_fields_value, > + }, > + [ACTION_NVGRE_ENCAP_END] =3D { > + .name =3D "end", > + .help =3D "end of the pattern for nvgre encap", > + .call =3D parse_vc_action_nvgre_encap_end, "end" only is being parsed, could ACTION_END be used instead? > + }, > }; >=20 > /** 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; > } >=20 > +/** Parse VXLAN_ENCAP action. */ > +static int > +parse_vc_action_vxlan_encap(struct context *ctx, const struct token *tok= en, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct buffer *out =3D buf; > + struct rte_flow_action *action; > + struct action_vxlan_encap_data *data; > + int ret; > + > + ret =3D 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 =3D &out->args.vc.actions[out->args.vc.actions_n - 1]; > + /* Point to selected object. */ > + ctx->object =3D out->args.vc.data; > + ctx->objmask =3D NULL; > + /* Set up default configuration. */ > + data =3D ctx->object; > + data->conf.definition =3D data->pattern; > + action->conf =3D &data->conf; > + > + return ret; > +} > + > +/** Parse VXLAN_DECAP action. */ > +static int > +parse_vc_action_vxlan_decap(struct context *ctx, const struct token *tok= en, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct buffer *out =3D buf; > + int ret; > + > + ret =3D 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 =3D out->args.vc.data; > + ctx->objmask =3D NULL; > + return ret; > +} > + > +static uint32_t get_proto_index_using_flag(uint32_t flag) { > + uint32_t c =3D 0, i =3D 0; > + uint32_t supported_ptypes[] =3D { > + 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 =3D 0; i !=3D RTE_DIM(supported_ptypes); i++) { > + if (supported_ptypes[i] & flag) > + c++; > + } > + c =3D (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 =3D ctx->object; > + data->hdr_flags |=3D RTE_PTYPE_L2_ETHER; > + p_index =3D get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec =3D &data->eth; > + data->pattern[p_index].mask =3D &rte_flow_item_eth_mask; > + data->pattern[p_index].type =3D 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 =3D ctx->object; > + data->hdr_flags |=3D RTE_PTYPE_L3_IPV4; > + p_index =3D get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec =3D &data->ipv4; > + data->pattern[p_index].mask =3D &rte_flow_item_ipv4_mask; > + data->pattern[p_index].type =3D RTE_FLOW_ITEM_TYPE_IPV4; > + break; > + case ACTION_VXLAN_ENCAP_UDP_DST: > + case ACTION_VXLAN_ENCAP_UDP_SRC: > + data =3D ctx->object; > + data->hdr_flags |=3D RTE_PTYPE_L4_UDP; > + p_index =3D get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec =3D &data->udp; > + data->pattern[p_index].mask =3D &rte_flow_item_udp_mask; > + data->pattern[p_index].type =3D RTE_FLOW_ITEM_TYPE_UDP; > + break; > + case ACTION_VXLAN_ENCAP_VXLAN_VNI: > + data =3D ctx->object; > + data->hdr_flags |=3D RTE_PTYPE_TUNNEL_VXLAN; > + p_index =3D get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec =3D &data->vxlan; > + data->pattern[p_index].mask =3D &rte_flow_item_vxlan_mask; > + data->pattern[p_index].type =3D 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 =3D ctx->object; > + switch (ctx->curr) { > + case ACTION_VXLAN_ENCAP_ETH_DST_VALUE: > + ret =3D cmdline_parse_etheraddr(NULL, str, &mac, size); > + if (ret < 0 || (unsigned int)ret !=3D len) > + return -1; > + memcpy(&data->eth.dst, &mac, sizeof(mac)); > + break; > + case ACTION_VXLAN_ENCAP_ETH_SRC_VALUE: > + ret =3D cmdline_parse_etheraddr(NULL, str, &mac, size); > + if (ret < 0 || (unsigned int)ret !=3D len) > + return -1; > + memcpy(&data->eth.src, &mac, sizeof(mac)); > + break; > + case ACTION_VXLAN_ENCAP_ETH_TYPE_VALUE: > + memcpy(str2, str, len); > + str2[len] =3D '\0'; > + val1 =3D strtoul(str2, NULL, 0); > + if (val1 =3D=3D 0) > + return -1; > + data->eth.type =3D htons(val1); > + break; > + case ACTION_VXLAN_ENCAP_IPV4_DST_VALUE: > + memcpy(str2, str, len); > + str2[len] =3D '\0'; > + ret =3D inet_pton(AF_INET, str2, &ip4); > + if (ret !=3D 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] =3D '\0'; > + ret =3D inet_pton(AF_INET, str2, &ip4); > + if (ret !=3D 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] =3D '\0'; > + val1 =3D strtoul(str2, NULL, 0); > + if (val1 =3D=3D 0) > + return -1; > + data->ipv4.hdr.next_proto_id =3D val1; > + break; > + case ACTION_VXLAN_ENCAP_UDP_DST_VALUE: > + memcpy(str2, str, len); > + str2[len] =3D '\0'; > + val1 =3D strtoul(str2, NULL, 0); > + if (val1 =3D=3D 0) > + return -1; > + data->udp.hdr.dst_port =3D htons(val1); > + break; > + case ACTION_VXLAN_ENCAP_UDP_SRC_VALUE: > + memcpy(str2, str, len); > + str2[len] =3D '\0'; > + val1 =3D strtoul(str2, NULL, 0); > + if (val1 =3D=3D 0) > + return -1; > + data->udp.hdr.src_port =3D htons(val1); > + break; > + case ACTION_VXLAN_ENCAP_VXLAN_VNI_VALUE: > + memcpy(str2, str, len); > + str2[len] =3D '\0'; > + val2 =3D strtoul(str2, NULL, 0); > + if (val2 =3D=3D 0) > + return -1; > + data->vxlan.vni[0] =3D (uint8_t)((val2 >> 16) & 0xff); > + data->vxlan.vni[1] =3D (uint8_t)((val2 >> 8) & 0xff); > + data->vxlan.vni[2] =3D (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 !=3D ACTION_VXLAN_ENCAP_END) > + return -1; > + if (!ctx->object) > + return len; > + data =3D ctx->object; > + p_index =3D get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index + 1].type =3D RTE_FLOW_ITEM_TYPE_END; > + > + return len; > +} > + > +/** Parse NVGRE_ENCAP action. */ > +static int > +parse_vc_action_nvgre_encap(struct context *ctx, const struct token *tok= en, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct buffer *out =3D buf; > + struct rte_flow_action *action; > + struct action_nvgre_encap_data *data; > + int ret; > + > + ret =3D 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 =3D &out->args.vc.actions[out->args.vc.actions_n - 1]; > + /* Point to selected object. */ > + ctx->object =3D out->args.vc.data; > + ctx->objmask =3D NULL; > + /* Set up default configuration. */ > + data =3D ctx->object; > + data->conf.definition =3D data->pattern; > + action->conf =3D &data->conf; > + > + return ret; > +} > + > +/** Parse NVGRE_DECAP action. */ > +static int > +parse_vc_action_nvgre_decap(struct context *ctx, const struct token *tok= en, > + const char *str, unsigned int len, > + void *buf, unsigned int size) > +{ > + struct buffer *out =3D buf; > + int ret; > + > + ret =3D 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 =3D out->args.vc.data; > + ctx->objmask =3D 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 =3D ctx->object; > + data->hdr_flags |=3D RTE_PTYPE_L2_ETHER; > + p_index =3D get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec =3D &data->eth; > + data->pattern[p_index].mask =3D &rte_flow_item_eth_mask; > + data->pattern[p_index].type =3D 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 =3D ctx->object; > + data->hdr_flags |=3D RTE_PTYPE_L3_IPV4; > + p_index =3D get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec =3D &data->ipv4; > + data->pattern[p_index].mask =3D &rte_flow_item_ipv4_mask; > + data->pattern[p_index].type =3D RTE_FLOW_ITEM_TYPE_IPV4; > + break; > + case ACTION_NVGRE_ENCAP_NVGRE_VSNI: > + data =3D ctx->object; > + data->hdr_flags |=3D RTE_PTYPE_TUNNEL_NVGRE; > + p_index =3D get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index].spec =3D &data->nvgre; > + data->pattern[p_index].mask =3D &rte_flow_item_nvgre_mask; > + data->pattern[p_index].type =3D 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 =3D ctx->object; > + switch (ctx->curr) { > + case ACTION_NVGRE_ENCAP_ETH_DST_VALUE: > + ret =3D cmdline_parse_etheraddr(NULL, str, &mac, size); > + if (ret < 0 || (unsigned int)ret !=3D len) > + return -1; > + memcpy(&data->eth.dst, &mac, sizeof(mac)); > + break; > + case ACTION_NVGRE_ENCAP_ETH_SRC_VALUE: > + ret =3D cmdline_parse_etheraddr(NULL, str, &mac, size); > + if (ret < 0 || (unsigned int)ret !=3D len) > + return -1; > + memcpy(&data->eth.src, &mac, sizeof(mac)); > + break; > + case ACTION_NVGRE_ENCAP_ETH_TYPE_VALUE: > + memcpy(str2, str, len); > + str2[len] =3D '\0'; > + val1 =3D strtoul(str2, NULL, 0); > + if (val1 =3D=3D 0) > + return -1; > + data->eth.type =3D htons(val1); > + break; > + case ACTION_NVGRE_ENCAP_IPV4_DST_VALUE: > + memcpy(str2, str, len); > + str2[len] =3D '\0'; > + ret =3D inet_pton(AF_INET, str2, &ip4); > + if (ret !=3D 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] =3D '\0'; > + ret =3D inet_pton(AF_INET, str2, &ip4); > + if (ret !=3D 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] =3D '\0'; > + val1 =3D strtoul(str2, NULL, 0); > + if (val1 =3D=3D 0) > + return -1; > + data->ipv4.hdr.next_proto_id =3D val1; > + break; > + case ACTION_NVGRE_ENCAP_NVGRE_VSNI_VALUE: > + memcpy(str2, str, len); > + str2[len] =3D '\0'; > + val2 =3D strtoul(str2, NULL, 0); > + if (val2 =3D=3D 0) > + return -1; > + data->nvgre.tni[0] =3D (uint8_t)((val2 >> 16) & 0xff); > + data->nvgre.tni[1] =3D (uint8_t)((val2 >> 8) & 0xff); > + data->nvgre.tni[2] =3D (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 !=3D ACTION_NVGRE_ENCAP_END) > + return -1; > + if (!ctx->object) > + return len; > + data =3D ctx->object; > + p_index =3D get_proto_index_using_flag(data->hdr_flags); > + data->pattern[p_index + 1].type =3D RTE_FLOW_ITEM_TYPE_END; > + > + return len; > +} > + > /** Parse tokens for destroy command. */ static int parse_destroy(stru= ct > context *ctx, const struct token *token, @@ -2961,6 +3832,7 @@ > parse_destroy(struct context *ctx, const struct token *token, > return len; > } >=20 > + 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 m= anagement. dpdk/build/doc/html/guides/testpmd_app_ug/index.html As the encap and decap flows are fairly complex, It might be worth adding s= ections on Sample Encap flow rules and Sample Decap flow rules. Regards, Bernard.