]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Netindex is now net-type specific
authorMaria Matejka <mq@ucw.cz>
Wed, 5 Jun 2024 15:47:32 +0000 (17:47 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 5 Jun 2024 15:47:32 +0000 (17:47 +0200)
Combining all network types in one netindex was just a waste of memory
and too much complexity for no reason.

lib/netindex.c
lib/netindex.h
lib/netindex_private.h
nest/rt-export.c
nest/rt-table.c
proto/bgp/attrs.c

index 296319691ee8dc1bf2a3f490276dc4c397c5926a..2b87ed0817771470ff40ca0bd60c14cccdf122f0 100644 (file)
@@ -36,29 +36,23 @@ net_lock_revive_unlock(struct netindex_hash_private *hp, struct netindex *i)
 void
 netindex_hash_consistency_check(struct netindex_hash_private *nh)
 {
-  for (uint t = 0; t < NET_MAX; t++)
+  uint count = 0;
+  HASH_WALK(nh->hash, next, i)
   {
-    if (!nh->net[t].hash.data)
-      continue;
-
-    uint count = 0;
-    HASH_WALK(nh->net[t].hash, next, i)
-    {
-      ASSERT_DIE(count < nh->net[t].hash.count);
-      ASSERT_DIE(nh->net[t].block[i->index] == i);
-      count++;
-    }
-    HASH_WALK_END;
-
-    ASSERT_DIE(count == nh->net[t].hash.count);
+    ASSERT_DIE(count < nh->hash.count);
+    ASSERT_DIE(nh->block[i->index] == i);
+    count++;
   }
+  HASH_WALK_END;
+
+  ASSERT_DIE(count == nh->hash.count);
 }
 
 /*
  * Index initialization
  */
 netindex_hash *
-netindex_hash_new(pool *sp, event_list *cleanup_target)
+netindex_hash_new(pool *sp, event_list *cleanup_target, u8 type)
 {
   DOMAIN(attrs) dom = DOMAIN_NEW(attrs);
   LOCK_DOMAIN(attrs, dom);
@@ -68,6 +62,15 @@ netindex_hash_new(pool *sp, event_list *cleanup_target)
   struct netindex_hash_private *nh = mb_allocz(p, sizeof *nh);
   nh->lock = dom;
   nh->pool = p;
+  nh->net_type = type;
+
+  nh->slab = net_addr_length[type] ? sl_new(nh->pool, sizeof (struct netindex) + net_addr_length[type]) : NULL;
+
+  HASH_INIT(nh->hash, nh->pool, NETINDEX_ORDER);
+  nh->block_size = 128;
+  nh->block = mb_allocz(nh->pool, nh->block_size * sizeof (struct netindex *));
+
+  hmap_init(&nh->id_map, nh->pool, 128);
 
   nh->cleanup_list = cleanup_target;
   nh->cleanup_event = (event) { .hook = netindex_hash_cleanup, nh };
@@ -88,29 +91,28 @@ netindex_hash_cleanup(void *_nh)
 
   uint kept = 0;
 
-  for (uint t = 0; t < NET_MAX; t++)
-    for (uint i = 0; i < nh->net[t].block_size; i++)
+  for (uint i = 0; i < nh->block_size; i++)
+  {
+    struct netindex *ni = nh->block[i];
+    if (!ni)
+      continue;
+
+    ASSERT_DIE(i == ni->index);
+
+    if (lfuc_finished(&ni->uc))
     {
-      struct netindex *ni = nh->net[t].block[i];
-      if (!ni)
-       continue;
-
-      ASSERT_DIE(i == ni->index);
-
-      if (lfuc_finished(&ni->uc))
-      {
-       HASH_REMOVE2(nh->net[t].hash, NETINDEX, nh->pool, ni);
-       hmap_clear(&nh->net[t].id_map, ni->index);
-       nh->net[t].block[i] = NULL;
-
-       if (nh->net[t].slab)
-         sl_free(ni);
-       else
-         mb_free(ni);
-      }
+      HASH_REMOVE2(nh->hash, NETINDEX, nh->pool, ni);
+      hmap_clear(&nh->id_map, ni->index);
+      nh->block[i] = NULL;
+
+      if (nh->slab)
+       sl_free(ni);
       else
-       kept++;
+       mb_free(ni);
     }
+    else
+      kept++;
+  }
 
   EXPENSIVE_CHECK(netindex_hash_consistency_check(nh));
 
@@ -126,13 +128,9 @@ netindex_hash_cleanup(void *_nh)
   event_list *t = nh->deleted_target;
 
   /* Check cleanliness */
-  for (uint t = 0; t < NET_MAX; t++)
-    if (nh->net[t].hash.data)
-    {
-      HASH_WALK(nh->net[t].hash, next, i)
-       bug("Stray netindex in deleted hash");
-      HASH_WALK_END;
-    }
+  HASH_WALK(nh->hash, next, i)
+    bug("Stray netindex in deleted hash");
+  HASH_WALK_END;
 
   /* Pool free is enough to drop everything */
   rp_free(nh->pool);
@@ -145,18 +143,6 @@ netindex_hash_cleanup(void *_nh)
   ev_send(t, e);
 }
 
-static void
-netindex_hash_init(struct netindex_hash_private *hp, u8 type)
-{
-  ASSERT_DIE(hp->net[type].block == NULL);
-
-  hp->net[type].slab = net_addr_length[type] ? sl_new(hp->pool, sizeof (struct netindex) + net_addr_length[type]) : NULL;
-  HASH_INIT(hp->net[type].hash, hp->pool, NETINDEX_ORDER);
-  hp->net[type].block_size = 128;
-  hp->net[type].block = mb_allocz(hp->pool, hp->net[type].block_size * sizeof (struct netindex *));
-  hmap_init(&hp->net[type].id_map, hp->pool, 128);
-};
-
 void
 netindex_hash_delete(netindex_hash *h, event *e, event_list *t)
 {
@@ -176,25 +162,20 @@ netindex_hash_delete(netindex_hash *h, event *e, event_list *t)
 struct netindex *
 net_find_index_fragile_chain(struct netindex_hash_private *hp, const net_addr *n)
 {
-  ASSERT_DIE(n->type < NET_MAX);
-  if (!hp->net[n->type].block)
-    return NULL;
-
+  ASSERT_DIE(n->type == hp->net_type);
   u32 h = net_hash(n);
-  return HASH_FIND_CHAIN(hp->net[n->type].hash, NETINDEX, h, n);
+  return HASH_FIND_CHAIN(hp->hash, NETINDEX, h, n);
 }
 
 struct netindex *
 net_find_index_fragile(struct netindex_hash_private *hp, const net_addr *n)
 {
-  ASSERT_DIE(n->type < NET_MAX);
-  if (!hp->net[n->type].block)
-    return NULL;
+  ASSERT_DIE(n->type == hp->net_type);
 
-  EXPENSIVE_CHECK(netindex_hash_consistency_check(nh));
+  EXPENSIVE_CHECK(netindex_hash_consistency_check(hp));
 
   u32 h = net_hash(n);
-  return HASH_FIND(hp->net[n->type].hash, NETINDEX, h, n);
+  return HASH_FIND(hp->hash, NETINDEX, h, n);
 }
 
 static struct netindex *
@@ -208,14 +189,11 @@ net_new_index_locked(struct netindex_hash_private *hp, const net_addr *n)
 {
   ASSERT_DIE(!hp->deleted_event);
 
-  if (!hp->net[n->type].block)
-    netindex_hash_init(hp, n->type);
-
-  u32 i = hmap_first_zero(&hp->net[n->type].id_map);
-  hmap_set(&hp->net[n->type].id_map, i);
+  u32 i = hmap_first_zero(&hp->id_map);
+  hmap_set(&hp->id_map, i);
 
-  struct netindex *ni = hp->net[n->type].slab ?
-    sl_alloc(hp->net[n->type].slab) :
+  struct netindex *ni = hp->slab ?
+    sl_alloc(hp->slab) :
     mb_alloc(hp->pool, n->length + sizeof *ni);
 
   *ni = (struct netindex) {
@@ -224,21 +202,21 @@ net_new_index_locked(struct netindex_hash_private *hp, const net_addr *n)
   };
   net_copy(ni->addr, n);
 
-  HASH_INSERT2(hp->net[n->type].hash, NETINDEX, hp->pool, ni);
-  while (hp->net[n->type].block_size <= i)
+  HASH_INSERT2(hp->hash, NETINDEX, hp->pool, ni);
+  while (hp->block_size <= i)
   {
-    u32 bs = hp->net[n->type].block_size;
+    u32 bs = hp->block_size;
     struct netindex **nb = mb_alloc(hp->pool, bs * 2 * sizeof *nb);
-    memcpy(nb, hp->net[n->type].block, bs * sizeof *nb);
+    memcpy(nb, hp->block, bs * sizeof *nb);
     memset(&nb[bs], 0, bs * sizeof *nb);
 
-    mb_free(hp->net[n->type].block);
-    hp->net[n->type].block = nb;
+    mb_free(hp->block);
+    hp->block = nb;
 
-    hp->net[n->type].block_size *= 2;
+    hp->block_size *= 2;
   }
 
-  hp->net[n->type].block[i] = ni;
+  hp->block[i] = ni;
 
   return net_lock_revive_unlock(hp, ni);
 }
@@ -277,13 +255,10 @@ net_get_index(netindex_hash *h, const net_addr *n)
 }
 
 struct netindex *
-net_resolve_index(netindex_hash *h, u8 net_type, u32 i)
+net_resolve_index(netindex_hash *h, u32 i)
 {
   NH_LOCK(h, hp);
-  if (i >= hp->net[net_type].block_size)
-    return NULL;
 
-  struct netindex *ni = hp->net[net_type].block[i];
-  ASSERT_DIE(!ni || (ni->addr->type == net_type));
+  struct netindex *ni = hp->block[i];
   return net_lock_revive_unlock(hp, ni);
 }
index b2553212abdc75136c6a5d76d000cbee0dfa1eb6..8749afeb0c7f290e317541b4c0174c9036f2071c 100644 (file)
@@ -28,13 +28,13 @@ struct netindex {
 typedef union netindex_hash netindex_hash;
 
 /* Initialization and teardown */
-netindex_hash *netindex_hash_new(pool *, event_list *);
+netindex_hash *netindex_hash_new(pool *, event_list *, u8);
 void netindex_hash_delete(netindex_hash *, event *, event_list *);
 
 /* Find/get/resolve index; pointer valid until end of task */ 
 struct netindex *net_find_index(netindex_hash *, const net_addr *);
 struct netindex *net_get_index(netindex_hash *, const net_addr *);
-struct netindex *net_resolve_index(netindex_hash *, u8, u32);
+struct netindex *net_resolve_index(netindex_hash *, u32);
 
 /* Update use-count without allocating a handle. Take same care
  * to ensure that your locks and unlocks are always balanced. */
index 8e72a5c87de9d38bff16469b64018c6177137400..745870d8e8134d24eda76ffbcd995e2bbb17bf81 100644 (file)
   DOMAIN(attrs) lock;          /* Assigned lock */             \
   event_list *cleanup_list;    /* Cleanup event list */        \
   event cleanup_event;         /* Cleanup event */             \
+  u8 net_type;                 /* Which NET_* is stored */     \
 
 struct netindex_hash_private {
   struct { NETINDEX_HASH_PUBLIC; };
   struct netindex_hash_private **locked_at;
   pool *pool;
-  struct {
-    slab *slab;
-    HASH(struct netindex) hash;
-    uint block_size;
-    struct netindex **block;
-    struct hmap id_map;
-  } net[NET_MAX];
+  slab *slab;
+  HASH(struct netindex) hash;
+  uint block_size;
+  struct netindex **block;
+  struct hmap id_map;
   event *deleted_event;
   event_list *deleted_target;
 };
index 252c3d73b748f1c6a611d546273074aa7f4ae1fc..1713f4738bd770932b686430a4200b19e022657d 100644 (file)
@@ -252,7 +252,7 @@ rt_export_next_feed(struct rt_export_feeder *f)
     struct netindex *ni = NULL;
     u32 mfi = atomic_load_explicit(&e->max_feed_index, memory_order_acquire);
     for (; !ni && f->feed_index < mfi; f->feed_index++)
-      ni = net_resolve_index(e->netindex, e->net_type, f->feed_index);
+      ni = net_resolve_index(e->netindex, f->feed_index);
 
     if (!ni)
     {
index ffa4a84c735297d67572abf2ab4c8b0c796de63f..b06b2cd1326b8b68eb40339025d170aa1f827c53 100644 (file)
@@ -123,7 +123,7 @@ pool *rt_table_pool;
 list routing_tables;
 list deleted_routing_tables;
 
-netindex_hash *rt_global_netindex_hash;
+netindex_hash *rt_global_netindex_hash[NET_MAX];
 #define RT_INITIAL_ROUTES_BLOCK_SIZE   128
 
 struct rt_cork rt_cork;
@@ -2884,7 +2884,7 @@ rt_setup(pool *pp, struct rtable_config *cf)
   if (t->id >= rtable_max_id)
     rtable_max_id = t->id + 1;
 
-  t->netindex = rt_global_netindex_hash;
+  t->netindex = rt_global_netindex_hash[cf->addr_type];
   atomic_store_explicit(&t->routes, mb_allocz(p, RT_INITIAL_ROUTES_BLOCK_SIZE * sizeof(net)), memory_order_relaxed);
   atomic_store_explicit(&t->routes_block_size, RT_INITIAL_ROUTES_BLOCK_SIZE, memory_order_relaxed);
 
@@ -3025,7 +3025,9 @@ rt_init(void)
   ev_init_list(&rt_cork.queue, &main_birdloop, "Route cork release");
   rt_cork.run = (event) { .hook = rt_cork_release_hook };
   idm_init(&rtable_idm, rt_table_pool, 256);
-  rt_global_netindex_hash = netindex_hash_new(rt_table_pool, &global_event_list);
+
+  for (uint i=1; i<NET_MAX; i++)
+    rt_global_netindex_hash[i] = netindex_hash_new(rt_table_pool, &global_event_list, i);
 }
 
 static _Bool
index ec6cb508795d3e99082de1cf8b03b4fc4b748b36..63089e0ad56ddbf2aff086b7415ed6fa3934236b 100644 (file)
@@ -1694,7 +1694,7 @@ bgp_init_prefix_table(struct bgp_ptx_private *c)
    * locked while entering a loop. That's kinda stupid but i'm lazy now
    * to rework it. */
   ASSERT_DIE(!c->netindex);
-  c->netindex = netindex_hash_new(c->c->pool, proto_event_list(c->c->c.proto));
+  c->netindex = netindex_hash_new(c->c->pool, proto_event_list(c->c->c.proto), c->c->c.net_type);
 
   u32 len = 64;
   struct bgp_prefix * _Atomic * block = mb_allocz(c->pool, len * sizeof *block);