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; From patchwork Thu Dec 16 15:01:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Morrissey X-Patchwork-Id: 105162 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 C6018A0032; Thu, 16 Dec 2021 16:02:48 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 005A841148; Thu, 16 Dec 2021 16:02:44 +0100 (CET) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mails.dpdk.org (Postfix) with ESMTP id B953E4114F for ; Thu, 16 Dec 2021 16:02:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1639666961; x=1671202961; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=lKkjCkQF2HeupsXLdwHekK9OPKHhlUoHJ7geU8o++fE=; b=XSxVtAoJ4Y8USqL4JoUZoMyNBReiBCx1sAO9Di19fOjE3+Eo7gwpOw3a 7NOqYPwl4S4uQUg+X1GigO6I5jIvXYk8EqlERxhoEUlOCJApOtGCjckOV uexc9XMTzd6FVnEe99es+hIAOd2GbCwOjzE5ZK0Vb4w0k/p8Rx94M+QqX bDPahVZXHJSed3BV1dFsuiGmdWy6X5KKu4xzYRrVVkeTDo7gbV6GYmOxi ACJrHR2obmpf8jCc9luZC14jKLfxG/cGifpmHTbIhmAY3v9HAwO6Kzad3 LS2zwBd7x1q9gmUv059YjkAC+ALT2uUVk3Rd8w/osB067Z+1h5n6HitJY g==; X-IronPort-AV: E=McAfee;i="6200,9189,10199"; a="325793918" X-IronPort-AV: E=Sophos;i="5.88,211,1635231600"; d="scan'208";a="325793918" 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:50 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,211,1635231600"; d="scan'208";a="615181606" Received: from silpixa00401215.ir.intel.com ([10.55.128.96]) by orsmga004.jf.intel.com with ESMTP; 16 Dec 2021 07:01:42 -0800 From: Sean Morrissey To: Cc: dev@dpdk.org, Sean Morrissey , Ravi Kerur Subject: [PATCH v1 2/2] examples/l3fwd: add config file support for EM Date: Thu, 16 Dec 2021 15:01:04 +0000 Message-Id: <20211216150104.860924-3-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 EM with a format similar to l3fwd-acl one. With the removal of the hardcoded route tables for IPv4 and IPv6 from 'l3fwd_em', these routes have been moved to a separate default config file for use with EM. Related l3fwd docs have been updated to relfect these changes. Signed-off-by: Sean Morrissey Signed-off-by: Ravi Kerur --- doc/guides/sample_app_ug/l3_forward.rst | 89 +++-- examples/l3fwd/em_default_v4.cfg | 17 + examples/l3fwd/em_default_v6.cfg | 17 + examples/l3fwd/l3fwd_em.c | 473 ++++++++++++++---------- examples/l3fwd/l3fwd_route.h | 38 +- 5 files changed, 412 insertions(+), 222 deletions(-) create mode 100644 examples/l3fwd/em_default_v4.cfg create mode 100644 examples/l3fwd/em_default_v6.cfg diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst index 6d7d7c5cc1..01d86db95d 100644 --- a/doc/guides/sample_app_ug/l3_forward.rst +++ b/doc/guides/sample_app_ug/l3_forward.rst @@ -47,6 +47,7 @@ and loaded into the LPM or FIB object at initialization time. In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only. +During the initialization phase route rules for IPv4 and IPv6 are read from rule files. Compiling the Application ------------------------- @@ -61,6 +62,8 @@ Running the Application The application has a number of command line options:: ./dpdk-l3fwd [EAL options] -- -p PORTMASK + --rule_ipv4=FILE + --rule_ipv6=FILE [-P] [--lookup LOOKUP_METHOD] --config(port,queue,lcore)[,(port,queue,lcore)] @@ -82,6 +85,11 @@ Where, * ``-p PORTMASK:`` Hexadecimal bitmask of ports to configure +* ``--rule_ipv4=FILE:`` specify the ipv4 rules entries file. + Each rule occupies one line. + +* ``--rule_ipv6=FILE:`` specify the ipv6 rules entries file. + * ``-P:`` Optional, sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address. Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted. @@ -135,7 +143,7 @@ To enable L3 forwarding between two ports, assuming that both ports are in the s .. code-block:: console - .//examples/dpdk-l3fwd -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" + .//examples/dpdk-l3fwd -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --rule_ipv4="rule_ipv4.cfg" --rule_ipv6="rule_ipv6.cfg" In this command: @@ -157,19 +165,23 @@ In this command: | | | | | +----------+-----------+-----------+-------------------------------------+ +* The -rule_ipv4 option specifies the reading of IPv4 rules sets from the rule_ipv4.cfg file + +* The -rule_ipv6 option specifies the reading of IPv6 rules sets from the rule_ipv6.cfg file. + To use eventdev mode with sync method **ordered** on above mentioned environment, Following is the sample command: .. code-block:: console - .//examples/dpdk-l3fwd -l 0-3 -n 4 -a -- -p 0x3 --eventq-sched=ordered + .//examples/dpdk-l3fwd -l 0-3 -n 4 -a -- -p 0x3 --eventq-sched=ordered --rule_ipv4="rule_ipv4.cfg" --rule_ipv6="rule_ipv6.cfg" or .. code-block:: console .//examples/dpdk-l3fwd -l 0-3 -n 4 -a \ - -- -p 0x03 --mode=eventdev --eventq-sched=ordered + -- -p 0x03 --mode=eventdev --eventq-sched=ordered --rule_ipv4="rule_ipv4.cfg" --rule_ipv6="rule_ipv6.cfg" In this command: @@ -192,7 +204,7 @@ scheduler. Following is the sample command: .. code-block:: console - .//examples/dpdk-l3fwd -l 0-7 -s 0xf0000 -n 4 --vdev event_sw0 -- -p 0x3 --mode=eventdev --eventq-sched=ordered + .//examples/dpdk-l3fwd -l 0-7 -s 0xf0000 -n 4 --vdev event_sw0 -- -p 0x3 --mode=eventdev --eventq-sched=ordered --rule_ipv4="rule_ipv4.cfg" --rule_ipv6="rule_ipv6.cfg" In case of eventdev mode, *--config* option is not used for ethernet port configuration. Instead each ethernet port will be configured with mentioned @@ -216,6 +228,49 @@ The following sections provide some explanation of the sample application code. the initialization and run-time paths are very similar to those of the :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`. The following sections describe aspects that are specific to the L3 Forwarding sample application. +Parse Rules from File +~~~~~~~~~~~~~~~~~~~~~ + +The application parses the rules from the file and adds them to the appropriate route table by calling the appropriate function. +It ignores empty and comment lines, and parses and validates the rules it reads. +If errors are detected, the application exits with messages to identify the errors encountered. + +The format of the route rules differs based on which lookup method is being used. +Therefore, the code only decreases the priority number with each rule it parses. +Route rules are mandatory. +To read data from the specified file successfully, the application assumes the following: + +* Each rule occupies a single line. + +* Only the following four rule line types are valid in this application: + +* Route rule line, which starts with a leading character 'R' + +* Comment line, which starts with a leading character '#' + +* Empty line, which consists of a space, form-feed ('\f'), newline ('\n'), + carriage return ('\r'), horizontal tab ('\t'), or vertical tab ('\v'). + +Other lines types are considered invalid. + +* Rules are organized in descending order of priority, + which means rules at the head of the file always have a higher priority than those further down in the file. + +* A typical IPv4 LPM/FIB rule line should have a format as shown below: + +R/ + +* A typical IPv4 EM rule line should have a format as shown below: + +R + +IPv4 addresses are specified in CIDR format as specified in RFC 4632. +For LPM/FIB they consist of the dot notation for the address and a prefix length separated by '/'. +For example, 192.168.0.34/32, where the address is 192.168.0.34 and the prefix length is 32. +For EM they consist of just the dot notation for the address and no prefix length. +For example, 192.168.0.34, where the Address is 192.168.0.34. +EM also includes ports which are specified as a single number which represents a single port. + Hash Initialization ~~~~~~~~~~~~~~~~~~~ @@ -227,8 +282,6 @@ for the convenience to execute hash performance test on 4M/8M/16M flows. The Hash initialization will setup both ipv4 and ipv6 hash table, and populate the either table depending on the value of variable ipv6. - To support the hash performance test with up to 8M single direction flows/16M bi-direction flows, - populate_ipv4_many_flow_into_table() function will populate the hash table with specified hash table entry number(default 4M). .. note:: @@ -246,22 +299,14 @@ for the convenience to execute hash performance test on 4M/8M/16M flows. { // ... - if (hash_entry_number != HASH_ENTRY_NUMBER_DEFAULT) { - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_many_flow_into_table(ipv4_l3fwd_lookup_struct[socketid], hash_entry_number); - } else { - /* populate the ipv6 hash */ - populate_ipv6_many_flow_into_table( ipv6_l3fwd_lookup_struct[socketid], hash_entry_number); - } - } else - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_few_flow_into_table(ipv4_l3fwd_lookup_struct[socketid]); - } else { - /* populate the ipv6 hash */ - populate_ipv6_few_flow_into_table(ipv6_l3fwd_lookup_struct[socketid]); - } + if (ipv6 == 0) { + /* populate the ipv4 hash */ + populate_ipv4_flow_into_table( + ipv4_l3fwd_em_lookup_struct[socketid]); + } else { + /* populate the ipv6 hash */ + populate_ipv6_flow_into_table( + ipv6_l3fwd_em_lookup_struct[socketid]); } } #endif diff --git a/examples/l3fwd/em_default_v4.cfg b/examples/l3fwd/em_default_v4.cfg new file mode 100644 index 0000000000..b70bdb6601 --- /dev/null +++ b/examples/l3fwd/em_default_v4.cfg @@ -0,0 +1,17 @@ +#Copy of hard-coded IPv4 FWD table for L3FWD EM +R198.18.0.0 198.18.0.1 9 9 0x11 0 +R198.18.1.0 198.18.1.1 9 9 0x11 1 +R198.18.2.0 198.18.2.1 9 9 0x11 2 +R198.18.3.0 198.18.3.1 9 9 0x11 3 +R198.18.4.0 198.18.4.1 9 9 0x11 4 +R198.18.5.0 198.18.5.1 9 9 0x11 5 +R198.18.6.0 198.18.6.1 9 9 0x11 6 +R198.18.7.0 198.18.7.1 9 9 0x11 7 +R198.18.8.0 198.18.8.1 9 9 0x11 8 +R198.18.9.0 198.18.9.1 9 9 0x11 9 +R198.18.10.0 198.18.10.1 9 9 0x11 10 +R198.18.11.0 198.18.11.1 9 9 0x11 11 +R198.18.12.0 198.18.12.1 9 9 0x11 12 +R198.18.13.0 198.18.13.1 9 9 0x11 13 +R198.18.14.0 198.18.14.1 9 9 0x11 14 +R198.18.15.0 198.18.15.1 9 9 0x11 15 diff --git a/examples/l3fwd/em_default_v6.cfg b/examples/l3fwd/em_default_v6.cfg new file mode 100644 index 0000000000..a18519ff2d --- /dev/null +++ b/examples/l3fwd/em_default_v6.cfg @@ -0,0 +1,17 @@ +#Copy of hard-coded IPv4 FWD table for L3FWD EM +R2001:0200:0000:0000:0000:0000:0000:0000 2001:0200:0000:0000:0000:0000:0000:0001 9 9 0x11 0 +R2001:0200:0000:0001:0000:0000:0000:0000 2001:0200:0000:0001:0000:0000:0000:0001 9 9 0x11 1 +R2001:0200:0000:0002:0000:0000:0000:0000 2001:0200:0000:0002:0000:0000:0000:0001 9 9 0x11 2 +R2001:0200:0000:0003:0000:0000:0000:0000 2001:0200:0000:0003:0000:0000:0000:0001 9 9 0x11 3 +R2001:0200:0000:0004:0000:0000:0000:0000 2001:0200:0000:0004:0000:0000:0000:0001 9 9 0x11 4 +R2001:0200:0000:0005:0000:0000:0000:0000 2001:0200:0000:0005:0000:0000:0000:0001 9 9 0x11 5 +R2001:0200:0000:0006:0000:0000:0000:0000 2001:0200:0000:0006:0000:0000:0000:0001 9 9 0x11 6 +R2001:0200:0000:0007:0000:0000:0000:0000 2001:0200:0000:0007:0000:0000:0000:0001 9 9 0x11 7 +R2001:0200:0000:0008:0000:0000:0000:0000 2001:0200:0000:0008:0000:0000:0000:0001 9 9 0x11 8 +R2001:0200:0000:0009:0000:0000:0000:0000 2001:0200:0000:0009:0000:0000:0000:0001 9 9 0x11 9 +R2001:0200:0000:000A:0000:0000:0000:0000 2001:0200:0000:000A:0000:0000:0000:0001 9 9 0x11 10 +R2001:0200:0000:000B:0000:0000:0000:0000 2001:0200:0000:000B:0000:0000:0000:0001 9 9 0x11 11 +R2001:0200:0000:000C:0000:0000:0000:0000 2001:0200:0000:000C:0000:0000:0000:0001 9 9 0x11 12 +R2001:0200:0000:000D:0000:0000:0000:0000 2001:0200:0000:000D:0000:0000:0000:0001 9 9 0x11 13 +R2001:0200:0000:000E:0000:0000:0000:0000 2001:0200:0000:000E:0000:0000:0000:0001 9 9 0x11 14 +R2001:0200:0000:000F:0000:0000:0000:0000 2001:0200:0000:000F:0000:0000:0000:0001 9 9 0x11 15 diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c index 4953cdae4e..9a337ed842 100644 --- a/examples/l3fwd/l3fwd_em.c +++ b/examples/l3fwd/l3fwd_em.c @@ -27,6 +27,7 @@ #include "l3fwd.h" #include "l3fwd_event.h" +#include "l3fwd_route.h" #if defined(RTE_ARCH_X86) || defined(__ARM_FEATURE_CRC32) #define EM_HASH_CRC 1 @@ -42,13 +43,18 @@ #define IPV6_ADDR_LEN 16 -struct ipv4_5tuple { - uint32_t ip_dst; - uint32_t ip_src; - uint16_t port_dst; - uint16_t port_src; - uint8_t proto; -} __rte_packed; +static struct em_rule *em_route_base_v4; +static struct em_rule *em_route_base_v6; + +enum { + CB_FLD_DST_ADDR, + CB_FLD_SRC_ADDR, + CB_FLD_DST_PORT, + CB_FLD_SRC_PORT, + CB_FLD_PROTO, + CB_FLD_IF_OUT, + CB_FLD_MAX +}; union ipv4_5tuple_host { struct { @@ -65,14 +71,6 @@ union ipv4_5tuple_host { #define XMM_NUM_IN_IPV6_5TUPLE 3 -struct ipv6_5tuple { - uint8_t ip_dst[IPV6_ADDR_LEN]; - uint8_t ip_src[IPV6_ADDR_LEN]; - uint16_t port_dst; - uint16_t port_src; - uint8_t proto; -} __rte_packed; - union ipv6_5tuple_host { struct { uint16_t pad0; @@ -87,8 +85,6 @@ union ipv6_5tuple_host { xmm_t xmm[XMM_NUM_IN_IPV6_5TUPLE]; }; - - struct ipv4_l3fwd_em_route { struct ipv4_5tuple key; uint8_t if_out; @@ -99,66 +95,6 @@ struct ipv6_l3fwd_em_route { uint8_t if_out; }; -/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). - * Use RFC863 Discard Protocol. - */ -static 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, 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, 3, 0), RTE_IPV4(198, 18, 3, 1), 9, 9, IPPROTO_UDP}, 3}, - {{RTE_IPV4(198, 18, 4, 0), RTE_IPV4(198, 18, 4, 1), 9, 9, IPPROTO_UDP}, 4}, - {{RTE_IPV4(198, 18, 5, 0), RTE_IPV4(198, 18, 5, 1), 9, 9, IPPROTO_UDP}, 5}, - {{RTE_IPV4(198, 18, 6, 0), RTE_IPV4(198, 18, 6, 1), 9, 9, IPPROTO_UDP}, 6}, - {{RTE_IPV4(198, 18, 7, 0), RTE_IPV4(198, 18, 7, 1), 9, 9, IPPROTO_UDP}, 7}, - {{RTE_IPV4(198, 18, 8, 0), RTE_IPV4(198, 18, 8, 1), 9, 9, IPPROTO_UDP}, 8}, - {{RTE_IPV4(198, 18, 9, 0), RTE_IPV4(198, 18, 9, 1), 9, 9, IPPROTO_UDP}, 9}, - {{RTE_IPV4(198, 18, 10, 0), RTE_IPV4(198, 18, 10, 1), 9, 9, IPPROTO_UDP}, 10}, - {{RTE_IPV4(198, 18, 11, 0), RTE_IPV4(198, 18, 11, 1), 9, 9, IPPROTO_UDP}, 11}, - {{RTE_IPV4(198, 18, 12, 0), RTE_IPV4(198, 18, 12, 1), 9, 9, IPPROTO_UDP}, 12}, - {{RTE_IPV4(198, 18, 13, 0), RTE_IPV4(198, 18, 13, 1), 9, 9, IPPROTO_UDP}, 13}, - {{RTE_IPV4(198, 18, 14, 0), RTE_IPV4(198, 18, 14, 1), 9, 9, IPPROTO_UDP}, 14}, - {{RTE_IPV4(198, 18, 15, 0), RTE_IPV4(198, 18, 15, 1), 9, 9, IPPROTO_UDP}, 15}, -}; - -/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180). - * Use RFC863 Discard Protocol. - */ -static 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, 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, 1}, 9, 9, IPPROTO_UDP}, 1}, - {{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 2}, - {{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 3}, - {{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 4}, - {{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 5}, - {{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 6}, - {{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 7}, - {{{32, 1, 2, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 8}, - {{{32, 1, 2, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 9}, - {{{32, 1, 2, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 10}, - {{{32, 1, 2, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 11}, - {{{32, 1, 2, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 12}, - {{{32, 1, 2, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 13}, - {{{32, 1, 2, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 14}, - {{{32, 1, 2, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0}, - {32, 1, 2, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1}, 9, 9, IPPROTO_UDP}, 15}, -}; - struct rte_hash *ipv4_l3fwd_em_lookup_struct[NB_SOCKETS]; struct rte_hash *ipv6_l3fwd_em_lookup_struct[NB_SOCKETS]; @@ -235,10 +171,6 @@ ipv6_hash_crc(const void *data, __rte_unused uint32_t data_len, return init_val; } -#define IPV4_L3FWD_EM_NUM_ROUTES RTE_DIM(ipv4_l3fwd_em_route_array) - -#define IPV6_L3FWD_EM_NUM_ROUTES RTE_DIM(ipv6_l3fwd_em_route_array) - static uint8_t ipv4_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; static uint8_t ipv6_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; @@ -346,6 +278,178 @@ em_get_ipv6_dst_port(void *ipv6_hdr, uint16_t portid, void *lookup_struct) #include "l3fwd_em.h" #endif +static int +em_parse_v6_net(const char *in, uint32_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; + uint32_t ip[4]; + 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; + } + + ip[0] = *(v->v6_key.ip32_dst); + rc = em_parse_v6_net(in[CB_FLD_DST_ADDR], ip); + if (rc != 0) + return rc; + ip[0] = *(v->v6_key.ip32_src); + rc = em_parse_v6_net(in[CB_FLD_SRC_ADDR], ip); + 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 void convert_ipv4_5tuple(struct ipv4_5tuple *key1, union ipv4_5tuple_host *key2) @@ -382,122 +486,92 @@ convert_ipv6_5tuple(struct ipv6_5tuple *key1, #define BIT_8_TO_15 0x0000ff00 static inline void -populate_ipv4_few_flow_into_table(const struct rte_hash *h) +populate_ipv4_flow_into_table(const struct rte_hash *h) { - uint32_t i; + int i; int32_t ret; + struct rte_eth_dev_info dev_info; + char srcbuf[INET6_ADDRSTRLEN]; + char dstbuf[INET6_ADDRSTRLEN]; mask0 = (rte_xmm_t){.u32 = {BIT_8_TO_15, ALL_32_BITS, ALL_32_BITS, ALL_32_BITS} }; - for (i = 0; i < IPV4_L3FWD_EM_NUM_ROUTES; i++) { - struct ipv4_l3fwd_em_route entry; + for (i = 0; i < route_num_v4; i++) { + struct em_rule *entry; union ipv4_5tuple_host newkey; + struct in_addr src; + struct in_addr dst; - entry = ipv4_l3fwd_em_route_array[i]; - convert_ipv4_5tuple(&entry.key, &newkey); + if ((1 << em_route_base_v4[i].if_out & + 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); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32 " to the l3fwd hash.\n", i); } - ipv4_l3fwd_out_if[ret] = entry.if_out; + ipv4_l3fwd_out_if[ret] = entry->if_out; + rte_eth_dev_info_get(em_route_base_v4[i].if_out, + &dev_info); + + 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) [%s]\n", + inet_ntop(AF_INET, &dst, dstbuf, sizeof(dstbuf)), + inet_ntop(AF_INET, &src, srcbuf, sizeof(srcbuf)), + em_route_base_v4[i].if_out, dev_info.device->name); } printf("Hash: Adding 0x%" PRIx64 " keys\n", - (uint64_t)IPV4_L3FWD_EM_NUM_ROUTES); + (uint64_t)route_num_v4); } #define BIT_16_TO_23 0x00ff0000 static inline void -populate_ipv6_few_flow_into_table(const struct rte_hash *h) +populate_ipv6_flow_into_table(const struct rte_hash *h) { - uint32_t i; + int i; int32_t ret; + struct rte_eth_dev_info dev_info; + char srcbuf[INET6_ADDRSTRLEN]; + char dstbuf[INET6_ADDRSTRLEN]; mask1 = (rte_xmm_t){.u32 = {BIT_16_TO_23, ALL_32_BITS, ALL_32_BITS, ALL_32_BITS} }; mask2 = (rte_xmm_t){.u32 = {ALL_32_BITS, ALL_32_BITS, 0, 0} }; - for (i = 0; i < IPV6_L3FWD_EM_NUM_ROUTES; i++) { - struct ipv6_l3fwd_em_route entry; + for (i = 0; i < route_num_v6; i++) { + struct em_rule *entry; union ipv6_5tuple_host newkey; - entry = ipv6_l3fwd_em_route_array[i]; - convert_ipv6_5tuple(&entry.key, &newkey); + if ((1 << em_route_base_v6[i].if_out & + enabled_port_mask) == 0) + continue; + + entry = &em_route_base_v6[i]; + convert_ipv6_5tuple(&(entry->v6_key), &newkey); ret = rte_hash_add_key(h, (void *) &newkey); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32 " to the l3fwd hash.\n", i); } - ipv6_l3fwd_out_if[ret] = entry.if_out; + ipv6_l3fwd_out_if[ret] = entry->if_out; + rte_eth_dev_info_get(em_route_base_v6[i].if_out, + &dev_info); + + printf("EM: Adding route %s %s (%d) [%s]\n", + inet_ntop(AF_INET6, em_route_base_v6[i].v6_key.ip32_dst, + dstbuf, sizeof(dstbuf)), + inet_ntop(AF_INET6, em_route_base_v6[i].v6_key.ip32_src, + srcbuf, sizeof(srcbuf)), + em_route_base_v6[i].if_out, dev_info.device->name); } printf("Hash: Adding 0x%" PRIx64 "keys\n", - (uint64_t)IPV6_L3FWD_EM_NUM_ROUTES); -} - -#define NUMBER_PORT_USED 16 -static inline void -populate_ipv4_many_flow_into_table(const struct rte_hash *h, - unsigned int nr_flow) -{ - unsigned i; - - mask0 = (rte_xmm_t){.u32 = {BIT_8_TO_15, ALL_32_BITS, - ALL_32_BITS, ALL_32_BITS} }; - - for (i = 0; i < nr_flow; i++) { - uint8_t port = i % NUMBER_PORT_USED; - struct ipv4_l3fwd_em_route entry; - union ipv4_5tuple_host newkey; - - uint8_t a = (uint8_t)((port + 1) % BYTE_VALUE_MAX); - - /* Create the ipv4 exact match flow */ - memset(&entry, 0, sizeof(entry)); - entry = ipv4_l3fwd_em_route_array[port]; - entry.key.ip_dst = RTE_IPV4(198, 18, port, a); - convert_ipv4_5tuple(&entry.key, &newkey); - int32_t ret = rte_hash_add_key(h, (void *) &newkey); - - if (ret < 0) - rte_exit(EXIT_FAILURE, "Unable to add entry %u\n", i); - - ipv4_l3fwd_out_if[ret] = (uint8_t) entry.if_out; - - } - printf("Hash: Adding 0x%x keys\n", nr_flow); -} - -static inline void -populate_ipv6_many_flow_into_table(const struct rte_hash *h, - unsigned int nr_flow) -{ - unsigned i; - - mask1 = (rte_xmm_t){.u32 = {BIT_16_TO_23, ALL_32_BITS, - ALL_32_BITS, ALL_32_BITS} }; - mask2 = (rte_xmm_t){.u32 = {ALL_32_BITS, ALL_32_BITS, 0, 0} }; - - for (i = 0; i < nr_flow; i++) { - uint8_t port = i % NUMBER_PORT_USED; - struct ipv6_l3fwd_em_route entry; - union ipv6_5tuple_host newkey; - - /* Create the ipv6 exact match flow */ - memset(&entry, 0, sizeof(entry)); - entry = ipv6_l3fwd_em_route_array[port]; - entry.key.ip_dst[15] = (port + 1) % BYTE_VALUE_MAX; - convert_ipv6_5tuple(&entry.key, &newkey); - int32_t ret = rte_hash_add_key(h, (void *) &newkey); - - if (ret < 0) - rte_exit(EXIT_FAILURE, "Unable to add entry %u\n", i); - - ipv6_l3fwd_out_if[ret] = (uint8_t) entry.if_out; - - } - printf("Hash: Adding 0x%x keys\n", nr_flow); + (uint64_t)route_num_v6); } /* Requirements: @@ -972,17 +1046,53 @@ em_event_main_loop_tx_q_burst_vector(__rte_unused void *dummy) return 0; } +static void +free_em_routes(void) +{ + free(em_route_base_v4); + free(em_route_base_v6); + em_route_base_v4 = NULL; + em_route_base_v6 = NULL; + route_num_v4 = 0; + route_num_v6 = 0; +} + /* Load rules from the input file */ void read_config_files_em(void) { - /* Empty till config file support added to EM */ + /* ipv4 check */ + if (parm_config.rule_ipv4_name != NULL) { + route_num_v4 = em_add_rules(parm_config.rule_ipv4_name, + &em_route_base_v4, &em_parse_v4_rule); + if (route_num_v4 < 0) { + free_em_routes(); + rte_exit(EXIT_FAILURE, "Failed to add EM IPv4 rules\n"); + } + } else { + RTE_LOG(ERR, L3FWD, "EM IPv4 rule file not specified\n"); + rte_exit(EXIT_FAILURE, "Failed to get valid EM options\n"); + } + + /* ipv6 check */ + if (parm_config.rule_ipv6_name != NULL) { + route_num_v6 = em_add_rules(parm_config.rule_ipv6_name, + &em_route_base_v6, &em_parse_v6_rule); + if (route_num_v6 < 0) { + free_em_routes(); + rte_exit(EXIT_FAILURE, "Failed to add EM IPv6 rules\n"); + } + } else { + RTE_LOG(ERR, L3FWD, "EM IPv6 rule file not specified\n"); + rte_exit(EXIT_FAILURE, "Failed to get valid EM options\n"); + } } /* Initialize exact match (hash) parameters. 8< */ void setup_hash(const int socketid) { + printf("IPPPROTO_UDP: %d\n", IPPROTO_UDP); struct rte_hash_parameters ipv4_l3fwd_hash_params = { .name = NULL, .entries = L3FWD_HASH_ENTRIES, @@ -1023,35 +1133,18 @@ setup_hash(const int socketid) "Unable to create the l3fwd hash on socket %d\n", socketid); - if (hash_entry_number != HASH_ENTRY_NUMBER_DEFAULT) { - /* For testing hash matching with a large number of flows we - * generate millions of IP 5-tuples with an incremented dst - * address to initialize the hash table. */ - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_many_flow_into_table( - ipv4_l3fwd_em_lookup_struct[socketid], - hash_entry_number); - } else { - /* populate the ipv6 hash */ - populate_ipv6_many_flow_into_table( - ipv6_l3fwd_em_lookup_struct[socketid], - hash_entry_number); - } + /* + * Use data from ipv4/ipv6 l3fwd config file + * directly to initialize the hash table. + */ + if (ipv6 == 0) { + /* populate the ipv4 hash */ + populate_ipv4_flow_into_table( + ipv4_l3fwd_em_lookup_struct[socketid]); } else { - /* - * Use data in ipv4/ipv6 l3fwd lookup table - * directly to initialize the hash table. - */ - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_few_flow_into_table( - ipv4_l3fwd_em_lookup_struct[socketid]); - } else { - /* populate the ipv6 hash */ - populate_ipv6_few_flow_into_table( - ipv6_l3fwd_em_lookup_struct[socketid]); - } + /* populate the ipv6 hash */ + populate_ipv6_flow_into_table( + ipv6_l3fwd_em_lookup_struct[socketid]); } } /* >8 End of initialization of hash parameters. */ diff --git a/examples/l3fwd/l3fwd_route.h b/examples/l3fwd/l3fwd_route.h index 6d41c926b1..a3ac991407 100644 --- a/examples/l3fwd/l3fwd_route.h +++ b/examples/l3fwd/l3fwd_route.h @@ -2,17 +2,27 @@ * Copyright(c) 2021 Intel Corporation */ -struct ipv4_l3fwd_route { - uint32_t ip; - uint8_t depth; - 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_l3fwd_route { - uint8_t ip[16]; - uint8_t depth; - uint8_t if_out; -}; +struct ipv6_5tuple { + union { + uint8_t ip_dst[IPV6_ADDR_LEN]; + uint32_t ip32_dst[4]; + }; + union { + uint8_t ip_src[IPV6_ADDR_LEN]; + uint32_t ip32_src[4]; + }; + uint16_t port_dst; + uint16_t port_src; + uint8_t proto; +} __rte_packed; struct lpm_route_rule { union { @@ -26,6 +36,14 @@ struct lpm_route_rule { uint8_t if_out; }; +struct em_rule { + union { + struct ipv4_5tuple v4_key; + struct ipv6_5tuple v6_key; + }; + uint8_t if_out; +}; + extern struct lpm_route_rule *route_base_v4; extern struct lpm_route_rule *route_base_v6; extern int route_num_v4;