lpm6: extend next hop field
authorVladyslav Buslov <vladyslav.buslov@harmonicinc.com>
Tue, 14 Mar 2017 17:17:38 +0000 (19:17 +0200)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Wed, 15 Mar 2017 17:49:41 +0000 (18:49 +0100)
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>
14 files changed:
doc/guides/prog_guide/lpm6_lib.rst
doc/guides/rel_notes/release_17_05.rst
examples/ip_fragmentation/main.c
examples/ip_reassembly/main.c
examples/ipsec-secgw/ipsec-secgw.c
examples/l3fwd/l3fwd_lpm.h
examples/l3fwd/l3fwd_lpm_sse.h
examples/performance-thread/l3fwd-thread/main.c
lib/librte_lpm/rte_lpm6.c
lib/librte_lpm/rte_lpm6.h
lib/librte_lpm/rte_lpm_version.map
lib/librte_table/rte_table_lpm_ipv6.c
test/test/test_lpm6.c
test/test/test_lpm6_perf.c

index 0aea5c5..f791507 100644 (file)
@@ -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:
index 4b90036..918f483 100644 (file)
@@ -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
 -----------
index 9e9ecae..1b005b5 100644 (file)
@@ -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;
index e62674c..b641576 100644 (file)
@@ -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);
index 685feec..d3c229a 100644 (file)
@@ -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;
index a43c507..258a82f 100644 (file)
@@ -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;
 
index 538fe3d..aa06b6d 100644 (file)
@@ -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);
 
        }
 
index 6845e28..bf92582 100644 (file)
@@ -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);
 
        }
 
index 32fdba0..9cc7be7 100644 (file)
@@ -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.
index 13d027f..3a3342d 100644 (file)
@@ -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
 }
index 239b371..90beac8 100644 (file)
@@ -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;
index 836f4cf..1e1a173 100644 (file)
@@ -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) {
index 61134f7..e0e7bf0 100644 (file)
@@ -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.
  */
index 0723081..30be430 100644 (file)
@@ -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);