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.
 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:
 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.
      =========================================================
 
      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.**
 
 
 * **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.
    =========================================================
 
    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
 -----------
 
 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;
                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;
        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 */
                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;
 
                        /* 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 */
                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;
 
                        /* 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;
        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];
 
 
        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 */
                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);
                }
 
                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 */
                }
 
                /* 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);
                }
 
                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)
 {
 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;
        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)
 {
 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;
 
        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)
 {
 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;
        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);
 
                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)) {
 
 
        } 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 = (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)
 {
 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,
        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)) {
 
 
        } 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 = (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)
 {
 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) ?
 
        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)
 {
 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,
        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)) {
 
 
        } 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,
 
                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. */
 /** 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. */
 };
 
        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
  * 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;
 
 {
        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,
  */
 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;
 
 {
        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,
 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;
 {
        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
  * 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)
                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;
 {
        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;
 }
 
        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.
 
 /*
  * 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,
 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;
 
 {
        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. */
                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;
        }
 }
                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
  * 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;
 {
        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;
 }
 
        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
 
 /*
  * 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;
                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. */
        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
                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;
 }
        }
 
        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.
 
 /*
  * 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
  * 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;
 {
        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;
 }
        /* 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.
 
 /*
  * Delete a rule from the rule table.
index 13d027f..3a3342d 100644 (file)
@@ -39,6 +39,7 @@
  */
 
 #include <stdint.h>
  */
 
 #include <stdint.h>
+#include <rte_compat.h>
 
 #ifdef __cplusplus
 extern "C" {
 
 #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,
  */
 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);
                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,
 
 /**
  * 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,
  */
 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.
 
 /**
  * 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
  *   -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.
 
 /**
  * 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],
 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
 }
 
 #ifdef __cplusplus
 }
index 239b371..90beac8 100644 (file)
@@ -34,3 +34,13 @@ DPDK_16.04 {
        rte_lpm_delete_all;
 
 } DPDK_2.0;
        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;
        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;
        int status;
-       uint8_t nht_pos0;
 
        /* Check input parameters */
        if (lpm == NULL) {
 
        /* 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,
 
        /* 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;
        }
                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;
        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 */
        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 *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) {
 
                        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 test25(void);
 static int32_t test26(void);
 static int32_t test27(void);
+static int32_t test28(void);
 
 rte_lpm6_test tests6[] = {
 /* Test Cases */
 
 rte_lpm6_test tests6[] = {
 /* Test Cases */
@@ -110,6 +111,7 @@ rte_lpm6_test tests6[] = {
        test25,
        test26,
        test27,
        test25,
        test26,
        test27,
+       test28,
 };
 
 #define NUM_LPM6_TESTS                (sizeof(tests6)/sizeof(tests6[0]))
 };
 
 #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};
        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;
        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];
        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;
        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};
        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;
 
        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};
        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;
 
        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};
        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;
        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};
        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;
        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};
        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;
        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};
        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;
 
        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};
        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;
        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};
        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;
        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 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;
        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--) {
 
        /* 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);
 
                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];
        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;
        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];
        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;
        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];
        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;
        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];
        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;
        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];
        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;
        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];
        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;
        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;
        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;
        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 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;
        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);
                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);
 
        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);
                        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);
 
        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);
                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);
 
        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};
                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;
 
                int32_t status = 0;
                int i, j;
 
@@ -1745,6 +1764,42 @@ test27(void)
                return PASS;
 }
 
                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.
  */
 /*
  * 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;
        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;
 
        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];
        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);
 
        for (i = 0; i < NUM_IPS_ENTRIES; i++)
                memcpy(ip_batch[i], large_ips_table[i].ip, 16);