From d8612e6545f0b631dcb834d6031787469c139e88 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 6 May 2019 19:42:26 -0400 Subject: [PATCH] zebra: Track tables allocated by vrf and cleanup For each table created by a vrf, keep track of it and allow for proper cleanup on shutdown of that particular table. Cleanup client shutdown to only cleanup data that the particular vrf owns. Before we were cleaning the same table 2 times. Signed-off-by: Donald Sharp --- zebra/zebra_rib.c | 23 ++++++++++++++--------- zebra/zebra_vrf.c | 37 ++++++++++++++++++++++++++++++++++++- zebra/zebra_vrf.h | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 10 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 2945a5ef9d18..af29443aabe7 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3227,18 +3227,23 @@ unsigned long rib_score_proto(uint8_t proto, unsigned short instance) { struct vrf *vrf; struct zebra_vrf *zvrf; + struct other_route_table *ort; unsigned long cnt = 0; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) - cnt += rib_score_proto_table( - proto, instance, - zvrf->table[AFI_IP][SAFI_UNICAST]) - + rib_score_proto_table( - proto, instance, - zvrf->table[AFI_IP6][SAFI_UNICAST]); + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { + zvrf = vrf->info; + if (!zvrf) + continue; - cnt += zebra_router_score_proto(proto, instance); + cnt += rib_score_proto_table(proto, instance, + zvrf->table[AFI_IP][SAFI_UNICAST]) + + rib_score_proto_table( + proto, instance, + zvrf->table[AFI_IP6][SAFI_UNICAST]); + + for_each(otable, &zvrf->other_tables, ort) cnt += + rib_score_proto_table(proto, instance, ort->table); + } return cnt; } diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 38f8adeae7b3..4883729c96d1 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -47,6 +47,8 @@ static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, static void zebra_rnhtable_node_cleanup(struct route_table *table, struct route_node *node); +DEFINE_MTYPE_STATIC(ZEBRA, OTHER_TABLE, "Other Table"); + /* VRF information update. */ static void zebra_vrf_add_update(struct zebra_vrf *zvrf) { @@ -93,6 +95,9 @@ static int zebra_vrf_new(struct vrf *vrf) zvrf = zebra_vrf_alloc(); vrf->info = zvrf; zvrf->vrf = vrf; + + otable_init(&zvrf->other_tables); + router_id_init(zvrf); return 0; } @@ -226,6 +231,7 @@ static int zebra_vrf_disable(struct vrf *vrf) static int zebra_vrf_delete(struct vrf *vrf) { struct zebra_vrf *zvrf = vrf->info; + struct other_route_table *otable; struct route_table *table; afi_t afi; safi_t safi; @@ -274,11 +280,22 @@ static int zebra_vrf_delete(struct vrf *vrf) route_table_finish(zvrf->import_check_table[afi]); } + otable = otable_pop(&zvrf->other_tables); + while (otable) { + zebra_router_release_table(zvrf, otable->table_id, + otable->afi, otable->safi); + XFREE(MTYPE_OTHER_TABLE, otable); + + otable = otable_pop(&zvrf->other_tables); + } + /* Cleanup EVPN states for vrf */ zebra_vxlan_vrf_delete(zvrf); list_delete_all_node(zvrf->rid_all_sorted_list); list_delete_all_node(zvrf->rid_lo_sorted_list); + + otable_fini(&zvrf->other_tables); XFREE(MTYPE_ZEBRA_VRF, zvrf); vrf->info = NULL; @@ -321,6 +338,8 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, uint32_t table_id) { struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id); + struct other_route_table ort, *otable; + struct route_table *table; if (!zvrf) return NULL; @@ -331,7 +350,23 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, if (table_id == zvrf->table_id) return zebra_vrf_table(afi, safi, vrf_id); - return zebra_router_get_table(zvrf, table_id, afi, safi); + ort.afi = afi; + ort.safi = safi; + ort.table_id = table_id; + otable = otable_find(&zvrf->other_tables, &ort); + if (otable) + return otable->table; + + table = zebra_router_get_table(zvrf, table_id, afi, safi); + + otable = XCALLOC(MTYPE_OTHER_TABLE, sizeof(*otable)); + otable->afi = afi; + otable->safi = safi; + otable->table_id = table_id; + otable->table = table; + otable_add(&zvrf->other_tables, otable); + + return table; } void zebra_rtable_node_cleanup(struct route_table *table, diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 49887f1b6793..febaf3c844ef 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -43,6 +43,18 @@ struct zebra_rmap { struct route_map *map; }; +PREDECL_RBTREE_UNIQ(otable); + +struct other_route_table { + struct otable_item next; + + afi_t afi; + safi_t safi; + uint32_t table_id; + + struct route_table *table; +}; + /* Routing table instance. */ struct zebra_vrf { /* Back pointer */ @@ -69,6 +81,8 @@ struct zebra_vrf { /* Import check table (used mostly by BGP */ struct route_table *import_check_table[AFI_MAX]; + struct otable_head other_tables; + /* 2nd pointer type used primarily to quell a warning on * ALL_LIST_ELEMENTS_RO */ @@ -192,6 +206,25 @@ static inline bool zvrf_is_active(struct zebra_vrf *zvrf) return zvrf->vrf->status & VRF_ACTIVE; } +static inline int +zvrf_other_table_compare_func(const struct other_route_table *a, + const struct other_route_table *b) +{ + if (a->afi != b->afi) + return a->afi - b->afi; + + if (a->safi != b->safi) + return a->safi - b->safi; + + if (a->table_id != b->table_id) + return a->table_id - b->table_id; + + return 0; +} + +DECLARE_RBTREE_UNIQ(otable, struct other_route_table, next, + zvrf_other_table_compare_func) + struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, vrf_id_t vrf_id, uint32_t table_id);