examples/l3fwd: support config file for EM
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 reflect these changes. Signed-off-by: Sean Morrissey <sean.morrissey@intel.com> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
This commit is contained in:
parent
52def963fc
commit
e7e6dd6430
@ -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
|
In the sample application, hash-based and FIB-based forwarding supports
|
||||||
both IPv4 and IPv6.
|
both IPv4 and IPv6.
|
||||||
LPM-based forwarding supports IPv4 only.
|
LPM-based forwarding supports IPv4 only.
|
||||||
|
During the initialization phase route rules for IPv4 and IPv6 are read from rule files.
|
||||||
|
|
||||||
Compiling the Application
|
Compiling the Application
|
||||||
-------------------------
|
-------------------------
|
||||||
@ -61,6 +62,8 @@ Running the Application
|
|||||||
The application has a number of command line options::
|
The application has a number of command line options::
|
||||||
|
|
||||||
./dpdk-l3fwd [EAL options] -- -p PORTMASK
|
./dpdk-l3fwd [EAL options] -- -p PORTMASK
|
||||||
|
--rule_ipv4=FILE
|
||||||
|
--rule_ipv6=FILE
|
||||||
[-P]
|
[-P]
|
||||||
[--lookup LOOKUP_METHOD]
|
[--lookup LOOKUP_METHOD]
|
||||||
--config(port,queue,lcore)[,(port,queue,lcore)]
|
--config(port,queue,lcore)[,(port,queue,lcore)]
|
||||||
@ -82,6 +85,11 @@ Where,
|
|||||||
|
|
||||||
* ``-p PORTMASK:`` Hexadecimal bitmask of ports to configure
|
* ``-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.
|
* ``-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.
|
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
|
.. code-block:: console
|
||||||
|
|
||||||
./<build_dir>/examples/dpdk-l3fwd -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)"
|
./<build_dir>/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:
|
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,
|
To use eventdev mode with sync method **ordered** on above mentioned environment,
|
||||||
Following is the sample command:
|
Following is the sample command:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
./<build_dir>/examples/dpdk-l3fwd -l 0-3 -n 4 -a <event device> -- -p 0x3 --eventq-sched=ordered
|
./<build_dir>/examples/dpdk-l3fwd -l 0-3 -n 4 -a <event device> -- -p 0x3 --eventq-sched=ordered --rule_ipv4="rule_ipv4.cfg" --rule_ipv6="rule_ipv6.cfg"
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
./<build_dir>/examples/dpdk-l3fwd -l 0-3 -n 4 -a <event device> \
|
./<build_dir>/examples/dpdk-l3fwd -l 0-3 -n 4 -a <event device> \
|
||||||
-- -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:
|
In this command:
|
||||||
|
|
||||||
@ -192,7 +204,7 @@ scheduler. Following is the sample command:
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
./<build_dir>/examples/dpdk-l3fwd -l 0-7 -s 0xf0000 -n 4 --vdev event_sw0 -- -p 0x3 --mode=eventdev --eventq-sched=ordered
|
./<build_dir>/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
|
In case of eventdev mode, *--config* option is not used for ethernet port
|
||||||
configuration. Instead each ethernet port will be configured with mentioned
|
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 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.
|
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<destination_ip>/<ip_mask_length><output_port_number>
|
||||||
|
|
||||||
|
* A typical IPv4 EM rule line should have a format as shown below:
|
||||||
|
|
||||||
|
R<destination_ip><source_ip><destination_port><source_port><protocol><output_port_number>
|
||||||
|
|
||||||
|
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
|
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,
|
The Hash initialization will setup both ipv4 and ipv6 hash table,
|
||||||
and populate the either table depending on the value of variable ipv6.
|
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::
|
.. 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) {
|
||||||
if (ipv6 == 0) {
|
/* populate the ipv4 hash */
|
||||||
/* populate the ipv4 hash */
|
populate_ipv4_flow_into_table(
|
||||||
populate_ipv4_many_flow_into_table(ipv4_l3fwd_lookup_struct[socketid], hash_entry_number);
|
ipv4_l3fwd_em_lookup_struct[socketid]);
|
||||||
} else {
|
} else {
|
||||||
/* populate the ipv6 hash */
|
/* populate the ipv6 hash */
|
||||||
populate_ipv6_many_flow_into_table( ipv6_l3fwd_lookup_struct[socketid], hash_entry_number);
|
populate_ipv6_flow_into_table(
|
||||||
}
|
ipv6_l3fwd_em_lookup_struct[socketid]);
|
||||||
} 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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
17
examples/l3fwd/em_default_v4.cfg
Normal file
17
examples/l3fwd/em_default_v4.cfg
Normal file
@ -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
|
17
examples/l3fwd/em_default_v6.cfg
Normal file
17
examples/l3fwd/em_default_v6.cfg
Normal file
@ -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
|
@ -2,17 +2,279 @@
|
|||||||
* Copyright(c) 2022 Intel Corporation
|
* Copyright(c) 2022 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include "l3fwd.h"
|
||||||
#include "l3fwd_route.h"
|
#include "l3fwd_route.h"
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
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++) {
|
||||||
|
memcpy(em_route_base_v6[i].v6_key.ip_dst, ipv6_l3fwd_em_route_array[i].key.ip_dst,
|
||||||
|
sizeof(em_route_base_v6[i].v6_key.ip_dst));
|
||||||
|
memcpy(em_route_base_v6[i].v6_key.ip_src, ipv6_l3fwd_em_route_array[i].key.ip_src,
|
||||||
|
sizeof(em_route_base_v6[i].v6_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;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
em_free_routes(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 */
|
/* Load rules from the input file */
|
||||||
void
|
void
|
||||||
read_config_files_em(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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,14 +43,6 @@
|
|||||||
|
|
||||||
#define IPV6_ADDR_LEN 16
|
#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;
|
|
||||||
|
|
||||||
union ipv4_5tuple_host {
|
union ipv4_5tuple_host {
|
||||||
struct {
|
struct {
|
||||||
uint8_t pad0;
|
uint8_t pad0;
|
||||||
@ -66,14 +58,6 @@ union ipv4_5tuple_host {
|
|||||||
|
|
||||||
#define XMM_NUM_IN_IPV6_5TUPLE 3
|
#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 {
|
union ipv6_5tuple_host {
|
||||||
struct {
|
struct {
|
||||||
uint16_t pad0;
|
uint16_t pad0;
|
||||||
@ -88,22 +72,10 @@ union ipv6_5tuple_host {
|
|||||||
xmm_t xmm[XMM_NUM_IN_IPV6_5TUPLE];
|
xmm_t xmm[XMM_NUM_IN_IPV6_5TUPLE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ipv4_l3fwd_em_route {
|
|
||||||
struct ipv4_5tuple key;
|
|
||||||
uint8_t if_out;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ipv6_l3fwd_em_route {
|
|
||||||
struct ipv6_5tuple key;
|
|
||||||
uint8_t if_out;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
|
/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
|
||||||
* Use RFC863 Discard Protocol.
|
* Use RFC863 Discard Protocol.
|
||||||
*/
|
*/
|
||||||
static const struct ipv4_l3fwd_em_route ipv4_l3fwd_em_route_array[] = {
|
const struct ipv4_l3fwd_em_route ipv4_l3fwd_em_route_array[] = {
|
||||||
{{RTE_IPV4(198, 18, 0, 0), RTE_IPV4(198, 18, 0, 1), 9, 9, IPPROTO_UDP}, 0},
|
{{RTE_IPV4(198, 18, 0, 0), RTE_IPV4(198, 18, 0, 1), 9, 9, IPPROTO_UDP}, 0},
|
||||||
{{RTE_IPV4(198, 18, 1, 0), RTE_IPV4(198, 18, 1, 1), 9, 9, IPPROTO_UDP}, 1},
|
{{RTE_IPV4(198, 18, 1, 0), RTE_IPV4(198, 18, 1, 1), 9, 9, IPPROTO_UDP}, 1},
|
||||||
{{RTE_IPV4(198, 18, 2, 0), RTE_IPV4(198, 18, 2, 1), 9, 9, IPPROTO_UDP}, 2},
|
{{RTE_IPV4(198, 18, 2, 0), RTE_IPV4(198, 18, 2, 1), 9, 9, IPPROTO_UDP}, 2},
|
||||||
@ -125,7 +97,7 @@ static const struct ipv4_l3fwd_em_route ipv4_l3fwd_em_route_array[] = {
|
|||||||
/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
|
/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
|
||||||
* Use RFC863 Discard Protocol.
|
* Use RFC863 Discard Protocol.
|
||||||
*/
|
*/
|
||||||
static const struct ipv6_l3fwd_em_route ipv6_l3fwd_em_route_array[] = {
|
const struct ipv6_l3fwd_em_route ipv6_l3fwd_em_route_array[] = {
|
||||||
{{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
{{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 0},
|
{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 0},
|
||||||
{{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
|
{{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
@ -236,10 +208,6 @@ ipv6_hash_crc(const void *data, __rte_unused uint32_t data_len,
|
|||||||
return init_val;
|
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 ipv4_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned;
|
||||||
static uint8_t ipv6_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned;
|
static uint8_t ipv6_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned;
|
||||||
|
|
||||||
@ -383,122 +351,106 @@ convert_ipv6_5tuple(struct ipv6_5tuple *key1,
|
|||||||
#define BIT_8_TO_15 0x0000ff00
|
#define BIT_8_TO_15 0x0000ff00
|
||||||
|
|
||||||
static inline void
|
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;
|
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,
|
mask0 = (rte_xmm_t){.u32 = {BIT_8_TO_15, ALL_32_BITS,
|
||||||
ALL_32_BITS, ALL_32_BITS} };
|
ALL_32_BITS, ALL_32_BITS} };
|
||||||
|
|
||||||
for (i = 0; i < IPV4_L3FWD_EM_NUM_ROUTES; i++) {
|
for (i = 0; i < route_num_v4; i++) {
|
||||||
struct ipv4_l3fwd_em_route entry;
|
struct em_rule *entry;
|
||||||
union ipv4_5tuple_host newkey;
|
union ipv4_5tuple_host newkey;
|
||||||
|
struct in_addr src;
|
||||||
|
struct in_addr dst;
|
||||||
|
|
||||||
entry = ipv4_l3fwd_em_route_array[i];
|
if ((1 << em_route_base_v4[i].if_out &
|
||||||
convert_ipv4_5tuple(&entry.key, &newkey);
|
enabled_port_mask) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
entry = &em_route_base_v4[i];
|
||||||
|
convert_ipv4_5tuple(&(entry->v4_key), &newkey);
|
||||||
ret = rte_hash_add_key(h, (void *) &newkey);
|
ret = rte_hash_add_key(h, (void *) &newkey);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32
|
rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32
|
||||||
" to the l3fwd hash.\n", i);
|
" 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",
|
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
|
#define BIT_16_TO_23 0x00ff0000
|
||||||
static inline void
|
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;
|
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,
|
mask1 = (rte_xmm_t){.u32 = {BIT_16_TO_23, ALL_32_BITS,
|
||||||
ALL_32_BITS, ALL_32_BITS} };
|
ALL_32_BITS, ALL_32_BITS} };
|
||||||
|
|
||||||
mask2 = (rte_xmm_t){.u32 = {ALL_32_BITS, ALL_32_BITS, 0, 0} };
|
mask2 = (rte_xmm_t){.u32 = {ALL_32_BITS, ALL_32_BITS, 0, 0} };
|
||||||
|
|
||||||
for (i = 0; i < IPV6_L3FWD_EM_NUM_ROUTES; i++) {
|
for (i = 0; i < route_num_v6; i++) {
|
||||||
struct ipv6_l3fwd_em_route entry;
|
struct em_rule *entry;
|
||||||
union ipv6_5tuple_host newkey;
|
union ipv6_5tuple_host newkey;
|
||||||
|
|
||||||
entry = ipv6_l3fwd_em_route_array[i];
|
if ((1 << em_route_base_v6[i].if_out &
|
||||||
convert_ipv6_5tuple(&entry.key, &newkey);
|
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);
|
ret = rte_hash_add_key(h, (void *) &newkey);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32
|
rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32
|
||||||
" to the l3fwd hash.\n", i);
|
" 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",
|
printf("Hash: Adding 0x%" PRIx64 "keys\n",
|
||||||
(uint64_t)IPV6_L3FWD_EM_NUM_ROUTES);
|
(uint64_t)route_num_v6);
|
||||||
}
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Requirements:
|
/* Requirements:
|
||||||
@ -1017,35 +969,18 @@ setup_hash(const int socketid)
|
|||||||
"Unable to create the l3fwd hash on socket %d\n",
|
"Unable to create the l3fwd hash on socket %d\n",
|
||||||
socketid);
|
socketid);
|
||||||
|
|
||||||
if (hash_entry_number != HASH_ENTRY_NUMBER_DEFAULT) {
|
/*
|
||||||
/* For testing hash matching with a large number of flows we
|
* Use data from ipv4/ipv6 l3fwd config file
|
||||||
* generate millions of IP 5-tuples with an incremented dst
|
* directly to initialize the hash table.
|
||||||
* address to initialize the hash table. */
|
*/
|
||||||
if (ipv6 == 0) {
|
if (ipv6 == 0) {
|
||||||
/* populate the ipv4 hash */
|
/* populate the ipv4 hash */
|
||||||
populate_ipv4_many_flow_into_table(
|
populate_ipv4_flow_into_table(
|
||||||
ipv4_l3fwd_em_lookup_struct[socketid],
|
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/* populate the ipv6 hash */
|
||||||
* Use data in ipv4/ipv6 l3fwd lookup table
|
populate_ipv6_flow_into_table(
|
||||||
* directly to initialize the hash table.
|
ipv6_l3fwd_em_lookup_struct[socketid]);
|
||||||
*/
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* >8 End of initialization of hash parameters. */
|
/* >8 End of initialization of hash parameters. */
|
||||||
|
@ -33,6 +33,22 @@ struct ipv6_l3fwd_route {
|
|||||||
uint8_t if_out;
|
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 {
|
struct lpm_route_rule {
|
||||||
union {
|
union {
|
||||||
uint32_t ip;
|
uint32_t ip;
|
||||||
@ -45,15 +61,35 @@ struct lpm_route_rule {
|
|||||||
uint8_t if_out;
|
uint8_t if_out;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ipv4_l3fwd_em_route {
|
||||||
|
struct ipv4_5tuple key;
|
||||||
|
uint8_t if_out;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipv6_l3fwd_em_route {
|
||||||
|
struct ipv6_5tuple key;
|
||||||
|
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_v4;
|
||||||
extern struct lpm_route_rule *route_base_v6;
|
extern struct lpm_route_rule *route_base_v6;
|
||||||
extern int route_num_v4;
|
extern int route_num_v4;
|
||||||
extern int route_num_v6;
|
extern int route_num_v6;
|
||||||
|
|
||||||
extern const struct ipv4_l3fwd_route ipv4_l3fwd_route_array[16];
|
extern const struct ipv4_l3fwd_route ipv4_l3fwd_route_array[16];
|
||||||
|
|
||||||
extern const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[16];
|
extern const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[16];
|
||||||
|
|
||||||
|
extern const struct ipv4_l3fwd_em_route ipv4_l3fwd_em_route_array[16];
|
||||||
|
extern const struct ipv6_l3fwd_em_route ipv6_l3fwd_em_route_array[16];
|
||||||
|
|
||||||
void
|
void
|
||||||
read_config_files_lpm(void);
|
read_config_files_lpm(void);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user