diff options
| -rw-r--r-- | bgpd/bgp_mplsvpn.c | 2 | ||||
| -rw-r--r-- | bgpd/bgp_nexthop.c | 57 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 18 | ||||
| -rw-r--r-- | bgpd/bgpd.c | 44 |
4 files changed, 78 insertions, 43 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index b58e9da6f4..eef711aa59 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -573,7 +573,7 @@ leak_update( new->extra->parent = bgp_info_lock(parent); bgp_lock_node((struct bgp_node *)((struct bgp_info *)parent)->net); if (bgp_orig) - new->extra->bgp_orig = bgp_orig; + new->extra->bgp_orig = bgp_lock(bgp_orig); if (nexthop_orig) new->extra->nexthop_orig = *nexthop_orig; diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 3700778c73..fd8d894878 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -326,35 +326,21 @@ void bgp_connected_delete(struct bgp *bgp, struct connected *ifc) { struct prefix p; struct prefix *addr; - struct bgp_node *rn; + struct bgp_node *rn = NULL; struct bgp_connected_ref *bc; addr = ifc->address; p = *(CONNECTED_PREFIX(ifc)); + apply_mask(&p); if (addr->family == AF_INET) { - apply_mask_ipv4((struct prefix_ipv4 *)&p); - if (prefix_ipv4_any((struct prefix_ipv4 *)&p)) return; bgp_address_del(bgp, addr); rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p); - if (!rn) - return; - - bc = rn->info; - bc->refcnt--; - if (bc->refcnt == 0) { - XFREE(MTYPE_BGP_CONN, bc); - rn->info = NULL; - } - bgp_unlock_node(rn); - bgp_unlock_node(rn); } else if (addr->family == AF_INET6) { - apply_mask_ipv6((struct prefix_ipv6 *)&p); - if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6)) return; @@ -363,17 +349,34 @@ void bgp_connected_delete(struct bgp *bgp, struct connected *ifc) rn = bgp_node_lookup(bgp->connected_table[AFI_IP6], (struct prefix *)&p); - if (!rn) - return; + } - bc = rn->info; - bc->refcnt--; - if (bc->refcnt == 0) { - XFREE(MTYPE_BGP_CONN, bc); - rn->info = NULL; - } - bgp_unlock_node(rn); - bgp_unlock_node(rn); + if (!rn) + return; + + bc = rn->info; + bc->refcnt--; + if (bc->refcnt == 0) { + XFREE(MTYPE_BGP_CONN, bc); + rn->info = NULL; + } + bgp_unlock_node(rn); + bgp_unlock_node(rn); +} + +static void bgp_connected_cleanup(struct route_table *table, + struct route_node *rn) +{ + struct bgp_connected_ref *bc; + + bc = rn->info; + if (!bc) + return; + + bc->refcnt--; + if (bc->refcnt == 0) { + XFREE(MTYPE_BGP_CONN, bc); + rn->info = NULL; } } @@ -656,6 +659,8 @@ void bgp_scan_finish(struct bgp *bgp) bgp_table_unlock(bgp->nexthop_cache_table[afi]); bgp->nexthop_cache_table[afi] = NULL; + bgp->connected_table[afi]->route_table->cleanup = + bgp_connected_cleanup; bgp_table_unlock(bgp->connected_table[afi]); bgp->connected_table[afi] = NULL; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 591af0f8cf..0e99bcbb14 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -206,11 +206,19 @@ struct bgp_info *bgp_info_new(void) static void bgp_info_free(struct bgp_info *binfo) { /* unlink reference to parent, if any. */ - if (binfo->extra && binfo->extra->parent) { - bgp_info_unlock((struct bgp_info *)binfo->extra->parent); - bgp_unlock_node((struct bgp_node *)((struct bgp_info *)binfo - ->extra->parent)->net); - binfo->extra->parent = NULL; + if (binfo->extra) { + if (binfo->extra->parent) { + bgp_unlock_node( + (struct bgp_node *)((struct bgp_info *)binfo + ->extra->parent) + ->net); + bgp_info_unlock( + (struct bgp_info *)binfo->extra->parent); + binfo->extra->parent = NULL; + } + + if (binfo->extra->bgp_orig) + bgp_unlock(binfo->extra->bgp_orig); } if (binfo->attr) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 0c7b642438..5d858ae14f 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2890,6 +2890,18 @@ static int bgp_startup_timer_expire(struct thread *thread) return 0; } +/* + * On shutdown we call the cleanup function which + * does a free of the link list nodes, free up + * the data we are pointing at too. + */ +static void bgp_vrf_string_name_delete(void *data) +{ + char *vname = data; + + XFREE(MTYPE_TMP, vname); +} + /* BGP instance creation by `router bgp' commands. */ static struct bgp *bgp_create(as_t *as, const char *name, enum bgp_instance_type inst_type) @@ -3000,7 +3012,11 @@ static struct bgp *bgp_create(as_t *as, const char *name, MPLS_LABEL_NONE; bgp->vpn_policy[afi].import_vrf = list_new(); + bgp->vpn_policy[afi].import_vrf->del = + bgp_vrf_string_name_delete; bgp->vpn_policy[afi].export_vrf = list_new(); + bgp->vpn_policy[afi].export_vrf->del = + bgp_vrf_string_name_delete; } if (name) { bgp->name = XSTRDUP(MTYPE_BGP, name); @@ -3412,17 +3428,6 @@ void bgp_free(struct bgp *bgp) rmap = &bgp->table_map[afi][safi]; if (rmap->name) XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); - - /* - * Yes this is per AFI, but - * the list_delete_and_null nulls the pointer - * and we'll not leak anything on going down - * and the if test will fail on the second safi. - */ - if (bgp->vpn_policy[afi].import_vrf) - list_delete_and_null(&bgp->vpn_policy[afi].import_vrf); - if (bgp->vpn_policy[afi].export_vrf) - list_delete_and_null(&bgp->vpn_policy[afi].export_vrf); } bgp_scan_finish(bgp); @@ -3434,6 +3439,23 @@ void bgp_free(struct bgp *bgp) bgp_evpn_cleanup(bgp); bgp_pbr_cleanup(bgp); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + vpn_policy_direction_t dir; + + if (bgp->vpn_policy[afi].import_vrf) + list_delete_and_null(&bgp->vpn_policy[afi].import_vrf); + if (bgp->vpn_policy[afi].export_vrf) + list_delete_and_null(&bgp->vpn_policy[afi].export_vrf); + + dir = BGP_VPN_POLICY_DIR_FROMVPN; + if (bgp->vpn_policy[afi].rtlist[dir]) + ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]); + dir = BGP_VPN_POLICY_DIR_TOVPN; + if (bgp->vpn_policy[afi].rtlist[dir]) + ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]); + } + if (bgp->name) XFREE(MTYPE_BGP, bgp->name); if (bgp->name_pretty) |
