From: Vladyslav Buslov Date: Tue, 14 Mar 2017 17:17:38 +0000 (+0200) Subject: lpm6: extend next hop field X-Git-Tag: spdx-start~4422 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=d89a5bce1d20068035da613c455d1612c20eec5e;p=dpdk.git lpm6: extend next hop field This patch extend next_hop field from 8-bits to 21-bits in LPM library for IPv6. Added versioning symbols to functions and updated library and applications that have a dependency on LPM library. Signed-off-by: Vladyslav Buslov Acked-by: Bruce Richardson --- diff --git a/doc/guides/prog_guide/lpm6_lib.rst b/doc/guides/prog_guide/lpm6_lib.rst index 0aea5c5c30..f791507336 100644 --- a/doc/guides/prog_guide/lpm6_lib.rst +++ b/doc/guides/prog_guide/lpm6_lib.rst @@ -53,7 +53,7 @@ several thousand IPv6 rules, but the number can vary depending on the case. An LPM prefix is represented by a pair of parameters (128-bit key, depth), with depth in the range of 1 to 128. An LPM rule is represented by an LPM prefix and some user data associated with the prefix. The prefix serves as the unique identifier for the LPM rule. -In this implementation, the user data is 1-byte long and is called "next hop", +In this implementation, the user data is 21-bits long and is called "next hop", which corresponds to its main use of storing the ID of the next hop in a routing table entry. The main methods exported for the LPM component are: diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst index 4b90036ef2..918f483968 100644 --- a/doc/guides/rel_notes/release_17_05.rst +++ b/doc/guides/rel_notes/release_17_05.rst @@ -41,6 +41,9 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Increased number of next hops for LPM IPv6 to 2^21.** + + The next_hop field is extended from 8 bits to 21 bits for IPv6. * **Added powerpc support in pci probing for vfio-pci devices.** @@ -114,6 +117,8 @@ API Changes Also, make sure to start the actual text at the margin. ========================================================= +* The LPM ``next_hop`` field is extended from 8 bits to 21 bits for IPv6 + while keeping ABI compatibility. ABI Changes ----------- diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c index 9e9ecaefb9..1b005b5fd6 100644 --- a/examples/ip_fragmentation/main.c +++ b/examples/ip_fragmentation/main.c @@ -265,8 +265,8 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf, uint8_t queueid, uint8_t port_in) { struct rx_queue *rxq; - uint32_t i, len, next_hop_ipv4; - uint8_t next_hop_ipv6, port_out, ipv6; + uint32_t i, len, next_hop; + uint8_t port_out, ipv6; int32_t len2; ipv6 = 0; @@ -290,9 +290,9 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf, ip_dst = rte_be_to_cpu_32(ip_hdr->dst_addr); /* Find destination port */ - if (rte_lpm_lookup(rxq->lpm, ip_dst, &next_hop_ipv4) == 0 && - (enabled_port_mask & 1 << next_hop_ipv4) != 0) { - port_out = next_hop_ipv4; + if (rte_lpm_lookup(rxq->lpm, ip_dst, &next_hop) == 0 && + (enabled_port_mask & 1 << next_hop) != 0) { + port_out = next_hop; /* Build transmission burst for new port */ len = qconf->tx_mbufs[port_out].len; @@ -326,9 +326,10 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf, ip_hdr = rte_pktmbuf_mtod(m, struct ipv6_hdr *); /* Find destination port */ - if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr, &next_hop_ipv6) == 0 && - (enabled_port_mask & 1 << next_hop_ipv6) != 0) { - port_out = next_hop_ipv6; + if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr, + &next_hop) == 0 && + (enabled_port_mask & 1 << next_hop) != 0) { + port_out = next_hop; /* Build transmission burst for new port */ len = qconf->tx_mbufs[port_out].len; diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c index e62674c5d0..b641576fc9 100644 --- a/examples/ip_reassembly/main.c +++ b/examples/ip_reassembly/main.c @@ -346,8 +346,8 @@ reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue, struct rte_ip_frag_death_row *dr; struct rx_queue *rxq; void *d_addr_bytes; - uint32_t next_hop_ipv4; - uint8_t next_hop_ipv6, dst_port; + uint32_t next_hop; + uint8_t dst_port; rxq = &qconf->rx_queue_list[queue]; @@ -390,9 +390,9 @@ reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue, ip_dst = rte_be_to_cpu_32(ip_hdr->dst_addr); /* Find destination port */ - if (rte_lpm_lookup(rxq->lpm, ip_dst, &next_hop_ipv4) == 0 && - (enabled_port_mask & 1 << next_hop_ipv4) != 0) { - dst_port = next_hop_ipv4; + if (rte_lpm_lookup(rxq->lpm, ip_dst, &next_hop) == 0 && + (enabled_port_mask & 1 << next_hop) != 0) { + dst_port = next_hop; } eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4); @@ -427,9 +427,10 @@ reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue, } /* Find destination port */ - if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr, &next_hop_ipv6) == 0 && - (enabled_port_mask & 1 << next_hop_ipv6) != 0) { - dst_port = next_hop_ipv6; + if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr, + &next_hop) == 0 && + (enabled_port_mask & 1 << next_hop) != 0) { + dst_port = next_hop; } eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv6); diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c index 685feec1fd..d3c229abb6 100644 --- a/examples/ipsec-secgw/ipsec-secgw.c +++ b/examples/ipsec-secgw/ipsec-secgw.c @@ -618,7 +618,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts) static inline void route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts) { - int16_t hop[MAX_PKT_BURST * 2]; + int32_t hop[MAX_PKT_BURST * 2]; uint8_t dst_ip[MAX_PKT_BURST * 2][16]; uint8_t *ip6_dst; uint16_t i, offset; diff --git a/examples/l3fwd/l3fwd_lpm.h b/examples/l3fwd/l3fwd_lpm.h index a43c50703f..258a82fec8 100644 --- a/examples/l3fwd/l3fwd_lpm.h +++ b/examples/l3fwd/l3fwd_lpm.h @@ -49,7 +49,7 @@ lpm_get_ipv4_dst_port(void *ipv4_hdr, uint8_t portid, void *lookup_struct) static inline uint8_t lpm_get_ipv6_dst_port(void *ipv6_hdr, uint8_t portid, void *lookup_struct) { - uint8_t next_hop; + uint32_t next_hop; struct rte_lpm6 *ipv6_l3fwd_lookup_struct = (struct rte_lpm6 *)lookup_struct; diff --git a/examples/l3fwd/l3fwd_lpm_sse.h b/examples/l3fwd/l3fwd_lpm_sse.h index 538fe3d760..aa06b6d343 100644 --- a/examples/l3fwd/l3fwd_lpm_sse.h +++ b/examples/l3fwd/l3fwd_lpm_sse.h @@ -40,8 +40,7 @@ static inline __attribute__((always_inline)) uint16_t lpm_get_dst_port(const struct lcore_conf *qconf, struct rte_mbuf *pkt, uint8_t portid) { - uint32_t next_hop_ipv4; - uint8_t next_hop_ipv6; + uint32_t next_hop; struct ipv6_hdr *ipv6_hdr; struct ipv4_hdr *ipv4_hdr; struct ether_hdr *eth_hdr; @@ -51,9 +50,11 @@ lpm_get_dst_port(const struct lcore_conf *qconf, struct rte_mbuf *pkt, eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); - return (uint16_t) ((rte_lpm_lookup(qconf->ipv4_lookup_struct, - rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop_ipv4) == 0) ? - next_hop_ipv4 : portid); + return (uint16_t) ( + (rte_lpm_lookup(qconf->ipv4_lookup_struct, + rte_be_to_cpu_32(ipv4_hdr->dst_addr), + &next_hop) == 0) ? + next_hop : portid); } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { @@ -61,8 +62,8 @@ lpm_get_dst_port(const struct lcore_conf *qconf, struct rte_mbuf *pkt, ipv6_hdr = (struct ipv6_hdr *)(eth_hdr + 1); return (uint16_t) ((rte_lpm6_lookup(qconf->ipv6_lookup_struct, - ipv6_hdr->dst_addr, &next_hop_ipv6) == 0) - ? next_hop_ipv6 : portid); + ipv6_hdr->dst_addr, &next_hop) == 0) + ? next_hop : portid); } @@ -78,14 +79,13 @@ static inline __attribute__((always_inline)) uint16_t lpm_get_dst_port_with_ipv4(const struct lcore_conf *qconf, struct rte_mbuf *pkt, uint32_t dst_ipv4, uint8_t portid) { - uint32_t next_hop_ipv4; - uint8_t next_hop_ipv6; + uint32_t next_hop; struct ipv6_hdr *ipv6_hdr; struct ether_hdr *eth_hdr; if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { return (uint16_t) ((rte_lpm_lookup(qconf->ipv4_lookup_struct, dst_ipv4, - &next_hop_ipv4) == 0) ? next_hop_ipv4 : portid); + &next_hop) == 0) ? next_hop : portid); } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { @@ -93,8 +93,8 @@ lpm_get_dst_port_with_ipv4(const struct lcore_conf *qconf, struct rte_mbuf *pkt, ipv6_hdr = (struct ipv6_hdr *)(eth_hdr + 1); return (uint16_t) ((rte_lpm6_lookup(qconf->ipv6_lookup_struct, - ipv6_hdr->dst_addr, &next_hop_ipv6) == 0) - ? next_hop_ipv6 : portid); + ipv6_hdr->dst_addr, &next_hop) == 0) + ? next_hop : portid); } diff --git a/examples/performance-thread/l3fwd-thread/main.c b/examples/performance-thread/l3fwd-thread/main.c index 6845e28729..bf92582246 100644 --- a/examples/performance-thread/l3fwd-thread/main.c +++ b/examples/performance-thread/l3fwd-thread/main.c @@ -909,7 +909,7 @@ static inline uint8_t get_ipv6_dst_port(void *ipv6_hdr, uint8_t portid, lookup6_struct_t *ipv6_l3fwd_lookup_struct) { - uint8_t next_hop; + uint32_t next_hop; return (uint8_t) ((rte_lpm6_lookup(ipv6_l3fwd_lookup_struct, ((struct ipv6_hdr *)ipv6_hdr)->dst_addr, &next_hop) == 0) ? @@ -1396,15 +1396,14 @@ rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t ptype) static inline __attribute__((always_inline)) uint16_t get_dst_port(struct rte_mbuf *pkt, uint32_t dst_ipv4, uint8_t portid) { - uint32_t next_hop_ipv4; - uint8_t next_hop_ipv6; + uint32_t next_hop; struct ipv6_hdr *ipv6_hdr; struct ether_hdr *eth_hdr; if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { return (uint16_t) ((rte_lpm_lookup( RTE_PER_LCORE(lcore_conf)->ipv4_lookup_struct, dst_ipv4, - &next_hop_ipv4) == 0) ? next_hop_ipv4 : portid); + &next_hop) == 0) ? next_hop : portid); } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { @@ -1413,8 +1412,8 @@ get_dst_port(struct rte_mbuf *pkt, uint32_t dst_ipv4, uint8_t portid) return (uint16_t) ((rte_lpm6_lookup( RTE_PER_LCORE(lcore_conf)->ipv6_lookup_struct, - ipv6_hdr->dst_addr, &next_hop_ipv6) == 0) ? next_hop_ipv6 : - portid); + ipv6_hdr->dst_addr, &next_hop) == 0) ? + next_hop : portid); } diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c index 32fdba01e8..9cc7be77dd 100644 --- a/lib/librte_lpm/rte_lpm6.c +++ b/lib/librte_lpm/rte_lpm6.c @@ -97,7 +97,7 @@ struct rte_lpm6_tbl_entry { /** Rules tbl entry structure. */ struct rte_lpm6_rule { uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE]; /**< Rule IP address. */ - uint8_t next_hop; /**< Rule next hop. */ + uint32_t next_hop; /**< Rule next hop. */ uint8_t depth; /**< Rule depth. */ }; @@ -297,7 +297,7 @@ rte_lpm6_free(struct rte_lpm6 *lpm) * the nexthop if so. Otherwise it adds a new rule if enough space is available. */ static inline int32_t -rule_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t next_hop, uint8_t depth) +rule_add(struct rte_lpm6 *lpm, uint8_t *ip, uint32_t next_hop, uint8_t depth) { uint32_t rule_index; @@ -340,7 +340,7 @@ rule_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t next_hop, uint8_t depth) */ static void expand_rule(struct rte_lpm6 *lpm, uint32_t tbl8_gindex, uint8_t depth, - uint8_t next_hop) + uint32_t next_hop) { uint32_t tbl8_group_end, tbl8_gindex_next, j; @@ -377,7 +377,7 @@ expand_rule(struct rte_lpm6 *lpm, uint32_t tbl8_gindex, uint8_t depth, static inline int add_step(struct rte_lpm6 *lpm, struct rte_lpm6_tbl_entry *tbl, struct rte_lpm6_tbl_entry **tbl_next, uint8_t *ip, uint8_t bytes, - uint8_t first_byte, uint8_t depth, uint8_t next_hop) + uint8_t first_byte, uint8_t depth, uint32_t next_hop) { uint32_t tbl_index, tbl_range, tbl8_group_start, tbl8_group_end, i; int32_t tbl8_gindex; @@ -507,8 +507,16 @@ add_step(struct rte_lpm6 *lpm, struct rte_lpm6_tbl_entry *tbl, * Add a route */ int -rte_lpm6_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, +rte_lpm6_add_v20(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, uint8_t next_hop) +{ + return rte_lpm6_add_v1705(lpm, ip, depth, next_hop); +} +VERSION_SYMBOL(rte_lpm6_add, _v20, 2.0); + +int +rte_lpm6_add_v1705(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, + uint32_t next_hop) { struct rte_lpm6_tbl_entry *tbl; struct rte_lpm6_tbl_entry *tbl_next; @@ -560,6 +568,10 @@ rte_lpm6_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, return status; } +BIND_DEFAULT_SYMBOL(rte_lpm6_add, _v1705, 17.05); +MAP_STATIC_SYMBOL(int rte_lpm6_add(struct rte_lpm6 *lpm, uint8_t *ip, + uint8_t depth, uint32_t next_hop), + rte_lpm6_add_v1705); /* * Takes a pointer to a table entry and inspect one level. @@ -569,7 +581,7 @@ rte_lpm6_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, static inline int lookup_step(const struct rte_lpm6 *lpm, const struct rte_lpm6_tbl_entry *tbl, const struct rte_lpm6_tbl_entry **tbl_next, uint8_t *ip, - uint8_t first_byte, uint8_t *next_hop) + uint8_t first_byte, uint32_t *next_hop) { uint32_t tbl8_index, tbl_entry; @@ -589,7 +601,7 @@ lookup_step(const struct rte_lpm6 *lpm, const struct rte_lpm6_tbl_entry *tbl, return 1; } else { /* If not extended then we can have a match. */ - *next_hop = (uint8_t)tbl_entry; + *next_hop = ((uint32_t)tbl_entry & RTE_LPM6_TBL8_BITMASK); return (tbl_entry & RTE_LPM6_LOOKUP_SUCCESS) ? 0 : -ENOENT; } } @@ -598,7 +610,26 @@ lookup_step(const struct rte_lpm6 *lpm, const struct rte_lpm6_tbl_entry *tbl, * Looks up an IP */ int -rte_lpm6_lookup(const struct rte_lpm6 *lpm, uint8_t *ip, uint8_t *next_hop) +rte_lpm6_lookup_v20(const struct rte_lpm6 *lpm, uint8_t *ip, uint8_t *next_hop) +{ + uint32_t next_hop32 = 0; + int32_t status; + + /* DEBUG: Check user input arguments. */ + if (next_hop == NULL) + return -EINVAL; + + status = rte_lpm6_lookup_v1705(lpm, ip, &next_hop32); + if (status == 0) + *next_hop = (uint8_t)next_hop32; + + return status; +} +VERSION_SYMBOL(rte_lpm6_lookup, _v20, 2.0); + +int +rte_lpm6_lookup_v1705(const struct rte_lpm6 *lpm, uint8_t *ip, + uint32_t *next_hop) { const struct rte_lpm6_tbl_entry *tbl; const struct rte_lpm6_tbl_entry *tbl_next = NULL; @@ -625,20 +656,23 @@ rte_lpm6_lookup(const struct rte_lpm6 *lpm, uint8_t *ip, uint8_t *next_hop) return status; } +BIND_DEFAULT_SYMBOL(rte_lpm6_lookup, _v1705, 17.05); +MAP_STATIC_SYMBOL(int rte_lpm6_lookup(const struct rte_lpm6 *lpm, uint8_t *ip, + uint32_t *next_hop), rte_lpm6_lookup_v1705); /* * Looks up a group of IP addresses */ int -rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm, +rte_lpm6_lookup_bulk_func_v20(const struct rte_lpm6 *lpm, uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], int16_t * next_hops, unsigned n) { unsigned i; const struct rte_lpm6_tbl_entry *tbl; const struct rte_lpm6_tbl_entry *tbl_next = NULL; - uint32_t tbl24_index; - uint8_t first_byte, next_hop; + uint32_t tbl24_index, next_hop; + uint8_t first_byte; int status; /* DEBUG: Check user input arguments. */ @@ -664,11 +698,59 @@ rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm, if (status < 0) next_hops[i] = -1; else - next_hops[i] = next_hop; + next_hops[i] = (int16_t)next_hop; + } + + return 0; +} +VERSION_SYMBOL(rte_lpm6_lookup_bulk_func, _v20, 2.0); + +int +rte_lpm6_lookup_bulk_func_v1705(const struct rte_lpm6 *lpm, + uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], + int32_t *next_hops, unsigned int n) +{ + unsigned int i; + const struct rte_lpm6_tbl_entry *tbl; + const struct rte_lpm6_tbl_entry *tbl_next = NULL; + uint32_t tbl24_index, next_hop; + uint8_t first_byte; + int status; + + /* DEBUG: Check user input arguments. */ + if ((lpm == NULL) || (ips == NULL) || (next_hops == NULL)) + return -EINVAL; + + for (i = 0; i < n; i++) { + first_byte = LOOKUP_FIRST_BYTE; + tbl24_index = (ips[i][0] << BYTES2_SIZE) | + (ips[i][1] << BYTE_SIZE) | ips[i][2]; + + /* Calculate pointer to the first entry to be inspected */ + tbl = &lpm->tbl24[tbl24_index]; + + do { + /* Continue inspecting following levels + * until success or failure + */ + status = lookup_step(lpm, tbl, &tbl_next, ips[i], + first_byte++, &next_hop); + tbl = tbl_next; + } while (status == 1); + + if (status < 0) + next_hops[i] = -1; + else + next_hops[i] = (int32_t)next_hop; } return 0; } +BIND_DEFAULT_SYMBOL(rte_lpm6_lookup_bulk_func, _v1705, 17.05); +MAP_STATIC_SYMBOL(int rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm, + uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], + int32_t *next_hops, unsigned int n), + rte_lpm6_lookup_bulk_func_v1705); /* * Finds a rule in rule table. @@ -698,8 +780,28 @@ rule_find(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth) * Look for a rule in the high-level rules table */ int -rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, -uint8_t *next_hop) +rte_lpm6_is_rule_present_v20(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, + uint8_t *next_hop) +{ + uint32_t next_hop32 = 0; + int32_t status; + + /* DEBUG: Check user input arguments. */ + if (next_hop == NULL) + return -EINVAL; + + status = rte_lpm6_is_rule_present_v1705(lpm, ip, depth, &next_hop32); + if (status > 0) + *next_hop = (uint8_t)next_hop32; + + return status; + +} +VERSION_SYMBOL(rte_lpm6_is_rule_present, _v20, 2.0); + +int +rte_lpm6_is_rule_present_v1705(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, + uint32_t *next_hop) { uint8_t ip_masked[RTE_LPM6_IPV6_ADDR_SIZE]; int32_t rule_index; @@ -724,6 +826,10 @@ uint8_t *next_hop) /* If rule is not found return 0. */ return 0; } +BIND_DEFAULT_SYMBOL(rte_lpm6_is_rule_present, _v1705, 17.05); +MAP_STATIC_SYMBOL(int rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, + uint8_t *ip, uint8_t depth, uint32_t *next_hop), + rte_lpm6_is_rule_present_v1705); /* * Delete a rule from the rule table. diff --git a/lib/librte_lpm/rte_lpm6.h b/lib/librte_lpm/rte_lpm6.h index 13d027f959..3a3342dacb 100644 --- a/lib/librte_lpm/rte_lpm6.h +++ b/lib/librte_lpm/rte_lpm6.h @@ -39,6 +39,7 @@ */ #include +#include #ifdef __cplusplus extern "C" { @@ -123,7 +124,13 @@ rte_lpm6_free(struct rte_lpm6 *lpm); */ int rte_lpm6_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, + uint32_t next_hop); +int +rte_lpm6_add_v20(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, uint8_t next_hop); +int +rte_lpm6_add_v1705(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, + uint32_t next_hop); /** * Check if a rule is present in the LPM table, @@ -142,7 +149,13 @@ rte_lpm6_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, */ int rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, -uint8_t *next_hop); + uint32_t *next_hop); +int +rte_lpm6_is_rule_present_v20(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, + uint8_t *next_hop); +int +rte_lpm6_is_rule_present_v1705(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, + uint32_t *next_hop); /** * Delete a rule from the LPM table. @@ -199,7 +212,12 @@ rte_lpm6_delete_all(struct rte_lpm6 *lpm); * -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit */ int -rte_lpm6_lookup(const struct rte_lpm6 *lpm, uint8_t *ip, uint8_t *next_hop); +rte_lpm6_lookup(const struct rte_lpm6 *lpm, uint8_t *ip, uint32_t *next_hop); +int +rte_lpm6_lookup_v20(const struct rte_lpm6 *lpm, uint8_t *ip, uint8_t *next_hop); +int +rte_lpm6_lookup_v1705(const struct rte_lpm6 *lpm, uint8_t *ip, + uint32_t *next_hop); /** * Lookup multiple IP addresses in an LPM table. @@ -220,7 +238,15 @@ rte_lpm6_lookup(const struct rte_lpm6 *lpm, uint8_t *ip, uint8_t *next_hop); int rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm, uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], - int16_t * next_hops, unsigned n); + int32_t *next_hops, unsigned int n); +int +rte_lpm6_lookup_bulk_func_v20(const struct rte_lpm6 *lpm, + uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], + int16_t *next_hops, unsigned int n); +int +rte_lpm6_lookup_bulk_func_v1705(const struct rte_lpm6 *lpm, + uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], + int32_t *next_hops, unsigned int n); #ifdef __cplusplus } diff --git a/lib/librte_lpm/rte_lpm_version.map b/lib/librte_lpm/rte_lpm_version.map index 239b371e28..90beac853d 100644 --- a/lib/librte_lpm/rte_lpm_version.map +++ b/lib/librte_lpm/rte_lpm_version.map @@ -34,3 +34,13 @@ DPDK_16.04 { rte_lpm_delete_all; } DPDK_2.0; + +DPDK_17.05 { + global: + + rte_lpm6_add; + rte_lpm6_is_rule_present; + rte_lpm6_lookup; + rte_lpm6_lookup_bulk_func; + +} DPDK_16.04; diff --git a/lib/librte_table/rte_table_lpm_ipv6.c b/lib/librte_table/rte_table_lpm_ipv6.c index 836f4cf6c5..1e1a173a9e 100644 --- a/lib/librte_table/rte_table_lpm_ipv6.c +++ b/lib/librte_table/rte_table_lpm_ipv6.c @@ -211,9 +211,8 @@ rte_table_lpm_ipv6_entry_add( struct rte_table_lpm_ipv6 *lpm = (struct rte_table_lpm_ipv6 *) table; struct rte_table_lpm_ipv6_key *ip_prefix = (struct rte_table_lpm_ipv6_key *) key; - uint32_t nht_pos, nht_pos0_valid; + uint32_t nht_pos, nht_pos0, nht_pos0_valid; int status; - uint8_t nht_pos0; /* Check input parameters */ if (lpm == NULL) { @@ -256,7 +255,7 @@ rte_table_lpm_ipv6_entry_add( /* Add rule to low level LPM table */ if (rte_lpm6_add(lpm->lpm, ip_prefix->ip, ip_prefix->depth, - (uint8_t) nht_pos) < 0) { + nht_pos) < 0) { RTE_LOG(ERR, TABLE, "%s: LPM IPv6 rule add failed\n", __func__); return -1; } @@ -280,7 +279,7 @@ rte_table_lpm_ipv6_entry_delete( struct rte_table_lpm_ipv6 *lpm = (struct rte_table_lpm_ipv6 *) table; struct rte_table_lpm_ipv6_key *ip_prefix = (struct rte_table_lpm_ipv6_key *) key; - uint8_t nht_pos; + uint32_t nht_pos; int status; /* Check input parameters */ @@ -356,7 +355,7 @@ rte_table_lpm_ipv6_lookup( uint8_t *ip = RTE_MBUF_METADATA_UINT8_PTR(pkt, lpm->offset); int status; - uint8_t nht_pos; + uint32_t nht_pos; status = rte_lpm6_lookup(lpm->lpm, ip, &nht_pos); if (status == 0) { diff --git a/test/test/test_lpm6.c b/test/test/test_lpm6.c index 61134f7003..e0e7bf0212 100644 --- a/test/test/test_lpm6.c +++ b/test/test/test_lpm6.c @@ -79,6 +79,7 @@ static int32_t test24(void); static int32_t test25(void); static int32_t test26(void); static int32_t test27(void); +static int32_t test28(void); rte_lpm6_test tests6[] = { /* Test Cases */ @@ -110,6 +111,7 @@ rte_lpm6_test tests6[] = { test25, test26, test27, + test28, }; #define NUM_LPM6_TESTS (sizeof(tests6)/sizeof(tests6[0])) @@ -354,7 +356,7 @@ test6(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t next_hop_return = 0; + uint32_t next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; @@ -392,7 +394,7 @@ test7(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[10][16]; - int16_t next_hop_return[10]; + int32_t next_hop_return[10]; int32_t status = 0; config.max_rules = MAX_RULES; @@ -469,7 +471,8 @@ test9(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t depth = 16, next_hop_add = 100, next_hop_return = 0; + uint8_t depth = 16; + uint32_t next_hop_add = 100, next_hop_return = 0; int32_t status = 0; uint8_t i; @@ -513,7 +516,8 @@ test10(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t depth, next_hop_add = 100; + uint8_t depth; + uint32_t next_hop_add = 100; int32_t status = 0; int i; @@ -557,7 +561,8 @@ test11(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t depth, next_hop_add = 100; + uint8_t depth; + uint32_t next_hop_add = 100; int32_t status = 0; config.max_rules = MAX_RULES; @@ -617,7 +622,8 @@ test12(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t depth, next_hop_add = 100; + uint8_t depth; + uint32_t next_hop_add = 100; int32_t status = 0; config.max_rules = MAX_RULES; @@ -655,7 +661,8 @@ test13(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t depth, next_hop_add = 100; + uint8_t depth; + uint32_t next_hop_add = 100; int32_t status = 0; config.max_rules = 2; @@ -702,7 +709,8 @@ test14(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t depth = 25, next_hop_add = 100; + uint8_t depth = 25; + uint32_t next_hop_add = 100; int32_t status = 0; int i; @@ -748,7 +756,8 @@ test15(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t depth = 24, next_hop_add = 100, next_hop_return = 0; + uint8_t depth = 24; + uint32_t next_hop_add = 100, next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; @@ -784,7 +793,8 @@ test16(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t depth = 128, next_hop_add = 100, next_hop_return = 0; + uint8_t depth = 128; + uint32_t next_hop_add = 100, next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; @@ -828,7 +838,8 @@ test17(void) uint8_t ip1[] = {127,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255}; uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t depth, next_hop_add, next_hop_return; + uint8_t depth; + uint32_t next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; @@ -857,7 +868,7 @@ test17(void) /* Loop with rte_lpm6_delete. */ for (depth = 16; depth >= 1; depth--) { - next_hop_add = (uint8_t) (depth - 1); + next_hop_add = (depth - 1); status = rte_lpm6_delete(lpm, ip2, depth); TEST_LPM_ASSERT(status == 0); @@ -893,8 +904,9 @@ test18(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16], ip_1[16], ip_2[16]; - uint8_t depth, depth_1, depth_2, next_hop_add, next_hop_add_1, - next_hop_add_2, next_hop_return; + uint8_t depth, depth_1, depth_2; + uint32_t next_hop_add, next_hop_add_1, + next_hop_add_2, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; @@ -1055,7 +1067,8 @@ test19(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16]; - uint8_t depth, next_hop_add, next_hop_return; + uint8_t depth; + uint32_t next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; @@ -1253,7 +1266,8 @@ test20(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16]; - uint8_t depth, next_hop_add, next_hop_return; + uint8_t depth; + uint32_t next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; @@ -1320,8 +1334,9 @@ test21(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip_batch[4][16]; - uint8_t depth, next_hop_add; - int16_t next_hop_return[4]; + uint8_t depth; + uint32_t next_hop_add; + int32_t next_hop_return[4]; int32_t status = 0; config.max_rules = MAX_RULES; @@ -1378,8 +1393,9 @@ test22(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip_batch[5][16]; - uint8_t depth[5], next_hop_add; - int16_t next_hop_return[5]; + uint8_t depth[5]; + uint32_t next_hop_add; + int32_t next_hop_return[5]; int32_t status = 0; config.max_rules = MAX_RULES; @@ -1495,7 +1511,8 @@ test23(void) struct rte_lpm6_config config; uint32_t i; uint8_t ip[16]; - uint8_t depth, next_hop_add, next_hop_return; + uint8_t depth; + uint32_t next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; @@ -1579,7 +1596,8 @@ test25(void) struct rte_lpm6_config config; uint8_t ip[16]; uint32_t i; - uint8_t depth, next_hop_add, next_hop_return, next_hop_expected; + uint8_t depth; + uint32_t next_hop_add, next_hop_return, next_hop_expected; int32_t status = 0; config.max_rules = MAX_RULES; @@ -1632,10 +1650,10 @@ test26(void) uint8_t d_ip_10_32 = 32; uint8_t d_ip_10_24 = 24; uint8_t d_ip_20_25 = 25; - uint8_t next_hop_ip_10_32 = 100; - uint8_t next_hop_ip_10_24 = 105; - uint8_t next_hop_ip_20_25 = 111; - uint8_t next_hop_return = 0; + uint32_t next_hop_ip_10_32 = 100; + uint32_t next_hop_ip_10_24 = 105; + uint32_t next_hop_ip_20_25 = 111; + uint32_t next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; @@ -1650,7 +1668,7 @@ test26(void) return -1; status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return); - uint8_t test_hop_10_32 = next_hop_return; + uint32_t test_hop_10_32 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32); @@ -1659,7 +1677,7 @@ test26(void) return -1; status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return); - uint8_t test_hop_10_24 = next_hop_return; + uint32_t test_hop_10_24 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24); @@ -1668,7 +1686,7 @@ test26(void) return -1; status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return); - uint8_t test_hop_20_25 = next_hop_return; + uint32_t test_hop_20_25 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25); @@ -1707,7 +1725,8 @@ test27(void) struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0}; - uint8_t depth = 128, next_hop_add = 100, next_hop_return; + uint8_t depth = 128; + uint32_t next_hop_add = 100, next_hop_return; int32_t status = 0; int i, j; @@ -1745,6 +1764,42 @@ test27(void) return PASS; } +/* + * Call add, lookup and delete for a single rule with maximum 21bit next_hop + * size. + * Check that next_hop returned from lookup is equal to provisioned value. + * Delete the rule and check that the same test returs a miss. + */ +int32_t +test28(void) +{ + struct rte_lpm6 *lpm = NULL; + struct rte_lpm6_config config; + uint8_t ip[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t depth = 16; + uint32_t next_hop_add = 0x001FFFFF, next_hop_return = 0; + int32_t status = 0; + + config.max_rules = MAX_RULES; + config.number_tbl8s = NUMBER_TBL8S; + config.flags = 0; + + lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); + TEST_LPM_ASSERT(lpm != NULL); + + status = rte_lpm6_add(lpm, ip, depth, next_hop_add); + TEST_LPM_ASSERT(status == 0); + + status = rte_lpm6_lookup(lpm, ip, &next_hop_return); + TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); + + status = rte_lpm6_delete(lpm, ip, depth); + TEST_LPM_ASSERT(status == 0); + rte_lpm6_free(lpm); + + return PASS; +} + /* * Do all unit tests. */ diff --git a/test/test/test_lpm6_perf.c b/test/test/test_lpm6_perf.c index 0723081bb5..30be430f7c 100644 --- a/test/test/test_lpm6_perf.c +++ b/test/test/test_lpm6_perf.c @@ -86,7 +86,7 @@ test_lpm6_perf(void) struct rte_lpm6_config config; uint64_t begin, total_time; unsigned i, j; - uint8_t next_hop_add = 0xAA, next_hop_return = 0; + uint32_t next_hop_add = 0xAA, next_hop_return = 0; int status = 0; int64_t count = 0; @@ -148,7 +148,7 @@ test_lpm6_perf(void) count = 0; uint8_t ip_batch[NUM_IPS_ENTRIES][16]; - int16_t next_hops[NUM_IPS_ENTRIES]; + int32_t next_hops[NUM_IPS_ENTRIES]; for (i = 0; i < NUM_IPS_ENTRIES; i++) memcpy(ip_batch[i], large_ips_table[i].ip, 16);