summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_mplsvpn.c2
-rw-r--r--bgpd/bgp_nexthop.c57
-rw-r--r--bgpd/bgp_route.c18
-rw-r--r--bgpd/bgpd.c44
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)