From patchwork Thu Dec 16 15:01:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Morrissey X-Patchwork-Id: 105161 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 66F41A0032; Thu, 16 Dec 2021 16:02:39 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 523E24111B; Thu, 16 Dec 2021 16:02:39 +0100 (CET) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mails.dpdk.org (Postfix) with ESMTP id 30D5F40DF7 for ; Thu, 16 Dec 2021 16:02:37 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1639666958; x=1671202958; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=P6vy8a1DWn220gQNWLJBvFLqKTFIAwFcI9d8xz30go4=; b=aRSqgwR+9T8ZRtiuR6tWbGTagdUBGbkgXbC/VMluZLwYruqIDMU4cUa/ a8NSu1YO3V0+SHVv0/AclfH2PqnkmTesluT/rnaokntiSgzpfYm12dHxK 0GaGor1RIxmviNUBp+K1lI3yspdwp1q7vA7tMcTsLOs4zg9YXxka2ndo4 l3/dZSme3R5VuA0GraHsjyMaNCrlY+mdU0kNwyiAUBWSkY0D0QDo1FoOP 8GMAEEYHGPE8kq3G+ReWn8weV5RQs+SjxdBFqtwm6a3MTRx7zfsCSxExx iR63qQaLaZ7GF85xz5IBtHZscApnqlSXKLacSfkErLngEGDiWdnkjtMN7 w==; X-IronPort-AV: E=McAfee;i="6200,9189,10199"; a="325793891" X-IronPort-AV: E=Sophos;i="5.88,211,1635231600"; d="scan'208";a="325793891" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Dec 2021 07:01:47 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,211,1635231600"; d="scan'208";a="615181554" Received: from silpixa00401215.ir.intel.com ([10.55.128.96]) by orsmga004.jf.intel.com with ESMTP; 16 Dec 2021 07:01:37 -0800 From: Sean Morrissey To: Cc: dev@dpdk.org, Sean Morrissey , Ravi Kerur Subject: [PATCH v1 1/2] examples/l3fwd: add config file support for LPM/FIB Date: Thu, 16 Dec 2021 15:01:03 +0000 Message-Id: <20211216150104.860924-2-sean.morrissey@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211216150104.860924-1-sean.morrissey@intel.com> References: <20211216150104.860924-1-sean.morrissey@intel.com> MIME-Version: 1.0 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 LPM and FIB, with format similar to l3fwd-acl one. With the removal of the hardcoded route tables for IPv4 and IPv6, these routes have been moved to a separate default config file for use with LPM and FIB. Signed-off-by: Sean Morrissey Signed-off-by: Ravi Kerur --- examples/l3fwd/l3fwd.h | 35 ++++ examples/l3fwd/l3fwd_em.c | 7 + examples/l3fwd/l3fwd_fib.c | 52 +++--- examples/l3fwd/l3fwd_lpm.c | 281 +++++++++++++++++++++++++++--- examples/l3fwd/l3fwd_route.h | 17 +- examples/l3fwd/lpm_default_v4.cfg | 17 ++ examples/l3fwd/lpm_default_v6.cfg | 17 ++ examples/l3fwd/main.c | 97 ++++++----- 8 files changed, 437 insertions(+), 86 deletions(-) create mode 100644 examples/l3fwd/lpm_default_v4.cfg create mode 100644 examples/l3fwd/lpm_default_v6.cfg diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h index 38ca19133c..d8b1f971e1 100644 --- a/examples/l3fwd/l3fwd.h +++ b/examples/l3fwd/l3fwd.h @@ -58,6 +58,30 @@ #endif #define HASH_ENTRY_NUMBER_DEFAULT 16 +/*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 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 +120,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) @@ -183,6 +209,12 @@ int init_mem(uint16_t portid, unsigned int nb_mbuf); /* Function pointers for LPM, EM or FIB functionality. */ +void +read_config_files_lpm(void); + +void +read_config_files_em(void); + void setup_lpm(const int socketid); @@ -286,4 +318,7 @@ fib_get_ipv4_l3fwd_lookup_struct(const int socketid); void * fib_get_ipv6_l3fwd_lookup_struct(const int socketid); +int +is_bypass_line(const char *buff); + #endif /* __L3_FWD_H__ */ diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c index 5cc4a4d979..4953cdae4e 100644 --- a/examples/l3fwd/l3fwd_em.c +++ b/examples/l3fwd/l3fwd_em.c @@ -972,6 +972,13 @@ 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) +{ + /* Empty till config file support added to EM */ +} + /* Initialize exact match (hash) parameters. 8< */ void setup_hash(const int socketid) diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c index 2110459cc3..003721c908 100644 --- a/examples/l3fwd/l3fwd_fib.c +++ b/examples/l3fwd/l3fwd_fib.c @@ -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,44 +652,50 @@ 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); } } + free(route_base_v4); + free(route_base_v6); } /* Return ipv4 fib lookup struct. */ diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c index a5b476ced3..4157f16c07 100644 --- a/examples/l3fwd/l3fwd_lpm.c +++ b/examples/l3fwd/l3fwd_lpm.c @@ -39,6 +39,16 @@ static struct rte_lpm *ipv4_l3fwd_lpm_lookup_struct[NB_SOCKETS]; static struct rte_lpm6 *ipv6_l3fwd_lpm_lookup_struct[NB_SOCKETS]; +struct lpm_route_rule *route_base_v4; +struct lpm_route_rule *route_base_v6; +int route_num_v4; +int route_num_v6; + +enum { + CB_FLD_DST_ADDR, + CB_FLD_IF_OUT, + CB_FLD_MAX +}; /* Performing LPM-based lookups. 8< */ static inline uint16_t @@ -139,6 +149,199 @@ lpm_get_dst_port_with_ipv4(const struct lcore_conf *qconf, struct rte_mbuf *pkt, #include "l3fwd_lpm.h" #endif +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_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; +} + +static void +free_lpm_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; +} + /* main processing loop */ int lpm_main_loop(__rte_unused void *dummy) @@ -153,6 +356,9 @@ lpm_main_loop(__rte_unused void *dummy) const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; + /* Config read and setup, free structs */ + free_lpm_routes(); + lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; @@ -548,13 +754,44 @@ lpm_event_main_loop_tx_q_burst_vector(__rte_unused void *dummy) return 0; } +/* Load rules from the input file */ +void +read_config_files_lpm(void) +{ + /* ipv4 check */ + if (parm_config.rule_ipv4_name != NULL) { + route_num_v4 = lpm_add_rules(parm_config.rule_ipv4_name, + &route_base_v4, &lpm_parse_v4_rule); + if (route_num_v4 < 0) { + free_lpm_routes(); + rte_exit(EXIT_FAILURE, "Failed to add IPv4 rules\n"); + } + } else { + RTE_LOG(ERR, L3FWD, "IPv4 rule file not specified\n"); + rte_exit(EXIT_FAILURE, "Failed to get valid route options\n"); + } + + /* ipv6 check */ + if (parm_config.rule_ipv6_name != NULL) { + route_num_v6 = lpm_add_rules(parm_config.rule_ipv6_name, + &route_base_v6, &lpm_parse_v6_rule); + if (route_num_v6 < 0) { + free_lpm_routes(); + rte_exit(EXIT_FAILURE, "Failed to add IPv6 rules\n"); + } + } else { + RTE_LOG(ERR, L3FWD, "IPv6 rule file not specified\n"); + rte_exit(EXIT_FAILURE, "Failed to get valid route options\n"); + } +} + void 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 +809,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) { + free_lpm_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 +846,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) { + free_lpm_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) { + free_lpm_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); } } diff --git a/examples/l3fwd/l3fwd_route.h b/examples/l3fwd/l3fwd_route.h index c7eba06c4d..6d41c926b1 100644 --- a/examples/l3fwd/l3fwd_route.h +++ b/examples/l3fwd/l3fwd_route.h @@ -14,6 +14,19 @@ struct ipv6_l3fwd_route { uint8_t if_out; }; -extern const struct ipv4_l3fwd_route ipv4_l3fwd_route_array[16]; +struct lpm_route_rule { + union { + uint32_t ip; + union { + uint32_t ip_32[4]; + uint8_t ip_8[16]; + }; + }; + uint8_t depth; + uint8_t if_out; +}; -extern const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[16]; +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; diff --git a/examples/l3fwd/lpm_default_v4.cfg b/examples/l3fwd/lpm_default_v4.cfg new file mode 100644 index 0000000000..4db5597ed8 --- /dev/null +++ b/examples/l3fwd/lpm_default_v4.cfg @@ -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 diff --git a/examples/l3fwd/lpm_default_v6.cfg b/examples/l3fwd/lpm_default_v6.cfg new file mode 100644 index 0000000000..c50233e0ba --- /dev/null +++ b/examples/l3fwd/lpm_default_v6.cfg @@ -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 diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c index eb68ffc5aa..b02c14a5fc 100644 --- a/examples/l3fwd/main.c +++ b/examples/l3fwd/main.c @@ -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,6 +143,7 @@ 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; @@ -152,6 +155,7 @@ struct l3fwd_lkp_mode { 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, @@ -161,6 +165,7 @@ static struct l3fwd_lkp_mode l3fwd_em_lkp = { }; 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, @@ -170,6 +175,7 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = { }; 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, @@ -179,50 +185,19 @@ static struct l3fwd_lkp_mode l3fwd_fib_lkp = { }; /* - * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). - * 198.18.{0-15}.0/24 = Port {0-15} + * API's called during initialization to setup ACL/EM/LPM rules. */ -const struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = { - {RTE_IPV4(198, 18, 0, 0), 24, 0}, - {RTE_IPV4(198, 18, 1, 0), 24, 1}, - {RTE_IPV4(198, 18, 2, 0), 24, 2}, - {RTE_IPV4(198, 18, 3, 0), 24, 3}, - {RTE_IPV4(198, 18, 4, 0), 24, 4}, - {RTE_IPV4(198, 18, 5, 0), 24, 5}, - {RTE_IPV4(198, 18, 6, 0), 24, 6}, - {RTE_IPV4(198, 18, 7, 0), 24, 7}, - {RTE_IPV4(198, 18, 8, 0), 24, 8}, - {RTE_IPV4(198, 18, 9, 0), 24, 9}, - {RTE_IPV4(198, 18, 10, 0), 24, 10}, - {RTE_IPV4(198, 18, 11, 0), 24, 11}, - {RTE_IPV4(198, 18, 12, 0), 24, 12}, - {RTE_IPV4(198, 18, 13, 0), 24, 13}, - {RTE_IPV4(198, 18, 14, 0), 24, 14}, - {RTE_IPV4(198, 18, 15, 0), 24, 15}, -}; +static void +l3fwd_set_rule_ipv4_name(const char *optarg) +{ + parm_config.rule_ipv4_name = optarg; +} -/* - * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180). - * 2001:200:0:{0-f}::/64 = Port {0-15} - */ -const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = { - {{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0}, - {{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1}, - {{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2}, - {{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3}, - {{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4}, - {{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5}, - {{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6}, - {{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7}, - {{32, 1, 2, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 8}, - {{32, 1, 2, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 9}, - {{32, 1, 2, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 10}, - {{32, 1, 2, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 11}, - {{32, 1, 2, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 12}, - {{32, 1, 2, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 13}, - {{32, 1, 2, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 14}, - {{32, 1, 2, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 15}, -}; +static void +l3fwd_set_rule_ipv6_name(const char *optarg) +{ + parm_config.rule_ipv6_name = optarg; +} /* * Setup lookup methods for forwarding. @@ -339,6 +314,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)]" @@ -382,6 +359,9 @@ print_usage(const char *prgname) " --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", + " --rule_ipv4=FILE: specify the ipv4 rules entries file. " + "Each rule occupies one line. " + " --rule_ipv6=FILE: specify the ipv6 rules entries file.\n", prgname); } @@ -596,6 +576,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 +592,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 +621,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 +777,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; @@ -1358,6 +1350,24 @@ l3fwd_event_service_setup(void) } } +/* 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; +} + int main(int argc, char **argv) { @@ -1395,6 +1405,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;