From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 31259A04A2; Fri, 4 Feb 2022 20:59:24 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3D7B140143; Fri, 4 Feb 2022 20:59:20 +0100 (CET) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mails.dpdk.org (Postfix) with ESMTP id 6CF0B40143 for ; Fri, 4 Feb 2022 20:59:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1644004758; x=1675540758; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DFAX+29u0zFx8KZ/E0kIYmKvdZu+I3bmgnstrf+60JI=; b=NoRH++imXKiRrF0iz3zKUxkUXk6QhaLHnTPgNa4Ep136CCTptzLUfnos IYj/tK8qk3S4zo+S7iFJahPSJPuyvmRHTfknGFi9gg0bF2Ktc9/Yl3CBW ei0eLMWhgsqySjkWCVun92vzBgY7fs7pux6Il0BxfPb+gQycN9Jfg7vRn vBIUnbeYajOzP8Me0aPCQPCA/Z7qZlr5tkop4qVE5CpsPzE2LJySSju1w 4A8sY7qGG7aHxWaEWEsbq61Qi46ESf/98I68AGp9A9cRNbM5vQXi3yB0g X4dNAnGS0t0k0qcPlbPVoI+xnfqSt6Ekc3VcRGxNc37NxDt+Q02dtu1np w==; X-IronPort-AV: E=McAfee;i="6200,9189,10248"; a="231999778" X-IronPort-AV: E=Sophos;i="5.88,343,1635231600"; d="scan'208";a="231999778" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Feb 2022 11:59:18 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,343,1635231600"; d="scan'208";a="566843352" Received: from silpixa00401215.ir.intel.com ([10.55.128.96]) by orsmga001.jf.intel.com with ESMTP; 04 Feb 2022 11:59:14 -0800 From: Sean Morrissey To: Cc: dev@dpdk.org, Sean Morrissey , Konstantin Ananyev Subject: [PATCH v5 1/2] examples/l3fwd: add config file support for LPM/FIB Date: Fri, 4 Feb 2022 19:59:04 +0000 Message-Id: <20220204195905.449192-2-sean.morrissey@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220204195905.449192-1-sean.morrissey@intel.com> References: <20220126124459.2469838-1-sean.morrissey@intel.com> <20220204195905.449192-1-sean.morrissey@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add support to define ipv4 and ipv6 forwarding tables from reading from a config file for 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 Acked-by: Konstantin Ananyev --- examples/l3fwd/l3fwd.h | 41 ++++ examples/l3fwd/l3fwd_em.c | 13 ++ examples/l3fwd/l3fwd_fib.c | 50 ++--- examples/l3fwd/l3fwd_lpm.c | 315 ++++++++++++++++++++++++++++-- examples/l3fwd/l3fwd_route.h | 17 ++ examples/l3fwd/lpm_default_v4.cfg | 17 ++ examples/l3fwd/lpm_default_v6.cfg | 17 ++ examples/l3fwd/main.c | 68 ++++++- 8 files changed, 495 insertions(+), 43 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..4e1e0af033 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,13 @@ fib_get_ipv4_l3fwd_lookup_struct(const int socketid); void * fib_get_ipv6_l3fwd_lookup_struct(const int socketid); +void +em_free_routes(void); + +void +lpm_free_routes(void); + +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..9058e75a76 100644 --- a/examples/l3fwd/l3fwd_em.c +++ b/examples/l3fwd/l3fwd_em.c @@ -972,6 +972,19 @@ 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 */ +} + +void +em_free_routes(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..6e0054b4cb 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,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); } } diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c index a5b476ced3..9e24ad1e7e 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,233 @@ 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 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++) { + *(route_base_v6[i].ip_8) = *(ipv6_l3fwd_route_array[i].ip); + 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; +} + +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; +} + /* main processing loop */ int lpm_main_loop(__rte_unused void *dummy) @@ -548,13 +785,47 @@ 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) +{ + 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"); + } + } +} + 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 +843,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 +880,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); } } diff --git a/examples/l3fwd/l3fwd_route.h b/examples/l3fwd/l3fwd_route.h index c7eba06c4d..843ffbe9fa 100644 --- a/examples/l3fwd/l3fwd_route.h +++ b/examples/l3fwd/l3fwd_route.h @@ -14,6 +14,23 @@ 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]; 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..8383d8f095 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,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; @@ -1358,6 +1400,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 +1455,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 +1564,9 @@ main(int argc, char **argv) } } + /* clean up config file routes */ + l3fwd_lkp.free_routes(); + /* clean up the EAL */ rte_eal_cleanup(); -- 2.25.1