summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2018-10-17 11:27:30 -0400
committerDonald Sharp <sharpd@cumulusnetworks.com>2018-10-17 11:27:30 -0400
commit7f040da1a18981277a1db29764a3dc6f0e7d2f10 (patch)
tree72244bcfefbcbab0c33ac650ff24ef807ac67a5f
parentd725199ad91716d54360d2e628383a2615cd5165 (diff)
bgpd: Fix crash when using v4 route w/ v6 nexthop
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>
-rw-r--r--bgpd/bgp_nexthop.c7
-rw-r--r--bgpd/bgp_nht.c11
-rw-r--r--bgpd/bgp_nht.h7
3 files changed, 19 insertions, 6 deletions
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 45c596254f..be219d2374 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -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);
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 5203e6eefd..e764860bcc 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -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);
diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h
index 7b29fa818f..0cc045a065 100644
--- a/bgpd/bgp_nht.h
+++ b/bgpd/bgp_nht.h
@@ -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 */