diff options
-rw-r--r-- | lib/table.c | 35 | ||||
-rw-r--r-- | lib/table.h | 8 |
2 files changed, 31 insertions, 12 deletions
diff --git a/lib/table.c b/lib/table.c index fcb7ecc0..7efb8c4f 100644 --- a/lib/table.c +++ b/lib/table.c @@ -27,8 +27,8 @@ #include "memory.h" #include "sockunion.h" -void route_node_delete (struct route_node *); -void route_table_free (struct route_table *); +static void route_node_delete (struct route_node *); +static void route_table_free (struct route_table *); struct route_table * route_table_init (void) @@ -76,7 +76,7 @@ route_node_free (struct route_node *node) } /* Free route table. */ -void +static void route_table_free (struct route_table *rt) { struct route_node *tmp_node; @@ -87,6 +87,9 @@ route_table_free (struct route_table *rt) node = rt->top; + /* Bulk deletion of nodes remaining in this table. This function is not + called until workers have completed their dependency on this table. + A final route_unlock_node() will not be called for these nodes. */ while (node) { if (node->l_left) @@ -104,22 +107,25 @@ route_table_free (struct route_table *rt) tmp_node = node; node = node->parent; + tmp_node->table->count--; + tmp_node->lock = 0; /* to cause assert if unlocked after this */ + route_node_free (tmp_node); + if (node != NULL) { if (node->l_left == tmp_node) node->l_left = NULL; else node->l_right = NULL; - - route_node_free (tmp_node); } else { - route_node_free (tmp_node); break; } } + assert (rt->count == 0); + XFREE (MTYPE_ROUTE_TABLE, rt); return; } @@ -186,6 +192,7 @@ route_lock_node (struct route_node *node) void route_unlock_node (struct route_node *node) { + assert (node->lock > 0); node->lock--; if (node->lock == 0) @@ -255,7 +262,7 @@ route_node_match_ipv6 (const struct route_table *table, /* Lookup same prefix node. Return NULL when we can't find route. */ struct route_node * -route_node_lookup (struct route_table *table, struct prefix *p) +route_node_lookup (const struct route_table *table, struct prefix *p) { struct route_node *node; u_char prefixlen = p->prefixlen; @@ -277,7 +284,7 @@ route_node_lookup (struct route_table *table, struct prefix *p) /* Add node to routing table. */ struct route_node * -route_node_get (struct route_table *table, struct prefix *p) +route_node_get (struct route_table *const table, struct prefix *p) { struct route_node *new; struct route_node *node; @@ -323,15 +330,17 @@ route_node_get (struct route_table *table, struct prefix *p) match = new; new = route_node_set (table, p); set_link (match, new); + table->count++; } } + table->count++; route_lock_node (new); return new; } /* Delete node from the routing table. */ -void +static void route_node_delete (struct route_node *node) { struct route_node *child; @@ -363,6 +372,8 @@ route_node_delete (struct route_node *node) else node->table->top = child; + node->table->count--; + route_node_free (node); /* If parent node is stub then delete it also. */ @@ -465,3 +476,9 @@ route_next_until (struct route_node *node, struct route_node *limit) route_unlock_node (start); return NULL; } + +unsigned long +route_table_count (const struct route_table *table) +{ + return table->count; +} diff --git a/lib/table.h b/lib/table.h index 41d1fa70..1e8df46d 100644 --- a/lib/table.h +++ b/lib/table.h @@ -27,6 +27,8 @@ struct route_table { struct route_node *top; + + unsigned long count; }; /* Each routing entry. */ @@ -56,14 +58,13 @@ struct route_node extern struct route_table *route_table_init (void); extern void route_table_finish (struct route_table *); extern void route_unlock_node (struct route_node *node); -extern void route_node_delete (struct route_node *node); extern struct route_node *route_top (struct route_table *); extern struct route_node *route_next (struct route_node *); extern struct route_node *route_next_until (struct route_node *, struct route_node *); -extern struct route_node *route_node_get (struct route_table *, +extern struct route_node *route_node_get (struct route_table *const, struct prefix *); -extern struct route_node *route_node_lookup (struct route_table *, +extern struct route_node *route_node_lookup (const struct route_table *, struct prefix *); extern struct route_node *route_lock_node (struct route_node *node); extern struct route_node *route_node_match (const struct route_table *, @@ -75,4 +76,5 @@ extern struct route_node *route_node_match_ipv6 (const struct route_table *, const struct in6_addr *); #endif /* HAVE_IPV6 */ +extern unsigned long route_table_count (const struct route_table *); #endif /* _ZEBRA_TABLE_H */ |