summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 03:03:54 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 03:03:54 +0200
commit9a233a02be66401489e12b99f1e28ece056594ea (patch)
tree77f6354a34329712a2ed19278b9a33991f153d89 /bgpd
parentEnsure that if 'update-source <interface>' is specified, that interface is (diff)
downloadfrr-9a233a02be66401489e12b99f1e28ece056594ea.tar.xz
frr-9a233a02be66401489e12b99f1e28ece056594ea.zip
Ensure connected nexthop entry for the peer is freed when the peer is freed.
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_nht.c62
-rw-r--r--bgpd/bgp_nht.h10
-rw-r--r--bgpd/bgpd.c5
3 files changed, 77 insertions, 0 deletions
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index c460f0ee6..ceb231a6d 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -128,6 +128,13 @@ bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
bgp_lock_node(rn);
if (connected)
SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
+ if (BGP_DEBUG(nht, NHT))
+ {
+ char buf[INET6_ADDRSTRLEN];
+
+ zlog_debug("Allocated bnc %s peer %p",
+ bnc_str(bnc, buf, INET6_ADDRSTRLEN), peer);
+ }
}
bnc = rn->info;
@@ -152,6 +159,61 @@ bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
}
void
+bgp_delete_connected_nexthop (afi_t afi, struct peer *peer)
+{
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+ struct prefix p;
+
+ if (afi == AFI_IP)
+ {
+ p.family = AF_INET;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ p.u.prefix4 = peer->su.sin.sin_addr;
+ }
+ else if (afi == AFI_IP6)
+ {
+ p.family = AF_INET6;
+ p.prefixlen = IPV6_MAX_BITLEN;
+ p.u.prefix6 = peer->su.sin6.sin6_addr;
+ }
+
+ rn = bgp_node_lookup(bgp_nexthop_cache_table[family2afi(p.family)], &p);
+ if (!rn || !rn->info)
+ {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("Cannot find connected NHT node for peer %s", peer->host);
+ if (rn)
+ bgp_unlock_node (rn);
+ return;
+ }
+
+ bnc = rn->info;
+ bgp_unlock_node(rn);
+
+ if (bnc->nht_info != peer)
+ {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("Connected NHT %p node for peer %s points to %p",
+ bnc, peer->host, bnc->nht_info);
+ return;
+ }
+
+ bnc->nht_info = NULL;
+
+ if (LIST_EMPTY(&(bnc->paths)))
+ {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("Freeing connected NHT node %p for peer %s",
+ bnc, peer->host);
+ unregister_nexthop(bnc);
+ bnc->node->info = NULL;
+ bgp_unlock_node(bnc->node);
+ bnc_free(bnc);
+ }
+}
+
+void
bgp_parse_nexthop_update (void)
{
struct stream *s;
diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h
index 2c779802b..963dd00f2 100644
--- a/bgpd/bgp_nht.h
+++ b/bgpd/bgp_nht.h
@@ -56,4 +56,14 @@ extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a,
*/
extern void bgp_unlink_nexthop(struct bgp_info *p);
+/**
+ * bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected
+ * nexthop entry. If no paths reference the nexthop, it will be unregistered
+ * and freed.
+ * ARGUMENTS:
+ * afi - afi: AFI_IP or AF_IP6
+ * peer - Ptr to peer
+ */
+extern void bgp_delete_connected_nexthop (afi_t afi, struct peer *peer);
+
#endif /* _BGP_NHT_H */
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index a204e972a..aed6debfc 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -882,6 +882,11 @@ peer_free (struct peer *peer)
BGP_WRITE_OFF (peer->t_write);
BGP_EVENT_FLUSH (peer);
+ /* Free connected nexthop, if present */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) &&
+ !peer_dynamic_neighbor (peer))
+ bgp_delete_connected_nexthop (family2afi(peer->su.sa.sa_family), peer);
+
if (peer->desc)
XFREE (MTYPE_PEER_DESC, peer->desc);