From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 29DD0A04A2; Fri, 4 Feb 2022 20:59:32 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6297E40E03; Fri, 4 Feb 2022 20:59:23 +0100 (CET) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mails.dpdk.org (Postfix) with ESMTP id 9887340687 for ; Fri, 4 Feb 2022 20:59:20 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1644004760; x=1675540760; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9PzES4VDbCsmipFpAm8HXm62Iz34eQ2L9yXVolAbKKo=; b=RHDNqmrTQtUEanrtG+W140rwV05UJ/GtvEwybmxRkLxJtlZtfq2o58Ik O3ooZg+HIKsFE4s+Kzh0c0HgT69VfUHkz+KpYdnMIFE5IEc1S9yyY28xU WBn6ta8doOVhq3LHC/At6qf0aC2//TPp/xZBS7E2rcTtXFNrPwo5cepvW 23PXcn24ahNfdP4Kz1BvQ7+klgLTOtWDxeK7VqYCAWXKntkWbfKSigKtG 2DkzR1m5f8gii8ZsnlfK4IXSqQqc6t+7cDZfW2ZkQ+j9wtGR39detZqKb rPQzFQisX6zP5mKk01yPptt7fx5Y7Ru4HZ0Y/wYEeqpbGQEj4fk7OLYlj Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10248"; a="231999782" X-IronPort-AV: E=Sophos;i="5.88,343,1635231600"; d="scan'208";a="231999782" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Feb 2022 11:59:20 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,343,1635231600"; d="scan'208";a="566843363" Received: from silpixa00401215.ir.intel.com ([10.55.128.96]) by orsmga001.jf.intel.com with ESMTP; 04 Feb 2022 11:59:18 -0800 From: Sean Morrissey To: Cc: dev@dpdk.org, Sean Morrissey , Konstantin Ananyev Subject: [PATCH v5 2/2] examples/l3fwd: add config file support for EM Date: Fri, 4 Feb 2022 19:59:05 +0000 Message-Id: <20220204195905.449192-3-sean.morrissey@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220204195905.449192-1-sean.morrissey@intel.com> References: <20220126124459.2469838-1-sean.morrissey@intel.com> <20220204195905.449192-1-sean.morrissey@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add support to define ipv4 and ipv6 forwarding tables from reading from a config file for EM with a format similar to l3fwd-acl one. Users can now use the default hardcoded route tables or optionally config files for 'l3fwd_em'. Default config files have been provided for use with EM. Related l3fwd docs have been updated to relfect these changes. Signed-off-by: Sean Morrissey Acked-by: Konstantin Ananyev --- doc/guides/sample_app_ug/l3_forward.rst | 89 +++-- examples/l3fwd/em_default_v4.cfg | 17 + examples/l3fwd/em_default_v6.cfg | 17 + examples/l3fwd/l3fwd_em.c | 468 +++++++++++++++++------- examples/l3fwd/l3fwd_route.h | 24 ++ 5 files changed, 459 insertions(+), 156 deletions(-) create mode 100644 examples/l3fwd/em_default_v4.cfg create mode 100644 examples/l3fwd/em_default_v6.cfg diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst index 6d7d7c5cc1..01d86db95d 100644 --- a/doc/guides/sample_app_ug/l3_forward.rst +++ b/doc/guides/sample_app_ug/l3_forward.rst @@ -47,6 +47,7 @@ and loaded into the LPM or FIB object at initialization time. In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only. +During the initialization phase route rules for IPv4 and IPv6 are read from rule files. Compiling the Application ------------------------- @@ -61,6 +62,8 @@ Running the Application The application has a number of command line options:: ./dpdk-l3fwd [EAL options] -- -p PORTMASK + --rule_ipv4=FILE + --rule_ipv6=FILE [-P] [--lookup LOOKUP_METHOD] --config(port,queue,lcore)[,(port,queue,lcore)] @@ -82,6 +85,11 @@ Where, * ``-p PORTMASK:`` Hexadecimal bitmask of ports to configure +* ``--rule_ipv4=FILE:`` specify the ipv4 rules entries file. + Each rule occupies one line. + +* ``--rule_ipv6=FILE:`` specify the ipv6 rules entries file. + * ``-P:`` Optional, sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address. Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted. @@ -135,7 +143,7 @@ To enable L3 forwarding between two ports, assuming that both ports are in the s .. code-block:: console - .//examples/dpdk-l3fwd -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" + .//examples/dpdk-l3fwd -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --rule_ipv4="rule_ipv4.cfg" --rule_ipv6="rule_ipv6.cfg" In this command: @@ -157,19 +165,23 @@ In this command: | | | | | +----------+-----------+-----------+-------------------------------------+ +* The -rule_ipv4 option specifies the reading of IPv4 rules sets from the rule_ipv4.cfg file + +* The -rule_ipv6 option specifies the reading of IPv6 rules sets from the rule_ipv6.cfg file. + To use eventdev mode with sync method **ordered** on above mentioned environment, Following is the sample command: .. code-block:: console - .//examples/dpdk-l3fwd -l 0-3 -n 4 -a -- -p 0x3 --eventq-sched=ordered + .//examples/dpdk-l3fwd -l 0-3 -n 4 -a -- -p 0x3 --eventq-sched=ordered --rule_ipv4="rule_ipv4.cfg" --rule_ipv6="rule_ipv6.cfg" or .. code-block:: console .//examples/dpdk-l3fwd -l 0-3 -n 4 -a \ - -- -p 0x03 --mode=eventdev --eventq-sched=ordered + -- -p 0x03 --mode=eventdev --eventq-sched=ordered --rule_ipv4="rule_ipv4.cfg" --rule_ipv6="rule_ipv6.cfg" In this command: @@ -192,7 +204,7 @@ scheduler. Following is the sample command: .. code-block:: console - .//examples/dpdk-l3fwd -l 0-7 -s 0xf0000 -n 4 --vdev event_sw0 -- -p 0x3 --mode=eventdev --eventq-sched=ordered + .//examples/dpdk-l3fwd -l 0-7 -s 0xf0000 -n 4 --vdev event_sw0 -- -p 0x3 --mode=eventdev --eventq-sched=ordered --rule_ipv4="rule_ipv4.cfg" --rule_ipv6="rule_ipv6.cfg" In case of eventdev mode, *--config* option is not used for ethernet port configuration. Instead each ethernet port will be configured with mentioned @@ -216,6 +228,49 @@ The following sections provide some explanation of the sample application code. the initialization and run-time paths are very similar to those of the :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`. The following sections describe aspects that are specific to the L3 Forwarding sample application. +Parse Rules from File +~~~~~~~~~~~~~~~~~~~~~ + +The application parses the rules from the file and adds them to the appropriate route table by calling the appropriate function. +It ignores empty and comment lines, and parses and validates the rules it reads. +If errors are detected, the application exits with messages to identify the errors encountered. + +The format of the route rules differs based on which lookup method is being used. +Therefore, the code only decreases the priority number with each rule it parses. +Route rules are mandatory. +To read data from the specified file successfully, the application assumes the following: + +* Each rule occupies a single line. + +* Only the following four rule line types are valid in this application: + +* Route rule line, which starts with a leading character 'R' + +* Comment line, which starts with a leading character '#' + +* Empty line, which consists of a space, form-feed ('\f'), newline ('\n'), + carriage return ('\r'), horizontal tab ('\t'), or vertical tab ('\v'). + +Other lines types are considered invalid. + +* Rules are organized in descending order of priority, + which means rules at the head of the file always have a higher priority than those further down in the file. + +* A typical IPv4 LPM/FIB rule line should have a format as shown below: + +R/ + +* A typical IPv4 EM rule line should have a format as shown below: + +R + +IPv4 addresses are specified in CIDR format as specified in RFC 4632. +For LPM/FIB they consist of the dot notation for the address and a prefix length separated by '/'. +For example, 192.168.0.34/32, where the address is 192.168.0.34 and the prefix length is 32. +For EM they consist of just the dot notation for the address and no prefix length. +For example, 192.168.0.34, where the Address is 192.168.0.34. +EM also includes ports which are specified as a single number which represents a single port. + Hash Initialization ~~~~~~~~~~~~~~~~~~~ @@ -227,8 +282,6 @@ for the convenience to execute hash performance test on 4M/8M/16M flows. The Hash initialization will setup both ipv4 and ipv6 hash table, and populate the either table depending on the value of variable ipv6. - To support the hash performance test with up to 8M single direction flows/16M bi-direction flows, - populate_ipv4_many_flow_into_table() function will populate the hash table with specified hash table entry number(default 4M). .. note:: @@ -246,22 +299,14 @@ for the convenience to execute hash performance test on 4M/8M/16M flows. { // ... - if (hash_entry_number != HASH_ENTRY_NUMBER_DEFAULT) { - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_many_flow_into_table(ipv4_l3fwd_lookup_struct[socketid], hash_entry_number); - } else { - /* populate the ipv6 hash */ - populate_ipv6_many_flow_into_table( ipv6_l3fwd_lookup_struct[socketid], hash_entry_number); - } - } else - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_few_flow_into_table(ipv4_l3fwd_lookup_struct[socketid]); - } else { - /* populate the ipv6 hash */ - populate_ipv6_few_flow_into_table(ipv6_l3fwd_lookup_struct[socketid]); - } + if (ipv6 == 0) { + /* populate the ipv4 hash */ + populate_ipv4_flow_into_table( + ipv4_l3fwd_em_lookup_struct[socketid]); + } else { + /* populate the ipv6 hash */ + populate_ipv6_flow_into_table( + ipv6_l3fwd_em_lookup_struct[socketid]); } } #endif diff --git a/examples/l3fwd/em_default_v4.cfg b/examples/l3fwd/em_default_v4.cfg new file mode 100644 index 0000000000..b70bdb6601 --- /dev/null +++ b/examples/l3fwd/em_default_v4.cfg @@ -0,0 +1,17 @@ +#Copy of hard-coded IPv4 FWD table for L3FWD EM +R198.18.0.0 198.18.0.1 9 9 0x11 0 +R198.18.1.0 198.18.1.1 9 9 0x11 1 +R198.18.2.0 198.18.2.1 9 9 0x11 2 +R198.18.3.0 198.18.3.1 9 9 0x11 3 +R198.18.4.0 198.18.4.1 9 9 0x11 4 +R198.18.5.0 198.18.5.1 9 9 0x11 5 +R198.18.6.0 198.18.6.1 9 9 0x11 6 +R198.18.7.0 198.18.7.1 9 9 0x11 7 +R198.18.8.0 198.18.8.1 9 9 0x11 8 +R198.18.9.0 198.18.9.1 9 9 0x11 9 +R198.18.10.0 198.18.10.1 9 9 0x11 10 +R198.18.11.0 198.18.11.1 9 9 0x11 11 +R198.18.12.0 198.18.12.1 9 9 0x11 12 +R198.18.13.0 198.18.13.1 9 9 0x11 13 +R198.18.14.0 198.18.14.1 9 9 0x11 14 +R198.18.15.0 198.18.15.1 9 9 0x11 15 diff --git a/examples/l3fwd/em_default_v6.cfg b/examples/l3fwd/em_default_v6.cfg new file mode 100644 index 0000000000..0b94f8d8d2 --- /dev/null +++ b/examples/l3fwd/em_default_v6.cfg @@ -0,0 +1,17 @@ +#Copy of hard-coded IPv6 FWD table for L3FWD EM +R2001:0200:0000:0000:0000:0000:0000:0000 2001:0200:0000:0000:0000:0000:0000:0001 9 9 0x11 0 +R2001:0200:0000:0001:0000:0000:0000:0000 2001:0200:0000:0001:0000:0000:0000:0001 9 9 0x11 1 +R2001:0200:0000:0002:0000:0000:0000:0000 2001:0200:0000:0002:0000:0000:0000:0001 9 9 0x11 2 +R2001:0200:0000:0003:0000:0000:0000:0000 2001:0200:0000:0003:0000:0000:0000:0001 9 9 0x11 3 +R2001:0200:0000:0004:0000:0000:0000:0000 2001:0200:0000:0004:0000:0000:0000:0001 9 9 0x11 4 +R2001:0200:0000:0005:0000:0000:0000:0000 2001:0200:0000:0005:0000:0000:0000:0001 9 9 0x11 5 +R2001:0200:0000:0006:0000:0000:0000:0000 2001:0200:0000:0006:0000:0000:0000:0001 9 9 0x11 6 +R2001:0200:0000:0007:0000:0000:0000:0000 2001:0200:0000:0007:0000:0000:0000:0001 9 9 0x11 7 +R2001:0200:0000:0008:0000:0000:0000:0000 2001:0200:0000:0008:0000:0000:0000:0001 9 9 0x11 8 +R2001:0200:0000:0009:0000:0000:0000:0000 2001:0200:0000:0009:0000:0000:0000:0001 9 9 0x11 9 +R2001:0200:0000:000A:0000:0000:0000:0000 2001:0200:0000:000A:0000:0000:0000:0001 9 9 0x11 10 +R2001:0200:0000:000B:0000:0000:0000:0000 2001:0200:0000:000B:0000:0000:0000:0001 9 9 0x11 11 +R2001:0200:0000:000C:0000:0000:0000:0000 2001:0200:0000:000C:0000:0000:0000:0001 9 9 0x11 12 +R2001:0200:0000:000D:0000:0000:0000:0000 2001:0200:0000:000D:0000:0000:0000:0001 9 9 0x11 13 +R2001:0200:0000:000E:0000:0000:0000:0000 2001:0200:0000:000E:0000:0000:0000:0001 9 9 0x11 14 +R2001:0200:0000:000F:0000:0000:0000:0000 2001:0200:0000:000F:0000:0000:0000:0001 9 9 0x11 15 diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c index 9058e75a76..dd1fc4a4be 100644 --- a/examples/l3fwd/l3fwd_em.c +++ b/examples/l3fwd/l3fwd_em.c @@ -27,6 +27,7 @@ #include "l3fwd.h" #include "l3fwd_event.h" +#include "l3fwd_route.h" #if defined(RTE_ARCH_X86) || defined(__ARM_FEATURE_CRC32) #define EM_HASH_CRC 1 @@ -42,13 +43,18 @@ #define IPV6_ADDR_LEN 16 -struct ipv4_5tuple { - uint32_t ip_dst; - uint32_t ip_src; - uint16_t port_dst; - uint16_t port_src; - uint8_t proto; -} __rte_packed; +static struct em_rule *em_route_base_v4; +static struct em_rule *em_route_base_v6; + +enum { + CB_FLD_DST_ADDR, + CB_FLD_SRC_ADDR, + CB_FLD_DST_PORT, + CB_FLD_SRC_PORT, + CB_FLD_PROTO, + CB_FLD_IF_OUT, + CB_FLD_MAX +}; union ipv4_5tuple_host { struct { @@ -65,14 +71,6 @@ union ipv4_5tuple_host { #define XMM_NUM_IN_IPV6_5TUPLE 3 -struct ipv6_5tuple { - uint8_t ip_dst[IPV6_ADDR_LEN]; - uint8_t ip_src[IPV6_ADDR_LEN]; - uint16_t port_dst; - uint16_t port_src; - uint8_t proto; -} __rte_packed; - union ipv6_5tuple_host { struct { uint16_t pad0; @@ -87,8 +85,6 @@ union ipv6_5tuple_host { xmm_t xmm[XMM_NUM_IN_IPV6_5TUPLE]; }; - - struct ipv4_l3fwd_em_route { struct ipv4_5tuple key; uint8_t if_out; @@ -235,10 +231,6 @@ ipv6_hash_crc(const void *data, __rte_unused uint32_t data_len, return init_val; } -#define IPV4_L3FWD_EM_NUM_ROUTES RTE_DIM(ipv4_l3fwd_em_route_array) - -#define IPV6_L3FWD_EM_NUM_ROUTES RTE_DIM(ipv6_l3fwd_em_route_array) - static uint8_t ipv4_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; static uint8_t ipv6_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; @@ -346,6 +338,214 @@ em_get_ipv6_dst_port(void *ipv6_hdr, uint16_t portid, void *lookup_struct) #include "l3fwd_em.h" #endif +static int +em_parse_v6_net(const char *in, uint8_t *v) +{ + int32_t rc; + + /* get address. */ + rc = inet_pton(AF_INET6, in, v); + if (rc != 1) + return -EINVAL; + + return 0; +} + +static int +em_parse_v6_rule(char *str, struct em_rule *v) +{ + int i, rc; + char *s, *sp, *in[CB_FLD_MAX]; + static const char *dlm = " \t\n"; + int dim = CB_FLD_MAX; + s = str; + + for (i = 0; i != dim; i++, s = NULL) { + in[i] = strtok_r(s, dlm, &sp); + if (in[i] == NULL) + return -EINVAL; + } + + rc = em_parse_v6_net(in[CB_FLD_DST_ADDR], v->v6_key.ip_dst); + if (rc != 0) + return rc; + rc = em_parse_v6_net(in[CB_FLD_SRC_ADDR], v->v6_key.ip_src); + if (rc != 0) + return rc; + + /* source port. */ + GET_CB_FIELD(in[CB_FLD_SRC_PORT], v->v6_key.port_src, 0, UINT16_MAX, 0); + /* destination port. */ + GET_CB_FIELD(in[CB_FLD_DST_PORT], v->v6_key.port_dst, 0, UINT16_MAX, 0); + /* protocol. */ + GET_CB_FIELD(in[CB_FLD_PROTO], v->v6_key.proto, 0, UINT8_MAX, 0); + /* out interface. */ + GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0); + + return 0; +} + +static int +em_parse_v4_rule(char *str, struct em_rule *v) +{ + int i, rc; + char *s, *sp, *in[CB_FLD_MAX]; + static const char *dlm = " \t\n"; + int dim = CB_FLD_MAX; + s = str; + + for (i = 0; i != dim; i++, s = NULL) { + in[i] = strtok_r(s, dlm, &sp); + if (in[i] == NULL) + return -EINVAL; + } + + rc = inet_pton(AF_INET, in[CB_FLD_DST_ADDR], &(v->v4_key.ip_dst)); + v->v4_key.ip_dst = ntohl(v->v4_key.ip_dst); + if (rc != 1) + return rc; + + rc = inet_pton(AF_INET, in[CB_FLD_SRC_ADDR], &(v->v4_key.ip_src)); + v->v4_key.ip_src = ntohl(v->v4_key.ip_src); + if (rc != 1) + return rc; + + /* source port. */ + GET_CB_FIELD(in[CB_FLD_SRC_PORT], v->v4_key.port_src, 0, UINT16_MAX, 0); + /* destination port. */ + GET_CB_FIELD(in[CB_FLD_DST_PORT], v->v4_key.port_dst, 0, UINT16_MAX, 0); + /* protocol. */ + GET_CB_FIELD(in[CB_FLD_PROTO], v->v4_key.proto, 0, UINT8_MAX, 0); + /* out interface. */ + GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0); + + return 0; +} + +static int +em_add_rules(const char *rule_path, + struct em_rule **proute_base, + int (*parser)(char *, struct em_rule *)) +{ + struct em_rule *route_rules; + struct em_rule *next; + unsigned int route_num = 0; + unsigned int route_cnt = 0; + char buff[LINE_MAX]; + FILE *fh; + unsigned int i = 0, rule_size = sizeof(*next); + int val; + + *proute_base = NULL; + fh = fopen(rule_path, "rb"); + if (fh == NULL) + return -EINVAL; + + while ((fgets(buff, LINE_MAX, fh) != NULL)) { + if (buff[0] == ROUTE_LEAD_CHAR) + route_num++; + } + + if (route_num == 0) { + fclose(fh); + return -EINVAL; + } + + val = fseek(fh, 0, SEEK_SET); + if (val < 0) { + fclose(fh); + return -EINVAL; + } + + route_rules = calloc(route_num, rule_size); + + if (route_rules == NULL) { + fclose(fh); + return -EINVAL; + } + + i = 0; + while (fgets(buff, LINE_MAX, fh) != NULL) { + i++; + if (is_bypass_line(buff)) + continue; + + char s = buff[0]; + + /* Route entry */ + if (s == ROUTE_LEAD_CHAR) + next = &route_rules[route_cnt]; + + /* Illegal line */ + else { + RTE_LOG(ERR, L3FWD, + "%s Line %u: should start with leading " + "char %c\n", + rule_path, i, ROUTE_LEAD_CHAR); + fclose(fh); + free(route_rules); + return -EINVAL; + } + + if (parser(buff + 1, next) != 0) { + RTE_LOG(ERR, L3FWD, + "%s Line %u: parse rules error\n", + rule_path, i); + fclose(fh); + free(route_rules); + return -EINVAL; + } + + route_cnt++; + } + + fclose(fh); + + *proute_base = route_rules; + + return route_cnt; +} + +static int +em_add_default_v4_rules(void) +{ + /* populate the LPM IPv4 table */ + unsigned int i, rule_size = sizeof(*em_route_base_v4); + route_num_v4 = RTE_DIM(ipv4_l3fwd_em_route_array); + + em_route_base_v4 = calloc(route_num_v4, rule_size); + + for (i = 0; i < (unsigned int)route_num_v4; i++) { + em_route_base_v4[i].v4_key.ip_dst = ipv4_l3fwd_em_route_array[i].key.ip_dst; + em_route_base_v4[i].v4_key.ip_src = ipv4_l3fwd_em_route_array[i].key.ip_src; + em_route_base_v4[i].v4_key.port_dst = ipv4_l3fwd_em_route_array[i].key.port_dst; + em_route_base_v4[i].v4_key.port_src = ipv4_l3fwd_em_route_array[i].key.port_src; + em_route_base_v4[i].v4_key.proto = ipv4_l3fwd_em_route_array[i].key.proto; + em_route_base_v4[i].if_out = ipv4_l3fwd_em_route_array[i].if_out; + } + return 0; +} + +static int +em_add_default_v6_rules(void) +{ + /* populate the LPM IPv6 table */ + unsigned int i, rule_size = sizeof(*em_route_base_v6); + route_num_v6 = RTE_DIM(ipv6_l3fwd_em_route_array); + + em_route_base_v6 = calloc(route_num_v6, rule_size); + + for (i = 0; i < (unsigned int)route_num_v6; i++) { + *em_route_base_v6[i].v6_key.ip_dst = *ipv6_l3fwd_em_route_array[i].key.ip_dst; + *em_route_base_v6[i].v6_key.ip_src = *ipv6_l3fwd_em_route_array[i].key.ip_src; + em_route_base_v6[i].v6_key.port_dst = ipv6_l3fwd_em_route_array[i].key.port_dst; + em_route_base_v6[i].v6_key.port_src = ipv6_l3fwd_em_route_array[i].key.port_src; + em_route_base_v6[i].v6_key.proto = ipv6_l3fwd_em_route_array[i].key.proto; + em_route_base_v6[i].if_out = ipv6_l3fwd_em_route_array[i].if_out; + } + return 0; +} + static void convert_ipv4_5tuple(struct ipv4_5tuple *key1, union ipv4_5tuple_host *key2) @@ -382,122 +582,106 @@ convert_ipv6_5tuple(struct ipv6_5tuple *key1, #define BIT_8_TO_15 0x0000ff00 static inline void -populate_ipv4_few_flow_into_table(const struct rte_hash *h) +populate_ipv4_flow_into_table(const struct rte_hash *h) { - uint32_t i; + int i; int32_t ret; + struct rte_eth_dev_info dev_info; + char srcbuf[INET6_ADDRSTRLEN]; + char dstbuf[INET6_ADDRSTRLEN]; mask0 = (rte_xmm_t){.u32 = {BIT_8_TO_15, ALL_32_BITS, ALL_32_BITS, ALL_32_BITS} }; - for (i = 0; i < IPV4_L3FWD_EM_NUM_ROUTES; i++) { - struct ipv4_l3fwd_em_route entry; + for (i = 0; i < route_num_v4; i++) { + struct em_rule *entry; union ipv4_5tuple_host newkey; + struct in_addr src; + struct in_addr dst; + + if ((1 << em_route_base_v4[i].if_out & + enabled_port_mask) == 0) + continue; - entry = ipv4_l3fwd_em_route_array[i]; - convert_ipv4_5tuple(&entry.key, &newkey); + entry = &em_route_base_v4[i]; + convert_ipv4_5tuple(&(entry->v4_key), &newkey); ret = rte_hash_add_key(h, (void *) &newkey); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32 " to the l3fwd hash.\n", i); } - ipv4_l3fwd_out_if[ret] = entry.if_out; + ipv4_l3fwd_out_if[ret] = entry->if_out; + ret = rte_eth_dev_info_get(em_route_base_v4[i].if_out, + &dev_info); + if (ret != 0) + rte_exit(EXIT_FAILURE, + "Error during getting device (port %u) info: %s\n", + em_route_base_v4[i].if_out, strerror(-ret)); + + src.s_addr = htonl(em_route_base_v4[i].v4_key.ip_src); + dst.s_addr = htonl(em_route_base_v4[i].v4_key.ip_dst); + printf("EM: Adding route %s, %s, %d, %d, %d (%d) [%s]\n", + inet_ntop(AF_INET, &dst, dstbuf, sizeof(dstbuf)), + inet_ntop(AF_INET, &src, srcbuf, sizeof(srcbuf)), + em_route_base_v4[i].v4_key.port_dst, + em_route_base_v4[i].v4_key.port_src, + em_route_base_v4[i].v4_key.proto, + em_route_base_v4[i].if_out, dev_info.device->name); } printf("Hash: Adding 0x%" PRIx64 " keys\n", - (uint64_t)IPV4_L3FWD_EM_NUM_ROUTES); + (uint64_t)route_num_v4); } #define BIT_16_TO_23 0x00ff0000 static inline void -populate_ipv6_few_flow_into_table(const struct rte_hash *h) +populate_ipv6_flow_into_table(const struct rte_hash *h) { - uint32_t i; + int i; int32_t ret; + struct rte_eth_dev_info dev_info; + char srcbuf[INET6_ADDRSTRLEN]; + char dstbuf[INET6_ADDRSTRLEN]; mask1 = (rte_xmm_t){.u32 = {BIT_16_TO_23, ALL_32_BITS, ALL_32_BITS, ALL_32_BITS} }; mask2 = (rte_xmm_t){.u32 = {ALL_32_BITS, ALL_32_BITS, 0, 0} }; - for (i = 0; i < IPV6_L3FWD_EM_NUM_ROUTES; i++) { - struct ipv6_l3fwd_em_route entry; + for (i = 0; i < route_num_v6; i++) { + struct em_rule *entry; union ipv6_5tuple_host newkey; - entry = ipv6_l3fwd_em_route_array[i]; - convert_ipv6_5tuple(&entry.key, &newkey); + if ((1 << em_route_base_v6[i].if_out & + enabled_port_mask) == 0) + continue; + + entry = &em_route_base_v6[i]; + convert_ipv6_5tuple(&(entry->v6_key), &newkey); ret = rte_hash_add_key(h, (void *) &newkey); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32 " to the l3fwd hash.\n", i); } - ipv6_l3fwd_out_if[ret] = entry.if_out; + ipv6_l3fwd_out_if[ret] = entry->if_out; + ret = rte_eth_dev_info_get(em_route_base_v6[i].if_out, + &dev_info); + if (ret != 0) + rte_exit(EXIT_FAILURE, + "Error during getting device (port %u) info: %s\n", + em_route_base_v6[i].if_out, strerror(-ret)); + + printf("EM: Adding route %s, %s, %d, %d, %d (%d) [%s]\n", + inet_ntop(AF_INET6, em_route_base_v6[i].v6_key.ip_dst, + dstbuf, sizeof(dstbuf)), + inet_ntop(AF_INET6, em_route_base_v6[i].v6_key.ip_src, + srcbuf, sizeof(srcbuf)), + em_route_base_v6[i].v6_key.port_dst, + em_route_base_v6[i].v6_key.port_src, + em_route_base_v6[i].v6_key.proto, + em_route_base_v6[i].if_out, dev_info.device->name); } printf("Hash: Adding 0x%" PRIx64 "keys\n", - (uint64_t)IPV6_L3FWD_EM_NUM_ROUTES); -} - -#define NUMBER_PORT_USED 16 -static inline void -populate_ipv4_many_flow_into_table(const struct rte_hash *h, - unsigned int nr_flow) -{ - unsigned i; - - mask0 = (rte_xmm_t){.u32 = {BIT_8_TO_15, ALL_32_BITS, - ALL_32_BITS, ALL_32_BITS} }; - - for (i = 0; i < nr_flow; i++) { - uint8_t port = i % NUMBER_PORT_USED; - struct ipv4_l3fwd_em_route entry; - union ipv4_5tuple_host newkey; - - uint8_t a = (uint8_t)((port + 1) % BYTE_VALUE_MAX); - - /* Create the ipv4 exact match flow */ - memset(&entry, 0, sizeof(entry)); - entry = ipv4_l3fwd_em_route_array[port]; - entry.key.ip_dst = RTE_IPV4(198, 18, port, a); - convert_ipv4_5tuple(&entry.key, &newkey); - int32_t ret = rte_hash_add_key(h, (void *) &newkey); - - if (ret < 0) - rte_exit(EXIT_FAILURE, "Unable to add entry %u\n", i); - - ipv4_l3fwd_out_if[ret] = (uint8_t) entry.if_out; - - } - printf("Hash: Adding 0x%x keys\n", nr_flow); -} - -static inline void -populate_ipv6_many_flow_into_table(const struct rte_hash *h, - unsigned int nr_flow) -{ - unsigned i; - - mask1 = (rte_xmm_t){.u32 = {BIT_16_TO_23, ALL_32_BITS, - ALL_32_BITS, ALL_32_BITS} }; - mask2 = (rte_xmm_t){.u32 = {ALL_32_BITS, ALL_32_BITS, 0, 0} }; - - for (i = 0; i < nr_flow; i++) { - uint8_t port = i % NUMBER_PORT_USED; - struct ipv6_l3fwd_em_route entry; - union ipv6_5tuple_host newkey; - - /* Create the ipv6 exact match flow */ - memset(&entry, 0, sizeof(entry)); - entry = ipv6_l3fwd_em_route_array[port]; - entry.key.ip_dst[15] = (port + 1) % BYTE_VALUE_MAX; - convert_ipv6_5tuple(&entry.key, &newkey); - int32_t ret = rte_hash_add_key(h, (void *) &newkey); - - if (ret < 0) - rte_exit(EXIT_FAILURE, "Unable to add entry %u\n", i); - - ipv6_l3fwd_out_if[ret] = (uint8_t) entry.if_out; - - } - printf("Hash: Adding 0x%x keys\n", nr_flow); + (uint64_t)route_num_v6); } /* Requirements: @@ -972,17 +1156,50 @@ em_event_main_loop_tx_q_burst_vector(__rte_unused void *dummy) return 0; } -/* Load rules from the input file */ void -read_config_files_em(void) +em_free_routes(void) { - /* Empty till config file support added to EM */ + free(em_route_base_v4); + free(em_route_base_v6); + em_route_base_v4 = NULL; + em_route_base_v6 = NULL; + route_num_v4 = 0; + route_num_v6 = 0; } +/* Load rules from the input file */ void -em_free_routes(void) +read_config_files_em(void) { - /* Empty till config file support added to EM */ + /* ipv4 check */ + if (parm_config.rule_ipv4_name != NULL && + parm_config.rule_ipv6_name != NULL) { + /* ipv4 check */ + route_num_v4 = em_add_rules(parm_config.rule_ipv4_name, + &em_route_base_v4, &em_parse_v4_rule); + if (route_num_v4 < 0) { + em_free_routes(); + rte_exit(EXIT_FAILURE, "Failed to add EM IPv4 rules\n"); + } + + /* ipv6 check */ + route_num_v6 = em_add_rules(parm_config.rule_ipv6_name, + &em_route_base_v6, &em_parse_v6_rule); + if (route_num_v6 < 0) { + em_free_routes(); + rte_exit(EXIT_FAILURE, "Failed to add EM IPv6 rules\n"); + } + } else { + RTE_LOG(INFO, L3FWD, "Missing 1 or more rule files, using default instead\n"); + if (em_add_default_v4_rules() < 0) { + em_free_routes(); + rte_exit(EXIT_FAILURE, "Failed to add default IPv4 rules\n"); + } + if (em_add_default_v6_rules() < 0) { + em_free_routes(); + rte_exit(EXIT_FAILURE, "Failed to add default IPv6 rules\n"); + } + } } /* Initialize exact match (hash) parameters. 8< */ @@ -1029,35 +1246,18 @@ setup_hash(const int socketid) "Unable to create the l3fwd hash on socket %d\n", socketid); - if (hash_entry_number != HASH_ENTRY_NUMBER_DEFAULT) { - /* For testing hash matching with a large number of flows we - * generate millions of IP 5-tuples with an incremented dst - * address to initialize the hash table. */ - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_many_flow_into_table( - ipv4_l3fwd_em_lookup_struct[socketid], - hash_entry_number); - } else { - /* populate the ipv6 hash */ - populate_ipv6_many_flow_into_table( - ipv6_l3fwd_em_lookup_struct[socketid], - hash_entry_number); - } + /* + * Use data from ipv4/ipv6 l3fwd config file + * directly to initialize the hash table. + */ + if (ipv6 == 0) { + /* populate the ipv4 hash */ + populate_ipv4_flow_into_table( + ipv4_l3fwd_em_lookup_struct[socketid]); } else { - /* - * Use data in ipv4/ipv6 l3fwd lookup table - * directly to initialize the hash table. - */ - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_few_flow_into_table( - ipv4_l3fwd_em_lookup_struct[socketid]); - } else { - /* populate the ipv6 hash */ - populate_ipv6_few_flow_into_table( - ipv6_l3fwd_em_lookup_struct[socketid]); - } + /* populate the ipv6 hash */ + populate_ipv6_flow_into_table( + ipv6_l3fwd_em_lookup_struct[socketid]); } } /* >8 End of initialization of hash parameters. */ diff --git a/examples/l3fwd/l3fwd_route.h b/examples/l3fwd/l3fwd_route.h index 843ffbe9fa..f48f7e1954 100644 --- a/examples/l3fwd/l3fwd_route.h +++ b/examples/l3fwd/l3fwd_route.h @@ -14,6 +14,22 @@ struct ipv6_l3fwd_route { uint8_t if_out; }; +struct ipv4_5tuple { + uint32_t ip_dst; + uint32_t ip_src; + uint16_t port_dst; + uint16_t port_src; + uint8_t proto; +} __rte_packed; + +struct ipv6_5tuple { + uint8_t ip_dst[IPV6_ADDR_LEN]; + uint8_t ip_src[IPV6_ADDR_LEN]; + uint16_t port_dst; + uint16_t port_src; + uint8_t proto; +} __rte_packed; + struct lpm_route_rule { union { uint32_t ip; @@ -26,6 +42,14 @@ struct lpm_route_rule { uint8_t if_out; }; +struct em_rule { + union { + struct ipv4_5tuple v4_key; + struct ipv6_5tuple v6_key; + }; + uint8_t if_out; +}; + extern struct lpm_route_rule *route_base_v4; extern struct lpm_route_rule *route_base_v6; extern int route_num_v4; -- 2.25.1