diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-05-14 14:41:56 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-05-14 14:41:56 -0700 |
commit | 4ba1c78bc8f45e6179dd612fcbdd7a1bba18b819 (patch) | |
tree | 196bb982fdb9028de821a745679fa40af9875428 | |
parent | 9fb3006d10c38f7337a705e82dd36bd3a963fa39 (diff) | |
download | quagga-4ba1c78bc8f45e6179dd612fcbdd7a1bba18b819.tar.bz2 quagga-4ba1c78bc8f45e6179dd612fcbdd7a1bba18b819.tar.xz |
Reference count BGP instance
Bug 3436
Add reference counting on BGP structure. Don't free BGP instance until
all peer's are deleted.
Fix memory leak where self reference created but never freed
-rw-r--r-- | bgpd/bgp_route.c | 2 | ||||
-rw-r--r-- | bgpd/bgpd.c | 30 | ||||
-rw-r--r-- | bgpd/bgpd.h | 16 |
3 files changed, 42 insertions, 6 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 6da17d9b..80ae0793 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1529,6 +1529,7 @@ bgp_processq_del (struct work_queue *wq, void *data) { struct bgp_process_queue *pq = data; + bgp_unlock(pq->bgp); bgp_unlock_node (pq->rn); XFREE (MTYPE_BGP_PROCESS_QUEUE, pq); } @@ -1578,6 +1579,7 @@ bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) pqnode->rn = bgp_lock_node (rn); /* unlocked by bgp_processq_del */ pqnode->bgp = bgp; + bgp_lock(bgp); pqnode->afi = afi; pqnode->safi = safi; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index f1d78389..6f44f1fd 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -648,7 +648,9 @@ void peer_free (struct peer *peer) { assert (peer->status == Deleted); - + + bgp_unlock(peer->bgp); + /* this /ought/ to have been done already through bgp_stop earlier, * but just to be sure.. */ @@ -708,6 +710,7 @@ peer_new (struct bgp *bgp) peer->password = NULL; peer->bgp = bgp; peer = peer_lock (peer); /* initial reference */ + bgp_lock (bgp); /* Set default flags. */ for (afi = AFI_IP; afi < AFI_MAX; afi++) @@ -1826,6 +1829,7 @@ bgp_create (as_t *as, const char *name) if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL) return NULL; + bgp_lock (bgp); bgp->peer_self = peer_new (bgp); bgp->peer_self->host = strdup ("Static announcement"); @@ -1962,7 +1966,6 @@ bgp_delete (struct bgp *bgp) struct listnode *node; struct listnode *next; afi_t afi; - safi_t safi; int i; /* Delete static route. */ @@ -1976,14 +1979,31 @@ bgp_delete (struct bgp *bgp) for (ALL_LIST_ELEMENTS (bgp->group, node, next, group)) peer_group_delete (group); - list_delete (bgp->group); for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) peer_delete (peer); - list_delete (bgp->peer); for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer)) peer_delete (peer); + + if (bgp->peer_self) { + peer_delete(bgp->peer_self); + bgp->peer_self = NULL; + } + + bgp_unlock(bgp); /* initial reference */ + + return 0; +} + +void +bgp_free(struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + + list_delete (bgp->group); + list_delete (bgp->peer); list_delete (bgp->rsclient); listnode_delete (bm->bgp, bgp); @@ -2002,8 +2022,6 @@ bgp_delete (struct bgp *bgp) XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]); } XFREE (MTYPE_BGP, bgp); - - return 0; } struct peer * diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 0cd88d81..84164593 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -70,6 +70,9 @@ struct bgp /* Name of this BGP instance. */ char *name; + /* Reference count to allow peer_delete to finish after bgp_delete */ + int lock; + /* Self peer. */ struct peer *peer_self; @@ -897,6 +900,19 @@ bgp_config_check (const struct bgp *bgp, int config) return CHECK_FLAG (bgp->config, config); } +static inline void +bgp_lock(struct bgp *bgp) +{ + ++bgp->lock; +} + +static inline void +bgp_unlock(struct bgp *bgp) +{ + if (--bgp->lock == 0) + bgp_free (bgp); +} + extern int bgp_router_id_set (struct bgp *, struct in_addr *); extern int bgp_cluster_id_set (struct bgp *, struct in_addr *); |