From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id 1E04B1252 for ; Mon, 18 Jun 2018 14:48:02 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 18 Jun 2018 05:48:02 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,239,1526367600"; d="scan'208";a="238410726" Received: from awalabdu-mobl.ger.corp.intel.com (HELO [163.33.228.61]) ([163.33.228.61]) by fmsmga006.fm.intel.com with ESMTP; 18 Jun 2018 05:48:01 -0700 To: Nelio Laranjeiro , dev@dpdk.org, Adrien Mazarguil , Wenzhuo Lu , Jingjing Wu , Bernard Iremonger References: <21ca48586731df9b48c3b3f550dd022320afc450.1529311723.git.nelio.laranjeiro@6wind.com> From: Mohammad Abdul Awal Message-ID: <1ad6301b-3887-8bcb-7a61-7a74ace7e482@intel.com> Date: Mon, 18 Jun 2018 13:48:00 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: <21ca48586731df9b48c3b3f550dd022320afc450.1529311723.git.nelio.laranjeiro@6wind.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US Subject: Re: [dpdk-dev] [PATCH v2 2/2] app/testpmd: add NVGRE encap/decap support 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: Mon, 18 Jun 2018 12:48:03 -0000 On 18/06/2018 09:52, Nelio Laranjeiro wrote: > Due to the complex NVGRE_ENCAP flow action and based on the fact testpmd > does not allocate memory, this patch adds a new command in testpmd to > initialise a global structure containing the necessary information to > make the outer layer of the packet. This same global structure will > then be used by the flow command line in testpmd when the action > nvgre_encap will be parsed, at this point, the conversion into such > action becomes trivial. > > This global structure is only used for the encap action. > > Signed-off-by: Nelio Laranjeiro > --- > app/test-pmd/cmdline.c | 79 +++++++++++++ > app/test-pmd/cmdline_flow.c | 119 ++++++++++++++++++++ > app/test-pmd/testpmd.c | 13 +++ > app/test-pmd/testpmd.h | 13 +++ > doc/guides/testpmd_app_ug/testpmd_funcs.rst | 13 +++ > 5 files changed, 237 insertions(+) > > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c > index a3b98b2f2..7ea1e5792 100644 > --- a/app/test-pmd/cmdline.c > +++ b/app/test-pmd/cmdline.c > @@ -785,6 +785,9 @@ static void cmd_help_long_parsed(void *parsed_result, > " eth-src eth-dst\n" > " Configure the VXLAN encapsulation for flows.\n\n" > > + "nvgre ipv4|ipv6 tni ip-src ip-dst eth-src eth-dst\n" > + " Configure the NVGRE encapsulation for flows.\n\n" Should there be support for outer VLAN header according to the definitions? > + > , list_pkt_forwarding_modes() > ); > } > @@ -14927,6 +14930,81 @@ cmdline_parse_inst_t cmd_set_vxlan = { > }, > }; > > +/** Set NVGRE encapsulation details */ > +struct cmd_set_nvgre_result { > + cmdline_fixed_string_t set; > + cmdline_fixed_string_t nvgre; > + cmdline_fixed_string_t ip_version; > + uint32_t tni; > + cmdline_ipaddr_t ip_src; > + cmdline_ipaddr_t ip_dst; > + struct ether_addr eth_src; > + struct ether_addr eth_dst; > +}; > + > +cmdline_parse_token_string_t cmd_set_nvgre_set = > + TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, set, "set"); > +cmdline_parse_token_string_t cmd_set_nvgre_nvgre = > + TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, nvgre, "nvgre"); > +cmdline_parse_token_string_t cmd_set_nvgre_ip_version = > + TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, ip_version, > + "ipv4#ipv6"); > +cmdline_parse_token_num_t cmd_set_nvgre_tni = > + TOKEN_NUM_INITIALIZER(struct cmd_set_nvgre_result, tni, UINT32); > +cmdline_parse_token_num_t cmd_set_nvgre_ip_src = > + TOKEN_IPADDR_INITIALIZER(struct cmd_set_nvgre_result, ip_src); > +cmdline_parse_token_ipaddr_t cmd_set_nvgre_ip_dst = > + TOKEN_IPADDR_INITIALIZER(struct cmd_set_nvgre_result, ip_dst); > +cmdline_parse_token_etheraddr_t cmd_set_nvgre_eth_src = > + TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_nvgre_result, eth_src); > +cmdline_parse_token_etheraddr_t cmd_set_nvgre_eth_dst = > + TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_nvgre_result, eth_dst); > + > +static void cmd_set_nvgre_parsed(void *parsed_result, > + __attribute__((unused)) struct cmdline *cl, > + __attribute__((unused)) void *data) > +{ > + struct cmd_set_nvgre_result *res = parsed_result; > + uint32_t tni = rte_cpu_to_be_32(res->tni) >> 8; > + > + if (strcmp(res->ip_version, "ipv4") == 0) > + nvgre_encap_conf.select_ipv4 = 1; > + else if (strcmp(res->ip_version, "ipv6") == 0) > + nvgre_encap_conf.select_ipv4 = 0; > + else > + return; > + memcpy(nvgre_encap_conf.tni, &tni, 3); > + if (nvgre_encap_conf.select_ipv4) { > + IPV4_ADDR_TO_UINT(res->ip_src, nvgre_encap_conf.ipv4_src); > + IPV4_ADDR_TO_UINT(res->ip_dst, nvgre_encap_conf.ipv4_dst); > + } else { > + IPV6_ADDR_TO_ARRAY(res->ip_src, nvgre_encap_conf.ipv6_src); > + IPV6_ADDR_TO_ARRAY(res->ip_dst, nvgre_encap_conf.ipv6_dst); > + } > + memcpy(nvgre_encap_conf.eth_src, res->eth_src.addr_bytes, > + ETHER_ADDR_LEN); > + memcpy(nvgre_encap_conf.eth_dst, res->eth_dst.addr_bytes, > + ETHER_ADDR_LEN); > +} > + > +cmdline_parse_inst_t cmd_set_nvgre = { > + .f = cmd_set_nvgre_parsed, > + .data = NULL, > + .help_str = "set nvgre ipv4|ipv6 " > + " ", > + .tokens = { > + (void *)&cmd_set_nvgre_set, > + (void *)&cmd_set_nvgre_nvgre, > + (void *)&cmd_set_nvgre_ip_version, > + (void *)&cmd_set_nvgre_tni, > + (void *)&cmd_set_nvgre_ip_src, > + (void *)&cmd_set_nvgre_ip_dst, > + (void *)&cmd_set_nvgre_eth_src, > + (void *)&cmd_set_nvgre_eth_dst, > + NULL, > + }, > +}; > + > /* Strict link priority scheduling mode setting */ > static void > cmd_strict_link_prio_parsed( > @@ -17552,6 +17630,7 @@ cmdline_parse_ctx_t main_ctx[] = { > (cmdline_parse_inst_t *)&cmd_set_port_tm_hierarchy_default, > #endif > (cmdline_parse_inst_t *)&cmd_set_vxlan, > + (cmdline_parse_inst_t *)&cmd_set_nvgre, > (cmdline_parse_inst_t *)&cmd_ddp_add, > (cmdline_parse_inst_t *)&cmd_ddp_del, > (cmdline_parse_inst_t *)&cmd_ddp_get_list, > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c > index 4f4aba407..7fd5468a8 100644 > --- a/app/test-pmd/cmdline_flow.c > +++ b/app/test-pmd/cmdline_flow.c > @@ -241,6 +241,8 @@ enum index { > ACTION_OF_PUSH_MPLS_ETHERTYPE, > ACTION_VXLAN_ENCAP, > ACTION_VXLAN_DECAP, > + ACTION_NVGRE_ENCAP, > + ACTION_NVGRE_DECAP, > }; > > /** Maximum size for pattern in struct rte_flow_item_raw. */ > @@ -276,6 +278,21 @@ struct action_vxlan_encap_data { > struct rte_flow_item_vxlan item_vxlan; > }; > > +/** Maximum number of items in struct rte_flow_action_nvgre_encap. */ > +#define ACTION_NVGRE_ENCAP_ITEMS_NUM 4 > + > +/** Storage for struct rte_flow_action_nvgre_encap including external data. */ > +struct action_nvgre_encap_data { > + struct rte_flow_action_nvgre_encap conf; > + struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM]; > + struct rte_flow_item_eth item_eth; > + union { > + struct rte_flow_item_ipv4 item_ipv4; > + struct rte_flow_item_ipv6 item_ipv6; > + }; > + struct rte_flow_item_nvgre item_nvgre; > +}; > + > /** Maximum number of subsequent tokens and arguments on the stack. */ > #define CTX_STACK_SIZE 16 > > @@ -795,6 +812,8 @@ static const enum index next_action[] = { > ACTION_OF_PUSH_MPLS, > ACTION_VXLAN_ENCAP, > ACTION_VXLAN_DECAP, > + ACTION_NVGRE_ENCAP, > + ACTION_NVGRE_DECAP, > ZERO, > }; > > @@ -928,6 +947,9 @@ static int parse_vc_action_rss_queue(struct context *, const struct token *, > static int parse_vc_action_vxlan_encap(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_destroy(struct context *, const struct token *, > const char *, unsigned int, > void *, unsigned int); > @@ -2428,6 +2450,24 @@ static const struct token token_list[] = { > .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), > .call = parse_vc, > }, > + [ACTION_NVGRE_ENCAP] = { > + .name = "nvgre_encap", > + .help = "NVGRE encapsulation, uses configuration set by \"set" > + " nvgre\"", > + .priv = PRIV_ACTION(NVGRE_ENCAP, > + sizeof(struct action_nvgre_encap_data)), > + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), > + .call = parse_vc_action_nvgre_encap, > + }, > + [ACTION_NVGRE_DECAP] = { > + .name = "nvgre_decap", > + .help = "Performs a decapsulation action by stripping all" > + " headers of the NVGRE tunnel network overlay from the" > + " matched flow.", > + .priv = PRIV_ACTION(NVGRE_DECAP, 0), > + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), > + .call = parse_vc, > + }, > }; > > /** Remove and return last entry from argument stack. */ > @@ -3080,6 +3120,85 @@ parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token, > return ret; > } > > +/** 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 *action_nvgre_encap_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. */ > + action_nvgre_encap_data = ctx->object; > + *action_nvgre_encap_data = (struct action_nvgre_encap_data){ > + .conf = (struct rte_flow_action_nvgre_encap){ > + .definition = action_nvgre_encap_data->items, > + }, > + .items = { > + { > + .type = RTE_FLOW_ITEM_TYPE_ETH, > + .spec = &action_nvgre_encap_data->item_eth, > + .mask = &action_nvgre_encap_data->item_eth, > + }, > + { > + .type = RTE_FLOW_ITEM_TYPE_IPV4, > + .spec = &action_nvgre_encap_data->item_ipv4, > + .mask = &action_nvgre_encap_data->item_ipv4, > + }, > + { > + .type = RTE_FLOW_ITEM_TYPE_NVGRE, > + .spec = &action_nvgre_encap_data->item_nvgre, > + .mask = &action_nvgre_encap_data->item_nvgre, > + }, > + { > + .type = RTE_FLOW_ITEM_TYPE_END, > + }, > + }, > + .item_eth = { .type = 0, }, > + .item_ipv4.hdr = { > + .src_addr = nvgre_encap_conf.ipv4_src, > + .dst_addr = nvgre_encap_conf.ipv4_dst, > + }, > + .item_nvgre.flow_id = 0, > + }; > + memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes, > + nvgre_encap_conf.eth_dst, ETHER_ADDR_LEN); > + memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes, > + nvgre_encap_conf.eth_src, ETHER_ADDR_LEN); > + if (!nvgre_encap_conf.select_ipv4) { > + memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr, > + &nvgre_encap_conf.ipv6_src, > + sizeof(nvgre_encap_conf.ipv6_src)); > + memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr, > + &nvgre_encap_conf.ipv6_dst, > + sizeof(nvgre_encap_conf.ipv6_dst)); > + action_nvgre_encap_data->items[1] = (struct rte_flow_item){ > + .type = RTE_FLOW_ITEM_TYPE_IPV6, > + .spec = &action_nvgre_encap_data->item_ipv6, > + .mask = &action_nvgre_encap_data->item_ipv6, > + }; > + } > + memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni, > + RTE_DIM(nvgre_encap_conf.tni)); > + action->conf = &action_nvgre_encap_data->conf; > + return ret; > +} > + > /** Parse tokens for destroy command. */ > static int > parse_destroy(struct context *ctx, const struct token *token, > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c > index 1c68c9d30..97b4c4f9c 100644 > --- a/app/test-pmd/testpmd.c > +++ b/app/test-pmd/testpmd.c > @@ -408,6 +408,19 @@ struct vxlan_encap_conf vxlan_encap_conf = { > .eth_dst = "\xff\xff\xff\xff\xff\xff", > }; > > +struct nvgre_encap_conf nvgre_encap_conf = { > + .select_ipv4 = 1, > + .tni = "\x00\x00\x00", > + .ipv4_src = IPv4(127, 0, 0, 1), > + .ipv4_dst = IPv4(255, 255, 255, 255), > + .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00" > + "\x00\x00\x00\x00\x00\x00\x00\x01", > + .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00" > + "\x00\x00\x00\x00\x00\x00\x11\x11", > + .eth_src = "\x00\x00\x00\x00\x00\x00", > + .eth_dst = "\xff\xff\xff\xff\xff\xff", > +}; > + > /* Forward function declarations */ > static void map_port_queue_stats_mapping_registers(portid_t pi, > struct rte_port *port); > diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h > index 72c4e8d54..7871b93e1 100644 > --- a/app/test-pmd/testpmd.h > +++ b/app/test-pmd/testpmd.h > @@ -494,6 +494,19 @@ struct vxlan_encap_conf { > }; > struct vxlan_encap_conf vxlan_encap_conf; > > +/* NVGRE encap/decap parameters. */ > +struct nvgre_encap_conf { > + uint32_t select_ipv4:1; > + uint8_t tni[3]; > + rte_be32_t ipv4_src; > + rte_be32_t ipv4_dst; > + uint8_t ipv6_src[16]; > + uint8_t ipv6_dst[16]; > + uint8_t eth_src[ETHER_ADDR_LEN]; > + uint8_t eth_dst[ETHER_ADDR_LEN]; > +}; > +struct nvgre_encap_conf nvgre_encap_conf; > + > static inline unsigned int > lcore_num(void) > { > diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst > index 162d1c535..59f5f6dad 100644 > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst > @@ -1541,6 +1541,13 @@ Configure the outer layer to encapsulate a packet inside a VXLAN tunnel:: > > testpmd> set vxlan ipv4|ipv6 (udp-src) (udp-dst) (ip-src) (ip-dst) (mac-src) (mac-dst) > > +Config NVGRE Encap outer layers > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + > +Configure the outer layer to encapsulate a packet inside a NVGRE tunnel:: > + > + testpmd> set nvgre ipv4|ipv6 (ip-src) (ip-dst) (mac-src) (mac-dst)                                                              ^^^^^^                                                          nvgre tni is missing? Also the VLAN tag id? > + > Port Functions > -------------- > > @@ -3662,6 +3669,12 @@ This section lists supported actions and their attributes, if any. > - ``vxlan_decap``: Performs a decapsulation action by stripping all headers of > the VXLAN tunnel network overlay from the matched flow. > > +- ``nvgre_encap``: Performs a NVGRE encapsulation, outer layer configuration > + is done through `Config NVGRE Encap outer layers`_. > + > +- ``nvgre_decap``: Performs a decapsulation action by stripping all headers of > + the NVGRE tunnel network overlay from the matched flow. > + > Destroying flow rules > ~~~~~~~~~~~~~~~~~~~~~ >