diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 03:03:54 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 03:03:54 +0200 |
commit | 9a233a02be66401489e12b99f1e28ece056594ea (patch) | |
tree | 77f6354a34329712a2ed19278b9a33991f153d89 /bgpd | |
parent | Ensure that if 'update-source <interface>' is specified, that interface is (diff) | |
download | frr-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.c | 62 | ||||
-rw-r--r-- | bgpd/bgp_nht.h | 10 | ||||
-rw-r--r-- | bgpd/bgpd.c | 5 |
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); |