]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Fix crash when using v4 route w/ v6 nexthop
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 17 Oct 2018 15:27:30 +0000 (11:27 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 17 Oct 2018 15:27:30 +0000 (11:27 -0400)
Recent changes to the nht code in bgp caused us to actually
keep a true count of v6 nexthop paths when using v4 over v6.
This change introduced a race condition on shutdown on who
got to the bnc cache first( the v4 table or not ).  Effectively
we were allowing the continued existence of the path->nexthop
pointing to the freed bnc.  This was especially true when
we had route leaking.   So when we free the bnc make sure
we clean up the path->nexthop variables pointing at it too.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_nht.h

index 45c596254f61982d4a065a36034f46df51ef1b88..be219d23740d565f083665c23be344d00f2217b4 100644 (file)
@@ -85,6 +85,13 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table)
        for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
                bnc = bgp_nexthop_get_node_info(rn);
                if (bnc != NULL) {
+                       while (!LIST_EMPTY(&(bnc->paths))) {
+                               struct bgp_path_info *path =
+                                       LIST_FIRST(&(bnc->paths));
+
+                               path_nh_map(path, bnc, false);
+                       }
+
                        bnc_free(bnc);
                        bgp_nexthop_set_node_info(rn, NULL);
                        bgp_unlock_node(rn);
index 5203e6eefd663fd64f039407cf566afd64accd13..e764860bccdfb5e387c944fa5129508a5f4e2c8b 100644 (file)
@@ -51,8 +51,6 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
                                 int is_bgp_static_route);
 static void evaluate_paths(struct bgp_nexthop_cache *bnc);
 static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p);
-static void path_nh_map(struct bgp_path_info *path,
-                       struct bgp_nexthop_cache *bnc, int keep);
 
 static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
 {
@@ -111,7 +109,7 @@ void bgp_unlink_nexthop(struct bgp_path_info *path)
        if (!bnc)
                return;
 
-       path_nh_map(path, NULL, 0);
+       path_nh_map(path, NULL, false);
 
        bgp_unlink_nexthop_check(bnc);
 }
@@ -253,7 +251,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                 */
                bgp_unlink_nexthop(pi);
 
-               path_nh_map(pi, bnc, 1); /* updates NHT pi list reference */
+               /* updates NHT pi list reference */
+               path_nh_map(pi, bnc, true);
 
                if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
                        (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric;
@@ -789,8 +788,8 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc)
  *   make - if set, make the association. if unset, just break the existing
  *          association.
  */
-static void path_nh_map(struct bgp_path_info *path,
-                       struct bgp_nexthop_cache *bnc, int make)
+void path_nh_map(struct bgp_path_info *path, struct bgp_nexthop_cache *bnc,
+                bool make)
 {
        if (path->nexthop) {
                LIST_REMOVE(path, nh_thread);
index 7b29fa818fb566c1c4eb5f7ae4ee9e01b2e2e0f5..0cc045a065e9a506a38bb06c25d35c7052536a35 100644 (file)
@@ -75,4 +75,11 @@ extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer);
  */
 extern void bgp_cleanup_nexthops(struct bgp *bgp);
 
+/*
+ * Add or remove the tracking of the bgp_path_info that
+ * uses this nexthop
+ */
+extern void path_nh_map(struct bgp_path_info *path,
+                       struct bgp_nexthop_cache *bnc, bool make);
+
 #endif /* _BGP_NHT_H */