summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladyslav Buslov <vladyslav.buslov@harmonicinc.com>2017-03-14 19:17:38 +0200
committerThomas Monjalon <thomas.monjalon@6wind.com>2017-03-15 18:49:41 +0100
commitd89a5bce1d20068035da613c455d1612c20eec5e (patch)
tree828f96f3376ef7ba320e2397efa55a6ceab20bf8
parent5852bf6ae1fae11d01712a6a0d3138a7a1370e2c (diff)
downloaddpdk-d89a5bce1d20068035da613c455d1612c20eec5e.zip
dpdk-d89a5bce1d20068035da613c455d1612c20eec5e.tar.gz
dpdk-d89a5bce1d20068035da613c455d1612c20eec5e.tar.xz
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 <vladyslav.buslov@harmonicinc.com> Acked-by: Bruce Richardson <bruce.richardson@intel.com>
-rw-r--r--doc/guides/prog_guide/lpm6_lib.rst2
-rw-r--r--doc/guides/rel_notes/release_17_05.rst5
-rw-r--r--examples/ip_fragmentation/main.c17
-rw-r--r--examples/ip_reassembly/main.c17
-rw-r--r--examples/ipsec-secgw/ipsec-secgw.c2
-rw-r--r--examples/l3fwd/l3fwd_lpm.h2
-rw-r--r--examples/l3fwd/l3fwd_lpm_sse.h24
-rw-r--r--examples/performance-thread/l3fwd-thread/main.c11
-rw-r--r--lib/librte_lpm/rte_lpm6.c134
-rw-r--r--lib/librte_lpm/rte_lpm6.h32
-rw-r--r--lib/librte_lpm/rte_lpm_version.map10
-rw-r--r--lib/librte_table/rte_table_lpm_ipv6.c9
-rw-r--r--test/test/test_lpm6.c115
-rw-r--r--test/test/test_lpm6_perf.c4
14 files changed, 293 insertions, 91 deletions
diff --git a/doc/guides/prog_guide/lpm6_lib.rst b/doc/guides/prog_guide/lpm6_lib.rst
index 0aea5c5..f791507 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 4b90036..918f483 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 9e9ecae..1b005b5 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 e62674c..b641576 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 685feec..d3c229a 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 a43c507..258a82f 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 538fe3d..aa06b6d 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 6845e28..bf92582 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 32fdba0..9cc7be7 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,9 +507,17 @@ 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;
int32_t rule_index;
@@ -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 13d027f..3a3342d 100644
--- a/lib/librte_lpm/rte_lpm6.h
+++ b/lib/librte_lpm/rte_lpm6.h
@@ -39,6 +39,7 @@
*/
#include <stdint.h>
+#include <rte_compat.h>
#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 239b371..90beac8 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 836f4cf..1e1a173 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 61134f7..e0e7bf0 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;
@@ -1746,6 +1765,42 @@ test27(void)
}
/*
+ * 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.
*/
static int
diff --git a/test/test/test_lpm6_perf.c b/test/test/test_lpm6_perf.c
index 0723081..30be430 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);