examples/l3fwd: support config file for LPM/FIB
Add support to define ipv4 and ipv6 forwarding tables from reading from a config file for LPM and FIB, with format similar to l3fwd-acl one. Users can now use the default hardcoded route tables or optionally config files. Default config files have been provided for use with LPM and FIB. Signed-off-by: Sean Morrissey <sean.morrissey@intel.com> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com> Tested-by: Yingya Han <yingyax.han@intel.com>
This commit is contained in:
parent
a8dde09f97
commit
52def963fc
18
examples/l3fwd/em_route_parse.c
Normal file
18
examples/l3fwd/em_route_parse.c
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright(c) 2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "l3fwd_route.h"
|
||||
|
||||
void
|
||||
em_free_routes(void)
|
||||
{
|
||||
/* Empty till config file support added to EM */
|
||||
}
|
||||
|
||||
/* Load rules from the input file */
|
||||
void
|
||||
read_config_files_em(void)
|
||||
{
|
||||
/* Empty till config file support added to EM */
|
||||
}
|
@ -58,6 +58,11 @@
|
||||
#endif
|
||||
#define HASH_ENTRY_NUMBER_DEFAULT 16
|
||||
|
||||
struct parm_cfg {
|
||||
const char *rule_ipv4_name;
|
||||
const char *rule_ipv6_name;
|
||||
};
|
||||
|
||||
struct mbuf_table {
|
||||
uint16_t len;
|
||||
struct rte_mbuf *m_table[MAX_PKT_BURST];
|
||||
@ -96,6 +101,8 @@ extern xmm_t val_eth[RTE_MAX_ETHPORTS];
|
||||
|
||||
extern struct lcore_conf lcore_conf[RTE_MAX_LCORE];
|
||||
|
||||
extern struct parm_cfg parm_config;
|
||||
|
||||
/* Send burst of packets on an output interface */
|
||||
static inline int
|
||||
send_burst(struct lcore_conf *qconf, uint16_t n, uint16_t port)
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "l3fwd.h"
|
||||
#include "l3fwd_event.h"
|
||||
#include "em_route_parse.c"
|
||||
|
||||
#if defined(RTE_ARCH_X86) || defined(__ARM_FEATURE_CRC32)
|
||||
#define EM_HASH_CRC 1
|
||||
|
@ -583,7 +583,7 @@ setup_fib(const int socketid)
|
||||
struct rte_eth_dev_info dev_info;
|
||||
struct rte_fib6_conf config;
|
||||
struct rte_fib_conf config_ipv4;
|
||||
unsigned int i;
|
||||
int i;
|
||||
int ret;
|
||||
char s[64];
|
||||
char abuf[INET6_ADDRSTRLEN];
|
||||
@ -603,37 +603,39 @@ setup_fib(const int socketid)
|
||||
"Unable to create the l3fwd FIB table on socket %d\n",
|
||||
socketid);
|
||||
|
||||
|
||||
/* Populate the fib ipv4 table. */
|
||||
for (i = 0; i < RTE_DIM(ipv4_l3fwd_route_array); i++) {
|
||||
for (i = 0; i < route_num_v4; i++) {
|
||||
struct in_addr in;
|
||||
|
||||
/* Skip unused ports. */
|
||||
if ((1 << ipv4_l3fwd_route_array[i].if_out &
|
||||
if ((1 << route_base_v4[i].if_out &
|
||||
enabled_port_mask) == 0)
|
||||
continue;
|
||||
|
||||
rte_eth_dev_info_get(ipv4_l3fwd_route_array[i].if_out,
|
||||
rte_eth_dev_info_get(route_base_v4[i].if_out,
|
||||
&dev_info);
|
||||
ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
|
||||
ipv4_l3fwd_route_array[i].ip,
|
||||
ipv4_l3fwd_route_array[i].depth,
|
||||
ipv4_l3fwd_route_array[i].if_out);
|
||||
route_base_v4[i].ip,
|
||||
route_base_v4[i].depth,
|
||||
route_base_v4[i].if_out);
|
||||
|
||||
if (ret < 0) {
|
||||
free(route_base_v4);
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
|
||||
i, socketid);
|
||||
}
|
||||
|
||||
in.s_addr = htonl(ipv4_l3fwd_route_array[i].ip);
|
||||
in.s_addr = htonl(route_base_v4[i].ip);
|
||||
if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
|
||||
printf("FIB: Adding route %s / %d (%d) [%s]\n", abuf,
|
||||
ipv4_l3fwd_route_array[i].depth,
|
||||
ipv4_l3fwd_route_array[i].if_out,
|
||||
route_base_v4[i].depth,
|
||||
route_base_v4[i].if_out,
|
||||
dev_info.device->name);
|
||||
} else {
|
||||
printf("FIB: IPv4 route added to port %d [%s]\n",
|
||||
ipv4_l3fwd_route_array[i].if_out,
|
||||
route_base_v4[i].if_out,
|
||||
dev_info.device->name);
|
||||
}
|
||||
}
|
||||
@ -650,41 +652,45 @@ setup_fib(const int socketid)
|
||||
config.trie.num_tbl8 = (1 << 15);
|
||||
ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
|
||||
&config);
|
||||
if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL)
|
||||
if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL) {
|
||||
free(route_base_v4);
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Unable to create the l3fwd FIB table on socket %d\n",
|
||||
socketid);
|
||||
}
|
||||
|
||||
/* Populate the fib IPv6 table. */
|
||||
for (i = 0; i < RTE_DIM(ipv6_l3fwd_route_array); i++) {
|
||||
for (i = 0; i < route_num_v6; i++) {
|
||||
|
||||
/* Skip unused ports. */
|
||||
if ((1 << ipv6_l3fwd_route_array[i].if_out &
|
||||
if ((1 << route_base_v6[i].if_out &
|
||||
enabled_port_mask) == 0)
|
||||
continue;
|
||||
|
||||
rte_eth_dev_info_get(ipv6_l3fwd_route_array[i].if_out,
|
||||
rte_eth_dev_info_get(route_base_v6[i].if_out,
|
||||
&dev_info);
|
||||
ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
|
||||
ipv6_l3fwd_route_array[i].ip,
|
||||
ipv6_l3fwd_route_array[i].depth,
|
||||
ipv6_l3fwd_route_array[i].if_out);
|
||||
route_base_v6[i].ip_8,
|
||||
route_base_v6[i].depth,
|
||||
route_base_v6[i].if_out);
|
||||
|
||||
if (ret < 0) {
|
||||
free(route_base_v4);
|
||||
free(route_base_v6);
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
|
||||
i, socketid);
|
||||
}
|
||||
|
||||
if (inet_ntop(AF_INET6, ipv6_l3fwd_route_array[i].ip,
|
||||
if (inet_ntop(AF_INET6, route_base_v6[i].ip_8,
|
||||
abuf, sizeof(abuf)) != NULL) {
|
||||
printf("FIB: Adding route %s / %d (%d) [%s]\n", abuf,
|
||||
ipv6_l3fwd_route_array[i].depth,
|
||||
ipv6_l3fwd_route_array[i].if_out,
|
||||
route_base_v6[i].depth,
|
||||
route_base_v6[i].if_out,
|
||||
dev_info.device->name);
|
||||
} else {
|
||||
printf("FIB: IPv6 route added to port %d [%s]\n",
|
||||
ipv6_l3fwd_route_array[i].if_out,
|
||||
route_base_v6[i].if_out,
|
||||
dev_info.device->name);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "l3fwd.h"
|
||||
#include "l3fwd_event.h"
|
||||
|
||||
#include "l3fwd_route.h"
|
||||
#include "lpm_route_parse.c"
|
||||
|
||||
#define IPV4_L3FWD_LPM_MAX_RULES 1024
|
||||
#define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
|
||||
@ -554,7 +554,7 @@ setup_lpm(const int socketid)
|
||||
struct rte_eth_dev_info dev_info;
|
||||
struct rte_lpm6_config config;
|
||||
struct rte_lpm_config config_ipv4;
|
||||
unsigned i;
|
||||
int i;
|
||||
int ret;
|
||||
char s[64];
|
||||
char abuf[INET6_ADDRSTRLEN];
|
||||
@ -572,32 +572,33 @@ setup_lpm(const int socketid)
|
||||
socketid);
|
||||
|
||||
/* populate the LPM table */
|
||||
for (i = 0; i < RTE_DIM(ipv4_l3fwd_route_array); i++) {
|
||||
for (i = 0; i < route_num_v4; i++) {
|
||||
struct in_addr in;
|
||||
|
||||
/* skip unused ports */
|
||||
if ((1 << ipv4_l3fwd_route_array[i].if_out &
|
||||
if ((1 << route_base_v4[i].if_out &
|
||||
enabled_port_mask) == 0)
|
||||
continue;
|
||||
|
||||
rte_eth_dev_info_get(ipv4_l3fwd_route_array[i].if_out,
|
||||
rte_eth_dev_info_get(route_base_v4[i].if_out,
|
||||
&dev_info);
|
||||
ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
|
||||
ipv4_l3fwd_route_array[i].ip,
|
||||
ipv4_l3fwd_route_array[i].depth,
|
||||
ipv4_l3fwd_route_array[i].if_out);
|
||||
route_base_v4[i].ip,
|
||||
route_base_v4[i].depth,
|
||||
route_base_v4[i].if_out);
|
||||
|
||||
if (ret < 0) {
|
||||
lpm_free_routes();
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Unable to add entry %u to the l3fwd LPM table on socket %d\n",
|
||||
i, socketid);
|
||||
}
|
||||
|
||||
in.s_addr = htonl(ipv4_l3fwd_route_array[i].ip);
|
||||
in.s_addr = htonl(route_base_v4[i].ip);
|
||||
printf("LPM: Adding route %s / %d (%d) [%s]\n",
|
||||
inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
|
||||
ipv4_l3fwd_route_array[i].depth,
|
||||
ipv4_l3fwd_route_array[i].if_out, dev_info.device->name);
|
||||
route_base_v4[i].depth,
|
||||
route_base_v4[i].if_out, dev_info.device->name);
|
||||
}
|
||||
|
||||
/* create the LPM6 table */
|
||||
@ -608,37 +609,40 @@ setup_lpm(const int socketid)
|
||||
config.flags = 0;
|
||||
ipv6_l3fwd_lpm_lookup_struct[socketid] = rte_lpm6_create(s, socketid,
|
||||
&config);
|
||||
if (ipv6_l3fwd_lpm_lookup_struct[socketid] == NULL)
|
||||
if (ipv6_l3fwd_lpm_lookup_struct[socketid] == NULL) {
|
||||
lpm_free_routes();
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Unable to create the l3fwd LPM table on socket %d\n",
|
||||
socketid);
|
||||
}
|
||||
|
||||
/* populate the LPM table */
|
||||
for (i = 0; i < RTE_DIM(ipv6_l3fwd_route_array); i++) {
|
||||
for (i = 0; i < route_num_v6; i++) {
|
||||
|
||||
/* skip unused ports */
|
||||
if ((1 << ipv6_l3fwd_route_array[i].if_out &
|
||||
if ((1 << route_base_v6[i].if_out &
|
||||
enabled_port_mask) == 0)
|
||||
continue;
|
||||
|
||||
rte_eth_dev_info_get(ipv4_l3fwd_route_array[i].if_out,
|
||||
rte_eth_dev_info_get(route_base_v6[i].if_out,
|
||||
&dev_info);
|
||||
ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
|
||||
ipv6_l3fwd_route_array[i].ip,
|
||||
ipv6_l3fwd_route_array[i].depth,
|
||||
ipv6_l3fwd_route_array[i].if_out);
|
||||
route_base_v6[i].ip_8,
|
||||
route_base_v6[i].depth,
|
||||
route_base_v6[i].if_out);
|
||||
|
||||
if (ret < 0) {
|
||||
lpm_free_routes();
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Unable to add entry %u to the l3fwd LPM table on socket %d\n",
|
||||
i, socketid);
|
||||
}
|
||||
|
||||
printf("LPM: Adding route %s / %d (%d) [%s]\n",
|
||||
inet_ntop(AF_INET6, ipv6_l3fwd_route_array[i].ip, abuf,
|
||||
inet_ntop(AF_INET6, route_base_v6[i].ip_8, abuf,
|
||||
sizeof(abuf)),
|
||||
ipv6_l3fwd_route_array[i].depth,
|
||||
ipv6_l3fwd_route_array[i].if_out, dev_info.device->name);
|
||||
route_base_v6[i].depth,
|
||||
route_base_v6[i].if_out, dev_info.device->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,25 @@
|
||||
* Copyright(c) 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
/* Log file related character defs. */
|
||||
#define COMMENT_LEAD_CHAR ('#')
|
||||
#define ROUTE_LEAD_CHAR ('R')
|
||||
|
||||
#define IPV6_ADDR_LEN 16
|
||||
#define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t))
|
||||
#define IPV6_ADDR_U32 (IPV6_ADDR_LEN / sizeof(uint32_t))
|
||||
|
||||
#define GET_CB_FIELD(in, fd, base, lim, dlm) do { \
|
||||
unsigned long val; \
|
||||
char *end; \
|
||||
errno = 0; \
|
||||
val = strtoul((in), &end, (base)); \
|
||||
if (errno != 0 || end[0] != (dlm) || val > (lim)) \
|
||||
return -EINVAL; \
|
||||
(fd) = (typeof(fd))val; \
|
||||
(in) = end + 1; \
|
||||
} while (0)
|
||||
|
||||
struct ipv4_l3fwd_route {
|
||||
uint32_t ip;
|
||||
uint8_t depth;
|
||||
@ -14,6 +33,38 @@ struct ipv6_l3fwd_route {
|
||||
uint8_t if_out;
|
||||
};
|
||||
|
||||
struct lpm_route_rule {
|
||||
union {
|
||||
uint32_t ip;
|
||||
union {
|
||||
uint32_t ip_32[IPV6_ADDR_U32];
|
||||
uint8_t ip_8[IPV6_ADDR_LEN];
|
||||
};
|
||||
};
|
||||
uint8_t depth;
|
||||
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;
|
||||
extern int route_num_v6;
|
||||
|
||||
extern const struct ipv4_l3fwd_route ipv4_l3fwd_route_array[16];
|
||||
|
||||
extern const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[16];
|
||||
|
||||
void
|
||||
read_config_files_lpm(void);
|
||||
|
||||
void
|
||||
read_config_files_em(void);
|
||||
|
||||
void
|
||||
em_free_routes(void);
|
||||
|
||||
void
|
||||
lpm_free_routes(void);
|
||||
|
||||
int
|
||||
is_bypass_line(const char *buff);
|
||||
|
17
examples/l3fwd/lpm_default_v4.cfg
Normal file
17
examples/l3fwd/lpm_default_v4.cfg
Normal file
@ -0,0 +1,17 @@
|
||||
# Copy of hard-coded IPv4 FWD table for L3FWD LPM
|
||||
R198.18.0.0/24 0
|
||||
R198.18.1.0/24 1
|
||||
R198.18.2.0/24 2
|
||||
R198.18.3.0/24 3
|
||||
R198.18.4.0/24 4
|
||||
R198.18.5.0/24 5
|
||||
R198.18.6.0/24 6
|
||||
R198.18.7.0/24 7
|
||||
R198.18.8.0/24 8
|
||||
R198.18.9.0/24 9
|
||||
R198.18.10.0/24 10
|
||||
R198.18.11.0/24 11
|
||||
R198.18.12.0/24 12
|
||||
R198.18.13.0/24 13
|
||||
R198.18.14.0/24 14
|
||||
R198.18.15.0/24 15
|
17
examples/l3fwd/lpm_default_v6.cfg
Normal file
17
examples/l3fwd/lpm_default_v6.cfg
Normal file
@ -0,0 +1,17 @@
|
||||
# Copy of hard-coded IPv6 FWD table for L3FWD LPM
|
||||
R2001:0200:0000:0000:0000:0000:0000:0000/64 0
|
||||
R2001:0200:0000:0001:0000:0000:0000:0000/64 1
|
||||
R2001:0200:0000:0002:0000:0000:0000:0000/64 2
|
||||
R2001:0200:0000:0003:0000:0000:0000:0000/64 3
|
||||
R2001:0200:0000:0004:0000:0000:0000:0000/64 4
|
||||
R2001:0200:0000:0005:0000:0000:0000:0000/64 5
|
||||
R2001:0200:0000:0006:0000:0000:0000:0000/64 6
|
||||
R2001:0200:0000:0007:0000:0000:0000:0000/64 7
|
||||
R2001:0200:0000:0008:0000:0000:0000:0000/64 8
|
||||
R2001:0200:0000:0009:0000:0000:0000:0000/64 9
|
||||
R2001:0200:0000:000A:0000:0000:0000:0000/64 10
|
||||
R2001:0200:0000:000B:0000:0000:0000:0000/64 11
|
||||
R2001:0200:0000:000C:0000:0000:0000:0000/64 12
|
||||
R2001:0200:0000:000D:0000:0000:0000:0000/64 13
|
||||
R2001:0200:0000:000E:0000:0000:0000:0000/64 14
|
||||
R2001:0200:0000:000F:0000:0000:0000:0000/64 15
|
302
examples/l3fwd/lpm_route_parse.c
Normal file
302
examples/l3fwd/lpm_route_parse.c
Normal file
@ -0,0 +1,302 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* 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"
|
||||
|
||||
enum {
|
||||
CB_FLD_DST_ADDR,
|
||||
CB_FLD_IF_OUT,
|
||||
CB_FLD_MAX
|
||||
};
|
||||
|
||||
struct lpm_route_rule *route_base_v4;
|
||||
struct lpm_route_rule *route_base_v6;
|
||||
int route_num_v4;
|
||||
int route_num_v6;
|
||||
|
||||
/* Bypass comment and empty lines */
|
||||
int
|
||||
is_bypass_line(const char *buff)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* comment line */
|
||||
if (buff[0] == COMMENT_LEAD_CHAR)
|
||||
return 1;
|
||||
/* empty line */
|
||||
while (buff[i] != '\0') {
|
||||
if (!isspace(buff[i]))
|
||||
return 0;
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_ipv6_addr_mask(char *token, uint32_t *ipv6, uint8_t *mask)
|
||||
{
|
||||
char *sa, *sm, *sv;
|
||||
const char *dlm = "/";
|
||||
|
||||
sv = NULL;
|
||||
sa = strtok_r(token, dlm, &sv);
|
||||
if (sa == NULL)
|
||||
return -EINVAL;
|
||||
sm = strtok_r(NULL, dlm, &sv);
|
||||
if (sm == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (inet_pton(AF_INET6, sa, ipv6) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
GET_CB_FIELD(sm, *mask, 0, 128, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_ipv4_addr_mask(char *token, uint32_t *ipv4, uint8_t *mask)
|
||||
{
|
||||
char *sa, *sm, *sv;
|
||||
const char *dlm = "/";
|
||||
|
||||
sv = NULL;
|
||||
sa = strtok_r(token, dlm, &sv);
|
||||
if (sa == NULL)
|
||||
return -EINVAL;
|
||||
sm = strtok_r(NULL, dlm, &sv);
|
||||
if (sm == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (inet_pton(AF_INET, sa, ipv4) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
GET_CB_FIELD(sm, *mask, 0, 32, 0);
|
||||
*ipv4 = ntohl(*ipv4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lpm_parse_v6_net(char *in, uint32_t *v, uint8_t *mask_len)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
/* get address. */
|
||||
rc = parse_ipv6_addr_mask(in, v, mask_len);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
lpm_parse_v6_rule(char *str, struct lpm_route_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 = lpm_parse_v6_net(in[CB_FLD_DST_ADDR], v->ip_32, &v->depth);
|
||||
|
||||
GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
lpm_parse_v4_rule(char *str, struct lpm_route_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 = parse_ipv4_addr_mask(in[CB_FLD_DST_ADDR], &v->ip, &v->depth);
|
||||
|
||||
GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
lpm_add_default_v4_rules(void)
|
||||
{
|
||||
/* populate the LPM IPv4 table */
|
||||
unsigned int i, rule_size = sizeof(*route_base_v4);
|
||||
route_num_v4 = RTE_DIM(ipv4_l3fwd_route_array);
|
||||
|
||||
route_base_v4 = calloc(route_num_v4, rule_size);
|
||||
|
||||
for (i = 0; i < (unsigned int)route_num_v4; i++) {
|
||||
route_base_v4[i].ip = ipv4_l3fwd_route_array[i].ip;
|
||||
route_base_v4[i].depth = ipv4_l3fwd_route_array[i].depth;
|
||||
route_base_v4[i].if_out = ipv4_l3fwd_route_array[i].if_out;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lpm_add_default_v6_rules(void)
|
||||
{
|
||||
/* populate the LPM IPv6 table */
|
||||
unsigned int i, rule_size = sizeof(*route_base_v6);
|
||||
route_num_v6 = RTE_DIM(ipv6_l3fwd_route_array);
|
||||
|
||||
route_base_v6 = calloc(route_num_v6, rule_size);
|
||||
|
||||
for (i = 0; i < (unsigned int)route_num_v6; i++) {
|
||||
memcpy(route_base_v6[i].ip_8, ipv6_l3fwd_route_array[i].ip,
|
||||
sizeof(route_base_v6[i].ip_8));
|
||||
route_base_v6[i].depth = ipv6_l3fwd_route_array[i].depth;
|
||||
route_base_v6[i].if_out = ipv6_l3fwd_route_array[i].if_out;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lpm_add_rules(const char *rule_path,
|
||||
struct lpm_route_rule **proute_base,
|
||||
int (*parser)(char *, struct lpm_route_rule *))
|
||||
{
|
||||
struct lpm_route_rule *route_rules;
|
||||
struct lpm_route_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;
|
||||
}
|
||||
|
||||
void
|
||||
lpm_free_routes(void)
|
||||
{
|
||||
free(route_base_v4);
|
||||
free(route_base_v6);
|
||||
route_base_v4 = NULL;
|
||||
route_base_v6 = NULL;
|
||||
route_num_v4 = 0;
|
||||
route_num_v6 = 0;
|
||||
}
|
||||
|
||||
/* Load rules from the input file */
|
||||
void
|
||||
read_config_files_lpm(void)
|
||||
{
|
||||
if (parm_config.rule_ipv4_name != NULL &&
|
||||
parm_config.rule_ipv6_name != NULL) {
|
||||
/* ipv4 check */
|
||||
route_num_v4 = lpm_add_rules(parm_config.rule_ipv4_name,
|
||||
&route_base_v4, &lpm_parse_v4_rule);
|
||||
if (route_num_v4 < 0) {
|
||||
lpm_free_routes();
|
||||
rte_exit(EXIT_FAILURE, "Failed to add IPv4 rules\n");
|
||||
}
|
||||
|
||||
/* ipv6 check */
|
||||
route_num_v6 = lpm_add_rules(parm_config.rule_ipv6_name,
|
||||
&route_base_v6, &lpm_parse_v6_rule);
|
||||
if (route_num_v6 < 0) {
|
||||
lpm_free_routes();
|
||||
rte_exit(EXIT_FAILURE, "Failed to add IPv6 rules\n");
|
||||
}
|
||||
} else {
|
||||
RTE_LOG(INFO, L3FWD, "Missing 1 or more rule files, using default instead\n");
|
||||
if (lpm_add_default_v4_rules() < 0) {
|
||||
lpm_free_routes();
|
||||
rte_exit(EXIT_FAILURE, "Failed to add default IPv4 rules\n");
|
||||
}
|
||||
if (lpm_add_default_v6_rules() < 0) {
|
||||
lpm_free_routes();
|
||||
rte_exit(EXIT_FAILURE, "Failed to add default IPv6 rules\n");
|
||||
}
|
||||
}
|
||||
}
|
@ -94,6 +94,8 @@ uint32_t hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
|
||||
|
||||
struct lcore_conf lcore_conf[RTE_MAX_LCORE];
|
||||
|
||||
struct parm_cfg parm_config;
|
||||
|
||||
struct lcore_params {
|
||||
uint16_t port_id;
|
||||
uint8_t queue_id;
|
||||
@ -141,41 +143,49 @@ static struct rte_mempool *vector_pool[RTE_MAX_ETHPORTS];
|
||||
static uint8_t lkp_per_socket[NB_SOCKETS];
|
||||
|
||||
struct l3fwd_lkp_mode {
|
||||
void (*read_config_files)(void);
|
||||
void (*setup)(int);
|
||||
int (*check_ptype)(int);
|
||||
rte_rx_callback_fn cb_parse_ptype;
|
||||
int (*main_loop)(void *);
|
||||
void* (*get_ipv4_lookup_struct)(int);
|
||||
void* (*get_ipv6_lookup_struct)(int);
|
||||
void (*free_routes)(void);
|
||||
};
|
||||
|
||||
static struct l3fwd_lkp_mode l3fwd_lkp;
|
||||
|
||||
static struct l3fwd_lkp_mode l3fwd_em_lkp = {
|
||||
.read_config_files = read_config_files_em,
|
||||
.setup = setup_hash,
|
||||
.check_ptype = em_check_ptype,
|
||||
.cb_parse_ptype = em_cb_parse_ptype,
|
||||
.main_loop = em_main_loop,
|
||||
.get_ipv4_lookup_struct = em_get_ipv4_l3fwd_lookup_struct,
|
||||
.get_ipv6_lookup_struct = em_get_ipv6_l3fwd_lookup_struct,
|
||||
.free_routes = em_free_routes,
|
||||
};
|
||||
|
||||
static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
|
||||
.read_config_files = read_config_files_lpm,
|
||||
.setup = setup_lpm,
|
||||
.check_ptype = lpm_check_ptype,
|
||||
.cb_parse_ptype = lpm_cb_parse_ptype,
|
||||
.main_loop = lpm_main_loop,
|
||||
.get_ipv4_lookup_struct = lpm_get_ipv4_l3fwd_lookup_struct,
|
||||
.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
|
||||
.free_routes = lpm_free_routes,
|
||||
};
|
||||
|
||||
static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
|
||||
.read_config_files = read_config_files_lpm,
|
||||
.setup = setup_fib,
|
||||
.check_ptype = lpm_check_ptype,
|
||||
.cb_parse_ptype = lpm_cb_parse_ptype,
|
||||
.main_loop = fib_main_loop,
|
||||
.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
|
||||
.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
|
||||
.free_routes = lpm_free_routes,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -224,6 +234,21 @@ const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = {
|
||||
{{32, 1, 2, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 15},
|
||||
};
|
||||
|
||||
/*
|
||||
* API's called during initialization to setup ACL/EM/LPM rules.
|
||||
*/
|
||||
static void
|
||||
l3fwd_set_rule_ipv4_name(const char *optarg)
|
||||
{
|
||||
parm_config.rule_ipv4_name = optarg;
|
||||
}
|
||||
|
||||
static void
|
||||
l3fwd_set_rule_ipv6_name(const char *optarg)
|
||||
{
|
||||
parm_config.rule_ipv6_name = optarg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup lookup methods for forwarding.
|
||||
* Currently exact-match, longest-prefix-match and forwarding information
|
||||
@ -339,6 +364,8 @@ print_usage(const char *prgname)
|
||||
{
|
||||
fprintf(stderr, "%s [EAL options] --"
|
||||
" -p PORTMASK"
|
||||
" --rule_ipv4=FILE"
|
||||
" --rule_ipv6=FILE"
|
||||
" [-P]"
|
||||
" [--lookup]"
|
||||
" --config (port,queue,lcore)[,(port,queue,lcore)]"
|
||||
@ -381,7 +408,10 @@ print_usage(const char *prgname)
|
||||
" --event-vector-size: Max vector size if event vectorization is enabled.\n"
|
||||
" --event-vector-tmo: Max timeout to form vector in nanoseconds if event vectorization is enabled\n"
|
||||
" -E : Enable exact match, legacy flag please use --lookup=em instead\n"
|
||||
" -L : Enable longest prefix match, legacy flag please use --lookup=lpm instead\n\n",
|
||||
" -L : Enable longest prefix match, legacy flag please use --lookup=lpm instead\n"
|
||||
" --rule_ipv4=FILE: Specify the ipv4 rules entries file.\n"
|
||||
" Each rule occupies one line.\n"
|
||||
" --rule_ipv6=FILE: Specify the ipv6 rules entries file.\n\n",
|
||||
prgname);
|
||||
}
|
||||
|
||||
@ -596,6 +626,8 @@ static const char short_options[] =
|
||||
#define CMD_LINE_OPT_ENABLE_VECTOR "event-vector"
|
||||
#define CMD_LINE_OPT_VECTOR_SIZE "event-vector-size"
|
||||
#define CMD_LINE_OPT_VECTOR_TMO_NS "event-vector-tmo"
|
||||
#define CMD_LINE_OPT_RULE_IPV4 "rule_ipv4"
|
||||
#define CMD_LINE_OPT_RULE_IPV6 "rule_ipv6"
|
||||
|
||||
enum {
|
||||
/* long options mapped to a short option */
|
||||
@ -610,6 +642,8 @@ enum {
|
||||
CMD_LINE_OPT_MAX_PKT_LEN_NUM,
|
||||
CMD_LINE_OPT_HASH_ENTRY_NUM_NUM,
|
||||
CMD_LINE_OPT_PARSE_PTYPE_NUM,
|
||||
CMD_LINE_OPT_RULE_IPV4_NUM,
|
||||
CMD_LINE_OPT_RULE_IPV6_NUM,
|
||||
CMD_LINE_OPT_PARSE_PER_PORT_POOL,
|
||||
CMD_LINE_OPT_MODE_NUM,
|
||||
CMD_LINE_OPT_EVENTQ_SYNC_NUM,
|
||||
@ -637,6 +671,8 @@ static const struct option lgopts[] = {
|
||||
{CMD_LINE_OPT_ENABLE_VECTOR, 0, 0, CMD_LINE_OPT_ENABLE_VECTOR_NUM},
|
||||
{CMD_LINE_OPT_VECTOR_SIZE, 1, 0, CMD_LINE_OPT_VECTOR_SIZE_NUM},
|
||||
{CMD_LINE_OPT_VECTOR_TMO_NS, 1, 0, CMD_LINE_OPT_VECTOR_TMO_NS_NUM},
|
||||
{CMD_LINE_OPT_RULE_IPV4, 1, 0, CMD_LINE_OPT_RULE_IPV4_NUM},
|
||||
{CMD_LINE_OPT_RULE_IPV6, 1, 0, CMD_LINE_OPT_RULE_IPV6_NUM},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
@ -791,6 +827,12 @@ parse_args(int argc, char **argv)
|
||||
case CMD_LINE_OPT_VECTOR_TMO_NS_NUM:
|
||||
evt_rsrc->vector_tmo_ns = strtoull(optarg, NULL, 10);
|
||||
break;
|
||||
case CMD_LINE_OPT_RULE_IPV4_NUM:
|
||||
l3fwd_set_rule_ipv4_name(optarg);
|
||||
break;
|
||||
case CMD_LINE_OPT_RULE_IPV6_NUM:
|
||||
l3fwd_set_rule_ipv6_name(optarg);
|
||||
break;
|
||||
default:
|
||||
print_usage(prgname);
|
||||
return -1;
|
||||
@ -1395,6 +1437,9 @@ main(int argc, char **argv)
|
||||
/* Setup function pointers for lookup method. */
|
||||
setup_l3fwd_lookup_tables();
|
||||
|
||||
/* Add the config file rules */
|
||||
l3fwd_lkp.read_config_files();
|
||||
|
||||
evt_rsrc->per_port_pool = per_port_pool;
|
||||
evt_rsrc->pkt_pool = pktmbuf_pool;
|
||||
evt_rsrc->vec_pool = vector_pool;
|
||||
@ -1501,6 +1546,9 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* clean up config file routes */
|
||||
l3fwd_lkp.free_routes();
|
||||
|
||||
/* clean up the EAL */
|
||||
rte_eal_cleanup();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user