]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: convert NHT code to use rb-trees instead of routing tables
authorRenato Westphal <renato@opensourcerouting.org>
Thu, 9 Apr 2020 18:56:11 +0000 (15:56 -0300)
committerGalaxyGorilla <sascha@netdef.org>
Mon, 31 Aug 2020 09:09:05 +0000 (09:09 +0000)
Fist, routing tables aren't the most appropriate data structure
to store nexthops and imported routes since we don't need to do
longest prefix matches with that information.

Second, by converting the NHT code to use rb-trees, we can index
the nexthops using additional information, not only the destination
address.  This will be useful later to index bgpd's nexthops by
both destination and SR-TE color.

Co-authored-by: Sebastien Merle <sebastien@netdef.org>
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
bgpd/bgp_nexthop.c
bgpd/bgp_nexthop.h
bgpd/bgp_nht.c
bgpd/bgpd.h

index 5cc0d605299a1ea79b3981d242677e24da836cde..9fbd5063e57dd56df81a77e10af9e7f5bb8f5764 100644 (file)
@@ -35,7 +35,6 @@
 #include "filter.h"
 
 #include "bgpd/bgpd.h"
-#include "bgpd/bgp_table.h"
 #include "bgpd/bgp_route.h"
 #include "bgpd/bgp_attr.h"
 #include "bgpd/bgp_nexthop.h"
 
 DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String");
 
-char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
+int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a,
+                             const struct bgp_nexthop_cache *b)
 {
-       prefix2str(bgp_dest_get_prefix(bnc->dest), buf, size);
-       return buf;
+       return prefix_cmp(&a->prefix, &b->prefix);
+}
+
+const char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
+{
+       return prefix2str(&bnc->prefix, buf, size);
 }
 
 void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
@@ -59,32 +63,47 @@ void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
        nexthops_free(bnc->nexthop);
 }
 
-struct bgp_nexthop_cache *bnc_new(void)
+struct bgp_nexthop_cache *bnc_new(struct bgp_nexthop_cache_head *tree,
+                                 struct prefix *prefix)
 {
        struct bgp_nexthop_cache *bnc;
 
        bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
                      sizeof(struct bgp_nexthop_cache));
+       bnc->prefix = *prefix;
+       bnc->tree = tree;
        LIST_INIT(&(bnc->paths));
+       bgp_nexthop_cache_add(tree, bnc);
+
        return bnc;
 }
 
 void bnc_free(struct bgp_nexthop_cache *bnc)
 {
        bnc_nexthop_free(bnc);
+       bgp_nexthop_cache_del(bnc->tree, bnc);
        XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
 }
 
+struct bgp_nexthop_cache *bnc_find(struct bgp_nexthop_cache_head *tree,
+                                  struct prefix *prefix)
+{
+       struct bgp_nexthop_cache bnc = {};
+
+       if (!tree)
+               return NULL;
+
+       bnc.prefix = *prefix;
+       return bgp_nexthop_cache_find(tree, &bnc);
+}
+
 /* Reset and free all BGP nexthop cache. */
-static void bgp_nexthop_cache_reset(struct bgp_table *table)
+static void bgp_nexthop_cache_reset(struct bgp_nexthop_cache_head *tree)
 {
-       struct bgp_dest *dest;
        struct bgp_nexthop_cache *bnc;
 
-       for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
-               bnc = bgp_dest_get_bgp_nexthop_info(dest);
-               if (!bnc)
-                       continue;
+       while (bgp_nexthop_cache_count(tree) > 0) {
+               bnc = bgp_nexthop_cache_first(tree);
 
                while (!LIST_EMPTY(&(bnc->paths))) {
                        struct bgp_path_info *path = LIST_FIRST(&(bnc->paths));
@@ -93,8 +112,6 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table)
                }
 
                bnc_free(bnc);
-               bgp_dest_set_bgp_nexthop_info(dest, NULL);
-               bgp_dest_unlock_node(dest);
        }
 }
 
@@ -773,20 +790,19 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
 }
 
 static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
-                            struct bgp_dest *dest,
                             struct bgp_nexthop_cache *bnc,
                             bool specific)
 {
        char buf[PREFIX2STR_BUFFER];
        time_t tbuf;
        struct peer *peer;
-       const struct prefix *p = bgp_dest_get_prefix(dest);
 
        peer = (struct peer *)bnc->nht_info;
 
        if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
                vty_out(vty, " %s valid [IGP metric %d], #paths %d",
-                       inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf)),
+                       inet_ntop(bnc->prefix.family, &bnc->prefix.u.prefix,
+                                 buf, sizeof(buf)),
                        bnc->metric, bnc->path_count);
                if (peer)
                        vty_out(vty, ", peer %s", peer->host);
@@ -794,7 +810,8 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
                bgp_show_nexthops_detail(vty, bgp, bnc);
        } else {
                vty_out(vty, " %s invalid, #paths %d",
-                       inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf)),
+                       inet_ntop(bnc->prefix.family, &bnc->prefix.u.prefix,
+                                 buf, sizeof(buf)),
                        bnc->path_count);
                if (peer)
                        vty_out(vty, ", peer %s", peer->host);
@@ -816,29 +833,21 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
 static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp,
                              bool import_table)
 {
-       struct bgp_dest *dest;
        struct bgp_nexthop_cache *bnc;
        afi_t afi;
-       struct bgp_table **table;
+       struct bgp_nexthop_cache_head(*tree)[AFI_MAX];
 
        if (import_table)
                vty_out(vty, "Current BGP import check cache:\n");
        else
                vty_out(vty, "Current BGP nexthop cache:\n");
        if (import_table)
-               table = bgp->import_check_table;
+               tree = &bgp->import_check_table;
        else
-               table = bgp->nexthop_cache_table;
+               tree = &bgp->nexthop_cache_table;
        for (afi = AFI_IP; afi < AFI_MAX; afi++) {
-               if (!table || !table[afi])
-                       continue;
-               for (dest = bgp_table_top(table[afi]); dest;
-                    dest = bgp_route_next(dest)) {
-                       bnc = bgp_dest_get_bgp_nexthop_info(dest);
-                       if (!bnc)
-                               continue;
-                       bgp_show_nexthop(vty, bgp, dest, bnc, false);
-               }
+               frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc)
+                       bgp_show_nexthop(vty, bgp, bnc, false);
        }
 }
 
@@ -859,27 +868,21 @@ static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
 
        if (nhopip_str) {
                struct prefix nhop;
-               struct bgp_table **table;
-               struct bgp_dest *dest;
+               struct bgp_nexthop_cache_head (*tree)[AFI_MAX];
                struct bgp_nexthop_cache *bnc;
 
                if (!str2prefix(nhopip_str, &nhop)) {
                        vty_out(vty, "nexthop address is malformed\n");
                        return CMD_WARNING;
                }
-               table = import_table ? \
-                       bgp->import_check_table : bgp->nexthop_cache_table;
-               dest = bgp_node_lookup(table[family2afi(nhop.family)], &nhop);
-               if (!dest) {
-                       vty_out(vty, "specified nexthop is not found\n");
-                       return CMD_SUCCESS;
-               }
-               bnc = bgp_dest_get_bgp_nexthop_info(dest);
+               tree = import_table ? &bgp->import_check_table
+                                   : &bgp->nexthop_cache_table;
+               bnc = bnc_find(tree[family2afi(nhop.family)], &nhop, 0);
                if (!bnc) {
                        vty_out(vty, "specified nexthop does not have entry\n");
                        return CMD_SUCCESS;
                }
-               bgp_show_nexthop(vty, bgp, dest, bnc, true);
+               bgp_show_nexthop(vty, bgp, bnc, true);
        } else
                bgp_show_nexthops(vty, bgp, import_table);
 
@@ -966,12 +969,10 @@ void bgp_scan_init(struct bgp *bgp)
        afi_t afi;
 
        for (afi = AFI_IP; afi < AFI_MAX; afi++) {
-               bgp->nexthop_cache_table[afi] =
-                       bgp_table_init(bgp, afi, SAFI_UNICAST);
+               bgp_nexthop_cache_init(&bgp->nexthop_cache_table[afi]);
+               bgp_nexthop_cache_init(&bgp->import_check_table[afi]);
                bgp->connected_table[afi] = bgp_table_init(bgp, afi,
                        SAFI_UNICAST);
-               bgp->import_check_table[afi] =
-                       bgp_table_init(bgp, afi, SAFI_UNICAST);
        }
 }
 
@@ -988,16 +989,12 @@ void bgp_scan_finish(struct bgp *bgp)
 
        for (afi = AFI_IP; afi < AFI_MAX; afi++) {
                /* Only the current one needs to be reset. */
-               bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
-               bgp_table_unlock(bgp->nexthop_cache_table[afi]);
-               bgp->nexthop_cache_table[afi] = NULL;
+               bgp_nexthop_cache_reset(&bgp->nexthop_cache_table[afi]);
+               bgp_nexthop_cache_reset(&bgp->import_check_table[afi]);
 
                bgp->connected_table[afi]->route_table->cleanup =
                        bgp_connected_cleanup;
                bgp_table_unlock(bgp->connected_table[afi]);
                bgp->connected_table[afi] = NULL;
-
-               bgp_table_unlock(bgp->import_check_table[afi]);
-               bgp->import_check_table[afi] = NULL;
        }
 }
index 416ab2a739ba4ae15412a0296383e2dbcce0fed9..e235fe472710e708bdfd8894eeab6c64c57f36f7 100644 (file)
@@ -24,6 +24,7 @@
 #include "if.h"
 #include "queue.h"
 #include "prefix.h"
+#include "bgp_table.h"
 
 #define NEXTHOP_FAMILY(nexthop_len)                                            \
        (((nexthop_len) == 4 || (nexthop_len) == 12                            \
 
 #define BGP_MP_NEXTHOP_FAMILY NEXTHOP_FAMILY
 
+PREDECL_RBTREE_UNIQ(bgp_nexthop_cache);
+
 /* BGP nexthop cache value structure. */
 struct bgp_nexthop_cache {
+       /* RB-tree entry. */
+       struct bgp_nexthop_cache_item entry;
+
        /* IGP route's metric. */
        uint32_t metric;
 
@@ -61,13 +67,21 @@ struct bgp_nexthop_cache {
 #define BGP_NEXTHOP_METRIC_CHANGED    (1 << 1)
 #define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
 
-       struct bgp_dest *dest;
+       /* Back pointer to the cache tree this entry belongs to. */
+       struct bgp_nexthop_cache_head *tree;
+
+       struct prefix prefix;
        void *nht_info; /* In BGP, peer session */
        LIST_HEAD(path_list, bgp_path_info) paths;
        unsigned int path_count;
        struct bgp *bgp;
 };
 
+extern int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a,
+                                    const struct bgp_nexthop_cache *b);
+DECLARE_RBTREE_UNIQ(bgp_nexthop_cache, struct bgp_nexthop_cache, entry,
+                   bgp_nexthop_cache_compare);
+
 /* Own tunnel-ip address structure */
 struct tip_addr {
        struct in_addr addr;
@@ -79,6 +93,12 @@ struct bgp_addrv6 {
        struct list *ifp_name_list;
 };
 
+/* Forward declaration(s). */
+struct peer;
+struct update_subgroup;
+struct bgp_dest;
+struct attr;
+
 extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
 extern void bgp_connected_delete(struct bgp *bgp, struct connected *c);
 extern bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
@@ -94,10 +114,13 @@ extern int bgp_config_write_scan_time(struct vty *);
 extern bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type,
                             uint8_t sub_type, struct attr *attr,
                             struct bgp_dest *dest);
-extern struct bgp_nexthop_cache *bnc_new(void);
+extern struct bgp_nexthop_cache *bnc_new(struct bgp_nexthop_cache_head *tree,
+                                        struct prefix *prefix);
 extern void bnc_free(struct bgp_nexthop_cache *bnc);
+extern struct bgp_nexthop_cache *bnc_find(struct bgp_nexthop_cache_head *tree,
+                                         struct prefix *prefix);
 extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc);
-extern char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size);
+extern const char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size);
 extern void bgp_scan_init(struct bgp *bgp);
 extern void bgp_scan_finish(struct bgp *bgp);
 extern void bgp_scan_vty_init(void);
index a780fb73472b5fffbda465ae24148583d39f0038..2365522bec6a3e5a137e7970af37009566e556ff 100644 (file)
@@ -78,9 +78,6 @@ static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
                }
                unregister_zebra_rnh(bnc,
                                     CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
-               bgp_dest_set_bgp_nexthop_info(bnc->dest, NULL);
-               bgp_dest_unlock_node(bnc->dest);
-               bnc->dest = NULL;
                bnc_free(bnc);
        }
 }
@@ -100,16 +97,13 @@ void bgp_unlink_nexthop(struct bgp_path_info *path)
 void bgp_unlink_nexthop_by_peer(struct peer *peer)
 {
        struct prefix p;
-       struct bgp_dest *dest;
        struct bgp_nexthop_cache *bnc;
        afi_t afi = family2afi(peer->su.sa.sa_family);
 
        if (!sockunion2hostprefix(&peer->su, &p))
                return;
 
-       dest = bgp_node_get(peer->bgp->nexthop_cache_table[afi], &p);
-
-       bnc = bgp_dest_get_bgp_nexthop_info(dest);
+       bnc = bnc_find(&peer->bgp->nexthop_cache_table[afi], &p);
        if (!bnc)
                return;
 
@@ -127,11 +121,10 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                            afi_t afi, struct bgp_path_info *pi,
                            struct peer *peer, int connected)
 {
-       struct bgp_dest *dest;
+       struct bgp_nexthop_cache_head *tree = NULL;
        struct bgp_nexthop_cache *bnc;
        struct prefix p;
        int is_bgp_static_route = 0;
-       const struct prefix *bnc_p;
 
        if (pi) {
                is_bgp_static_route = ((pi->type == ZEBRA_ROUTE_BGP)
@@ -168,17 +161,14 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                return 0;
 
        if (is_bgp_static_route)
-               dest = bgp_node_get(bgp_nexthop->import_check_table[afi], &p);
+               tree = &bgp_nexthop->import_check_table[afi];
        else
-               dest = bgp_node_get(bgp_nexthop->nexthop_cache_table[afi], &p);
+               tree = &bgp_nexthop->nexthop_cache_table[afi];
 
-       bnc = bgp_dest_get_bgp_nexthop_info(dest);
+       bnc = bnc_find(tree, &p);
        if (!bnc) {
-               bnc = bnc_new();
-               bgp_dest_set_bgp_nexthop_info(dest, bnc);
-               bnc->dest = dest;
+               bnc = bnc_new(tree, &p);
                bnc->bgp = bgp_nexthop;
-               bgp_dest_lock_node(dest);
                if (BGP_DEBUG(nht, NHT)) {
                        char buf[PREFIX2STR_BUFFER];
 
@@ -188,9 +178,6 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                }
        }
 
-       bnc_p = bgp_dest_get_prefix(bnc->dest);
-
-       bgp_dest_unlock_node(dest);
        if (is_bgp_static_route) {
                SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
 
@@ -236,7 +223,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
                SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
        } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)
-                  && !is_default_host_route(bnc_p))
+                  && !is_default_host_route(&bnc->prefix))
                register_zebra_rnh(bnc, is_bgp_static_route);
 
        if (pi && pi->nexthop != bnc) {
@@ -269,7 +256,6 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
 
 void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
 {
-       struct bgp_dest *dest;
        struct bgp_nexthop_cache *bnc;
        struct prefix p;
 
@@ -279,26 +265,15 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
        if (!sockunion2hostprefix(&peer->su, &p))
                return;
 
-       dest = bgp_node_lookup(
-               peer->bgp->nexthop_cache_table[family2afi(p.family)], &p);
-       if (!dest) {
-               if (BGP_DEBUG(nht, NHT))
-                       zlog_debug(
-                               "Cannot find connected NHT node for peer %s(%s)",
-                               peer->host, peer->bgp->name_pretty);
-               return;
-       }
-
-       bnc = bgp_dest_get_bgp_nexthop_info(dest);
+       bnc = bnc_find(&peer->bgp->nexthop_cache_table[family2afi(p.family)],
+                      &p);
        if (!bnc) {
                if (BGP_DEBUG(nht, NHT))
                        zlog_debug(
-                               "Cannot find connected NHT node for peer %s(%s) on route_node as expected",
+                               "Cannot find connected NHT node for peer %s(%s)",
                                peer->host, peer->bgp->name_pretty);
-               bgp_dest_unlock_node(dest);
                return;
        }
-       bgp_dest_unlock_node(dest);
 
        if (bnc->nht_info != peer) {
                if (BGP_DEBUG(nht, NHT))
@@ -317,15 +292,13 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
                                "Freeing connected NHT node %p for peer %s(%s)",
                                bnc, peer->host, bnc->bgp->name_pretty);
                unregister_zebra_rnh(bnc, 0);
-               bgp_dest_set_bgp_nexthop_info(bnc->dest, NULL);
-               bgp_dest_unlock_node(bnc->dest);
                bnc_free(bnc);
        }
 }
 
 void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
 {
-       struct bgp_dest *dest = NULL;
+       struct bgp_nexthop_cache_head *tree = NULL;
        struct bgp_nexthop_cache *bnc;
        struct nexthop *nexthop;
        struct nexthop *oldnh;
@@ -352,39 +325,23 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
        }
 
        if (command == ZEBRA_NEXTHOP_UPDATE)
-               dest = bgp_node_lookup(
-                       bgp->nexthop_cache_table[family2afi(nhr.prefix.family)],
-                       &nhr.prefix);
+               tree = &bgp->nexthop_cache_table[family2afi(nhr.prefix.family)];
        else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
-               dest = bgp_node_lookup(
-                       bgp->import_check_table[family2afi(nhr.prefix.family)],
-                       &nhr.prefix);
-
-       if (!dest) {
-               if (BGP_DEBUG(nht, NHT)) {
-                       char buf[PREFIX2STR_BUFFER];
-                       prefix2str(&nhr.prefix, buf, sizeof(buf));
-                       zlog_debug("parse nexthop update(%s(%s)): rn not found",
-                                  buf, bgp->name_pretty);
-               }
-               return;
-       }
+               tree = &bgp->import_check_table[family2afi(nhr.prefix.family)];
 
-       bnc = bgp_dest_get_bgp_nexthop_info(dest);
+       bnc = bnc_find(tree, &nhr.prefix);
        if (!bnc) {
                if (BGP_DEBUG(nht, NHT)) {
                        char buf[PREFIX2STR_BUFFER];
 
                        prefix2str(&nhr.prefix, buf, sizeof(buf));
                        zlog_debug(
-                               "parse nexthop update(%s(%s)): bnc node info not found",
+                               "parse nexthop update(%s(%s)): bnc info not found",
                                buf, bgp->name_pretty);
                }
-               bgp_dest_unlock_node(dest);
                return;
        }
 
-       bgp_dest_unlock_node(dest);
        bnc->last_update = bgp_clock();
        bnc->change_flags = 0;
 
@@ -503,20 +460,11 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
  */
 void bgp_cleanup_nexthops(struct bgp *bgp)
 {
-       afi_t afi;
-       struct bgp_dest *dest;
-       struct bgp_nexthop_cache *bnc;
-
-       for (afi = AFI_IP; afi < AFI_MAX; afi++) {
-               if (!bgp->nexthop_cache_table[afi])
-                       continue;
-
-               for (dest = bgp_table_top(bgp->nexthop_cache_table[afi]); dest;
-                    dest = bgp_route_next(dest)) {
-                       bnc = bgp_dest_get_bgp_nexthop_info(dest);
-                       if (!bnc)
-                               continue;
+       for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) {
+               struct bgp_nexthop_cache *bnc;
 
+               frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi],
+                         bnc) {
                        /* Clear relevant flags. */
                        UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
                        UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
@@ -609,7 +557,6 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
  */
 static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
 {
-       const struct prefix *p;
        bool exact_match = false;
        int ret;
 
@@ -631,23 +578,18 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
                                "%s: We have not connected yet, cannot send nexthops",
                                __func__);
        }
-       p = bgp_dest_get_prefix(bnc->dest);
        if ((command == ZEBRA_NEXTHOP_REGISTER
             || command == ZEBRA_IMPORT_ROUTE_REGISTER)
            && (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
                || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)))
                exact_match = true;
 
-       if (BGP_DEBUG(zebra, ZEBRA)) {
-               char buf[PREFIX2STR_BUFFER];
-
-               prefix2str(p, buf, PREFIX2STR_BUFFER);
-               zlog_debug("%s: sending cmd %s for %s (vrf %s)",
-                       __func__, zserv_command_string(command), buf,
-                       bnc->bgp->name_pretty);
-       }
+       if (BGP_DEBUG(zebra, ZEBRA))
+               zlog_debug("%s: sending cmd %s for %pFX (vrf %s)", __func__,
+                          zserv_command_string(command), &bnc->prefix,
+                          bnc->bgp->name_pretty);
 
-       ret = zclient_send_rnh(zclient, command, p, exact_match,
+       ret = zclient_send_rnh(zclient, command, &bnc->prefix, exact_match,
                               bnc->bgp->vrf_id);
        /* TBD: handle the failure */
        if (ret < 0)
@@ -901,21 +843,11 @@ void path_nh_map(struct bgp_path_info *path, struct bgp_nexthop_cache *bnc,
  */
 void bgp_nht_register_nexthops(struct bgp *bgp)
 {
-       struct bgp_dest *dest;
-       struct bgp_nexthop_cache *bnc;
-       afi_t afi;
-
-       for (afi = AFI_IP; afi < AFI_MAX; afi++) {
-               if (!bgp->nexthop_cache_table[afi])
-                       continue;
-
-               for (dest = bgp_table_top(bgp->nexthop_cache_table[afi]); dest;
-                    dest = bgp_route_next(dest)) {
-                       bnc = bgp_dest_get_bgp_nexthop_info(dest);
-
-                       if (!bnc)
-                               continue;
+       for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) {
+               struct bgp_nexthop_cache *bnc;
 
+               frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi],
+                         bnc) {
                        register_zebra_rnh(bnc, 0);
                }
        }
@@ -924,7 +856,6 @@ void bgp_nht_register_nexthops(struct bgp *bgp)
 void bgp_nht_reg_enhe_cap_intfs(struct peer *peer)
 {
        struct bgp *bgp;
-       struct bgp_dest *dest;
        struct bgp_nexthop_cache *bnc;
        struct nexthop *nhop;
        struct interface *ifp;
@@ -934,10 +865,6 @@ void bgp_nht_reg_enhe_cap_intfs(struct peer *peer)
                return;
 
        bgp = peer->bgp;
-
-       if (!bgp->nexthop_cache_table[AFI_IP6])
-               return;
-
        if (!sockunion2hostprefix(&peer->su, &p)) {
                zlog_warn("%s: Unable to convert sockunion to prefix for %s",
                          __func__, peer->host);
@@ -946,11 +873,8 @@ void bgp_nht_reg_enhe_cap_intfs(struct peer *peer)
 
        if (p.family != AF_INET6)
                return;
-       dest = bgp_node_lookup(bgp->nexthop_cache_table[AFI_IP6], &p);
-       if (!dest)
-               return;
 
-       bnc = bgp_dest_get_bgp_nexthop_info(dest);
+       bnc = bnc_find(&bgp->nexthop_cache_table[AFI_IP6], &p);
        if (!bnc)
                return;
 
@@ -973,7 +897,6 @@ void bgp_nht_reg_enhe_cap_intfs(struct peer *peer)
 void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer)
 {
        struct bgp *bgp;
-       struct bgp_dest *dest;
        struct bgp_nexthop_cache *bnc;
        struct nexthop *nhop;
        struct interface *ifp;
@@ -984,9 +907,6 @@ void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer)
 
        bgp = peer->bgp;
 
-       if (!bgp->nexthop_cache_table[AFI_IP6])
-               return;
-
        if (!sockunion2hostprefix(&peer->su, &p)) {
                zlog_warn("%s: Unable to convert sockunion to prefix for %s",
                          __func__, peer->host);
@@ -996,11 +916,7 @@ void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer)
        if (p.family != AF_INET6)
                return;
 
-       dest = bgp_node_lookup(bgp->nexthop_cache_table[AFI_IP6], &p);
-       if (!dest)
-               return;
-
-       bnc = bgp_dest_get_bgp_nexthop_info(dest);
+       bnc = bnc_find(&bgp->nexthop_cache_table[AFI_IP6], &p);
        if (!bnc)
                return;
 
index 6fc3f088365054df5c99d6f6f7f9b3befae3350c..20a41987cae56bf5cb911b5eb8ee135885e9322a 100644 (file)
@@ -42,6 +42,7 @@
 #include "vxlan.h"
 #include "bgp_labelpool.h"
 #include "bgp_addpath_types.h"
+#include "bgp_nexthop.h"
 
 #define BGP_MAX_HOSTNAME 64    /* Linux max, is larger than most other sys */
 #define BGP_PEER_MAX_HASH_SIZE 16384
@@ -482,11 +483,11 @@ struct bgp {
        /* BGP per AF peer count */
        uint32_t af_peer_count[AFI_MAX][SAFI_MAX];
 
-       /* Route table for next-hop lookup cache. */
-       struct bgp_table *nexthop_cache_table[AFI_MAX];
+       /* Tree for next-hop lookup cache. */
+       struct bgp_nexthop_cache_head nexthop_cache_table[AFI_MAX];
 
-       /* Route table for import-check */
-       struct bgp_table *import_check_table[AFI_MAX];
+       /* Tree for import-check */
+       struct bgp_nexthop_cache_head import_check_table[AFI_MAX];
 
        struct bgp_table *connected_table[AFI_MAX];