]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
This also hits the cork, maybe this refactoring is too brutal at once mq-too-big-refactoring-of-calbacks
authorMaria Matejka <mq@ucw.cz>
Sat, 15 Jun 2024 20:55:19 +0000 (22:55 +0200)
committerMaria Matejka <mq@ucw.cz>
Sat, 15 Jun 2024 20:55:19 +0000 (22:55 +0200)
lib/route.h
nest/mpls.c
nest/neighbor.c
nest/proto.c
nest/protocol.h
nest/route.h
nest/rt-attr.c
nest/rt-table.c

index 2b9a67256a78398b0a097e29204ac02e8de64895..de8d1c0fdb3d247d6c95269f0b2a5a4718f52f51 100644 (file)
@@ -87,8 +87,8 @@ struct rte_owner {
   u32 hash_key;
   u32 uc;
   u32 debug;
-  struct callback *prune_callback;
-  event *stop;
+  callback prune;
+  callback *stop;
 };
 
 extern DOMAIN(attrs) attrs_domain;
@@ -118,7 +118,7 @@ static inline void rt_lock_source(struct rte_src *src)
 
 static inline void rt_unlock_source(struct rte_src *src)
 {
-  lfuc_unlock(&src->uc, src->owner->prune_callback);
+  lfuc_unlock(&src->uc, &src->owner->prune);
 }
 
 #ifdef RT_SOURCE_DEBUG
@@ -129,8 +129,8 @@ static inline void rt_unlock_source(struct rte_src *src)
 #define rt_unlock_source(x) ( log(L_INFO "Unlock source %uG at %s:%d", (x)->global_id, __FILE__, __LINE__), _rt_unlock_source_internal(x) )
 #endif
 
-void rt_init_sources(struct rte_owner *, const char *name, event_list *list);
-void rt_destroy_sources(struct rte_owner *, event *);
+void rt_init_sources(struct rte_owner *, const char *name, struct birdloop *loop);
+void rt_destroy_sources(struct rte_owner *, callback *);
 
 void rt_dump_sources(struct rte_owner *);
 
index eca0d7d6d29eb8a66e0f466fda5aaf9a94e57857..517b43efa85efd1aff52de0d4b0ccce9b4ddadb4 100644 (file)
@@ -1239,7 +1239,7 @@ mpls_announce_fec(struct mpls_fec_map *m, struct mpls_fec *fec, ea_list *src)
     /* The same hostentry, but different dependent table */
     SKIP_BACK_DECLARE(struct hostentry_adata, head, ad, heea->u.ad);
     struct hostentry *he = head->he;
-    ea_set_hostentry(&e.attrs, m->channel->table, he->owner, he->addr, he->link,
+    ea_set_hostentry(&e.attrs, m->channel->table, he->owner->tab, he->addr, he->link,
        HOSTENTRY_LABEL_COUNT(head), head->labels);
   }
   else
index 991ed0ead51e0f4fcf0d6f9b538c657534f6b370..4103f3ab999e64648e7b8f56eab9fe29e392fb16 100644 (file)
@@ -395,7 +395,7 @@ neigh_unlink(neighbor *n)
   proto_neigh_rem_node(&p->neighbors, n);
 
   if ((p->proto_state == PS_DOWN) && EMPTY_TLIST(proto_neigh, &p->neighbors))
-    proto_send_event(p, p->event);
+    callback_activate(&p->done);
 
   n->proto = NULL;
 
index f74e8063bd3bcd90e97cf5dadfb7a5c9500cfbf2..1cf49681223575ed6a9416bd08b07b9887789082 100644 (file)
@@ -656,7 +656,7 @@ channel_check_stopped(struct channel *c)
       ASSERT_DIE(!rt_export_feed_active(&c->reimporter));
 
       channel_set_state(c, CS_DOWN);
-      proto_send_event(c->proto, c->proto->event);
+      callback_activate(&c->proto->done);
 
       break;
     case CS_PAUSE:
@@ -819,7 +819,7 @@ channel_do_down(struct channel *c)
 
   /* Schedule protocol shutddown */
   if (proto_is_done(c->proto))
-    proto_send_event(c->proto, c->proto->event);
+    callback_activate(&c->proto->done);
 }
 
 void
@@ -1182,9 +1182,9 @@ proto_loop_stopped(void *ptr)
 
 
 static void
-proto_event(void *ptr)
+proto_event(callback *cb)
 {
-  struct proto *p = ptr;
+  SKIP_BACK_DECLARE(struct proto, p, done, cb);
 
   if (p->do_stop)
   {
@@ -1249,7 +1249,7 @@ proto_init(struct proto_config *c, struct proto *after)
   p->vrf = c->vrf;
   proto_add_after(&global_proto_list, p, after);
 
-  p->event = ev_new_init(proto_pool, proto_event, p);
+  callback_init(&p->done, proto_event, p->loop);
 
   PD(p, "Initializing%s", p->disabled ? " [disabled]" : "");
 
@@ -1269,6 +1269,8 @@ proto_start(struct proto *p)
   {
     p->loop = birdloop_new(proto_pool, p->cf->loop_order, p->cf->loop_max_latency, "Protocol %s", p->cf->name);
     p->pool = birdloop_pool(p->loop);
+    ASSERT_DIE(!callback_is_active(&p->done));
+    p->done.target = p->loop;
   }
   else
     p->pool = rp_newf(proto_pool, the_bird_domain.the_bird, "Protocol %s", p->cf->name);
@@ -1680,7 +1682,7 @@ proto_rethink_goal(struct proto *p)
     OBSREF_CLEAR(p->global_config);
     proto_remove_channels(p);
     proto_rem_node(&global_proto_list, p);
-    rfree(p->event);
+    callback_cancel(&p->done);
     mb_free(p->message);
     mb_free(p);
     if (!nc)
@@ -2181,7 +2183,7 @@ proto_do_start(struct proto *p)
 {
   p->active = 1;
 
-  rt_init_sources(&p->sources, p->name, proto_event_list(p));
+  rt_init_sources(&p->sources, p->name, p->loop);
   if (!p->sources.class)
     p->sources.class = &default_rte_owner_class;
 
@@ -2226,10 +2228,10 @@ proto_do_stop(struct proto *p)
   p->pool_up = NULL;
 
   proto_stop_channels(p);
-  rt_destroy_sources(&p->sources, p->event);
+  rt_destroy_sources(&p->sources, &p->done);
 
   p->do_stop = 1;
-  proto_send_event(p, p->event);
+  callback_activate(&p->done);
 }
 
 static void
@@ -2239,7 +2241,7 @@ proto_do_down(struct proto *p)
 
   /* Shutdown is finished in the protocol event */
   if (proto_is_done(p))
-    proto_send_event(p, p->event);
+    callback_activate(&p->done);
 }
 
 
index ad43e9d97108ee599b3aff29e877c2af7d1173c5..c97c8cfe30ed444a1dac35e3713a1e94a5ed52b7 100644 (file)
@@ -141,7 +141,7 @@ struct proto {
                                           as the protocol enters the STOP / DOWN state */
   pool *pool_inloop;                   /* Pool containing local objects which need to be freed
                                           before the protocol's birdloop actually stops, like olocks */
-  event *event;                                /* Protocol event */
+  callback done;                       /* Protocol shutdown checker */
   timer *restart_timer;                        /* Timer to restart the protocol from limits */
   event *restart_event;                        /* Event to restart/shutdown the protocol from limits */
   struct birdloop *loop;               /* BIRDloop running this protocol */
index 452fe5182c416240377465b6b6d7c5d86cffe206..ae5141e9bbbd64163ececfe78058b61b534d4500 100644 (file)
@@ -361,7 +361,7 @@ extern uint rtable_max_id;
     _Atomic u32 routes_block_size;     /* Size of the route object pointer block */            \
     struct f_trie * _Atomic trie;      /* Trie of prefixes defined in fib */                   \
     event *nhu_event;                  /* Nexthop updater */                                   \
-    event *hcu_event;                  /* Hostcache updater */                                 \
+    callback shutdown_finished;                /* Shutdown finisher */                                 \
     struct rt_exporter export_all;     /* Route export journal for all routes */               \
     struct rt_exporter export_best;    /* Route export journal for best routes */              \
 
@@ -449,8 +449,10 @@ LOBJ_UNLOCK_CLEANUP(rtable, rtable);
 
 extern struct rt_cork {
   _Atomic uint active;
-  event_list queue;
-  event run;
+  struct rt_cork_callbacks {
+    struct rt_cork_callbacks *_Atomic next;
+    callback *uncork_block[0];
+  } *_Atomic callbacks;
 } rt_cork;
 
 static inline void rt_cork_acquire(void)
@@ -464,7 +466,7 @@ static inline void rt_cork_release(void)
     ev_send(&global_work_list, &rt_cork.run);
 }
 
-static inline _Bool rt_cork_check(event *e)
+static inline _Bool rt_cork_check(callback *cb)
 {
   int corked = (atomic_load_explicit(&rt_cork.active, memory_order_acquire) > 0);
   if (corked)
@@ -641,7 +643,7 @@ struct hostentry {
   ip_addr link;                                /* (link-local) IP address of host, used as gw
                                           if host is directly attached */
   rtable *tab;                         /* Dependent table, part of key */
-  rtable *owner;                       /* Nexthop owner table */
+  struct hostcache *owner;             /* Nexthop owner hostcache (use with care) */
   struct hostentry *next;              /* Next in hash chain */
   unsigned hash_key;                   /* Hash key */
   u32 igp_metric;                      /* Chosen route IGP metric */
@@ -658,11 +660,14 @@ struct hostcache {
   unsigned hash_order, hash_shift;
   unsigned hash_max, hash_min;
   unsigned hash_items;
+  u8 corked;                           /* Stuck by cork */
   linpool *lp;                         /* Linpool for trie */
   struct f_trie *trie;                 /* Trie of prefixes that might affect hostentries */
   list hostentries;                    /* List of all hostentries */
   struct rt_export_request req;                /* Notifier */
   event source_event;
+  callback update;                     /* Hostcache updater */
+  callback uncork;                     /* Hostcache uncorker */
 };
 
 struct rt_digestor {
index 538d670b2d2b36cc48543c5ffab9f81b66a6cede..7a0dd8086ac5b8810f9c657130beec50f497aa27 100644 (file)
@@ -150,7 +150,7 @@ static void
 ea_gen_hostentry_freed(const eattr *ea)
 {
   struct hostentry_adata *had = (struct hostentry_adata *) ea->u.ptr;
-  lfuc_unlock(&had->he->uc, birdloop_event_list(had->he->owner->loop), had->he->owner->hcu_event);
+  lfuc_unlock(&had->he->uc, &had->he->owner->update);
 }
 
 struct ea_class ea_gen_hostentry = {
@@ -244,7 +244,7 @@ rt_get_source_o(struct rte_owner *p, u32 id)
   if (p->stop)
     bug("Stopping route owner asked for another source.");
 
-  ASSERT_DIE(birdloop_inside(p->list->loop));
+  ASSERT_DIE(birdloop_inside(p->prune.target));
 
   struct rte_src *src = rt_find_source(p, id);
 
@@ -327,16 +327,10 @@ rt_find_source_global(u32 id)
   return src;
 }
 
-static inline void
-rt_done_sources(struct rte_owner *o)
-{
-  ev_send(o->list, o->stop);
-}
-
 void
-rt_prune_sources(void *data)
+rt_prune_sources(callback *cb)
 {
-  struct rte_owner *o = data;
+  SKIP_BACK_DECLARE(struct rte_owner, o, prune, cb);
 
   HASH_WALK_FILTER(o->hash, next, src, sp)
   {
@@ -365,13 +359,13 @@ rt_prune_sources(void *data)
 
   if (o->stop && !o->uc)
   {
-    rfree(o->prune);
+    callback_cancel(&o->prune);
     RTA_UNLOCK;
 
     if (o->debug & D_EVENTS)
       log(L_TRACE "%s: all rte_src's pruned, scheduling stop event", o->name);
 
-    rt_done_sources(o);
+    callback_activate(o->stop);
   }
   else
     RTA_UNLOCK;
@@ -402,23 +396,22 @@ rt_dump_sources(struct rte_owner *o)
 }
 
 void
-rt_init_sources(struct rte_owner *o, const char *name, event_list *list)
+rt_init_sources(struct rte_owner *o, const char *name, struct birdloop *loop)
 {
   RTA_LOCK;
   HASH_INIT(o->hash, rta_pool, RSH_INIT_ORDER);
   o->hash_key = random_u32();
   o->uc = 0;
   o->name = name;
-  o->prune = ev_new_init(rta_pool, rt_prune_sources, o);
+  callback_init(&o->prune, rt_prune_sources, loop);
   o->stop = NULL;
-  o->list = list;
   RTA_UNLOCK;
   if (o->debug & D_EVENTS)
     log(L_TRACE "%s: initialized rte_src owner", o->name);
 }
 
 void
-rt_destroy_sources(struct rte_owner *o, event *done)
+rt_destroy_sources(struct rte_owner *o, callback *done)
 {
   o->stop = done;
 
@@ -427,11 +420,7 @@ rt_destroy_sources(struct rte_owner *o, event *done)
     if (o->debug & D_EVENTS)
       log(L_TRACE "%s: rte_src owner destroy requested, already clean, scheduling stop event", o->name);
 
-    RTA_LOCK;
-    rfree(o->prune);
-    RTA_UNLOCK;
-
-    rt_done_sources(o);
+    callback_activate(o->stop);
   }
   else
     if (o->debug & D_EVENTS)
@@ -1386,9 +1375,9 @@ ea_show_hostentry(const struct adata *ad, byte *buf, uint size)
   uint s = 0;
 
   if (ipa_nonzero(had->he->link) && !ipa_equal(had->he->link, had->he->addr))
-    s = bsnprintf(buf, size, "via %I %I table %s", had->he->addr, had->he->link, had->he->owner->name);
+    s = bsnprintf(buf, size, "via %I %I table %s", had->he->addr, had->he->link, had->he->owner->tab->name);
   else
-    s = bsnprintf(buf, size, "via %I table %s", had->he->addr, had->he->owner->name);
+    s = bsnprintf(buf, size, "via %I table %s", had->he->addr, had->he->owner->tab->name);
 
   uint lc = HOSTENTRY_LABEL_COUNT(had);
   if (!lc)
@@ -1632,7 +1621,7 @@ static SPINHASH(struct ea_storage) rta_hash_table;
 #define RTAH_REHASH            rta_rehash
 #define RTAH_PARAMS            /8, *2, 2, 2, 12, 28
 
-static void RTAH_REHASH(void *_ UNUSED) {
+static void RTAH_REHASH(callback *_ UNUSED) {
   int step;
 
   RTA_LOCK;
@@ -1838,7 +1827,7 @@ rta_init(void)
   for (uint i=0; i<ARRAY_SIZE(ea_slab_sizes); i++)
     ea_slab[i] = sl_new(rta_pool, ea_slab_sizes[i]);
 
-  SPINHASH_INIT(rta_hash_table, RTAH, rta_pool, &global_work_list);
+  SPINHASH_INIT(rta_hash_table, RTAH, rta_pool, &main_birdloop);
 
   rte_src_init();
   ea_class_init();
index 593f79f9dfd1a3ec38ca163bcc1321407af88f72..06c0175dd455ab570ed0ffa52bdae74bcf3ebd01 100644 (file)
@@ -129,8 +129,8 @@ struct rt_cork rt_cork;
 /* Data structures for export journal */
 
 static void rt_free_hostcache(struct rtable_private *tab);
-static void rt_hcu_uncork(void *_tab);
-static void rt_update_hostcache(void *tab);
+static void rt_hcu_update(callback *);
+static void rt_hcu_uncork(callback *);
 static void rt_next_hop_update(void *_tab);
 static void rt_nhu_uncork(void *_tab);
 static inline void rt_next_hop_resolve_rte(rte *r);
@@ -3068,7 +3068,7 @@ rt_setup(pool *pp, struct rtable_config *cf)
   if (t->id >= rtable_max_id)
     rtable_max_id = t->id + 1;
 
-  t->netindex = netindex_hash_new(birdloop_pool(t->loop), birdloop_event_list(t->loop), cf->addr_type);
+  t->netindex = netindex_hash_new(birdloop_pool(t->loop), t->loop, 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);
 
@@ -4319,11 +4319,10 @@ rt_unlock_table_priv(struct rtable_private *r, const char *file, uint line)
 }
 
 static void
-rt_shutdown_finished(void *tab_)
+rt_shutdown_finished(struct callback *cb)
 {
-  rtable *t = tab_;
-  RT_LOCK(t, tab);
-  birdloop_stop_self(t->loop, rt_delete, t);
+  RT_LOCK(SKIP_BACK(rtable, shutdown_finished, cb), tab);
+  birdloop_stop_self(tab->loop, rt_delete, tab);
 }
 
 static void
@@ -4332,6 +4331,8 @@ rt_shutdown(void *tab_)
   rtable *t = tab_;
   RT_LOCK(t, tab);
 
+  callback_init(&tab->shutdown_finished, rt_shutdown_finished, tab->loop);
+
   if (tab->export_digest)
   {
     rtex_export_unsubscribe(&tab->export_digest->req);
@@ -4345,9 +4346,7 @@ rt_shutdown(void *tab_)
   rt_exporter_shutdown(&tab->export_best, NULL);
   rt_exporter_shutdown(&tab->export_all, NULL);
 
-  netindex_hash_delete(tab->netindex,
-      ev_new_init(tab->rp, rt_shutdown_finished, tab),
-      birdloop_event_list(tab->loop));
+  netindex_hash_delete(tab->netindex, &tab->shutdown_finished);
 }
 
 static void
@@ -4495,13 +4494,9 @@ rt_commit(struct config *new, struct config *old)
 
          rt_check_cork_low(tab);
 
-         if (tab->hcu_event)
-         {
-           if (ev_get_list(tab->hcu_event) == &rt_cork.queue)
-             ev_postpone(tab->hcu_event);
-
+         /* Stop the hostcache updater */
+         if (rt_export_get_state(&tab->hostcache->req) != TES_DOWN)
            rtex_export_unsubscribe(&tab->hostcache->req);
-         }
 
          rt_unlock_table(tab);
        }
@@ -4637,6 +4632,9 @@ hc_notify_export(void *_hc)
 
   RT_EXPORT_WALK(&hc->req, u)
   {
+    if (callback_is_active(&hc->update))
+      continue;
+
     const net_addr *n = NULL;
     switch (u->kind)
     {
@@ -4676,9 +4674,6 @@ hc_notify_export(void *_hc)
       continue;
 
     RT_LOCK(hc->tab, tab);
-    if (ev_active(tab->hcu_event))
-      continue;
-
     if (!trie_match_net(hc->trie, n))
     {
       /* No interest in this update, mark seen only */
@@ -4693,12 +4688,12 @@ hc_notify_export(void *_hc)
            hc->req.name, n, NET_TO_INDEX(n)->index);
 
       if ((rt_export_get_state(&hc->req) == TES_READY)
-         && !ev_active(tab->hcu_event))
+         && !callback_is_active(&hc->update))
       {
        if (hc->req.trace_routes & D_EVENTS)
          log(L_TRACE "%s requesting HCU", hc->req.name);
 
-       ev_send_loop(tab->loop, tab->hcu_event);
+       callback_activate(&hc->update);
       }
     }
 
@@ -4722,12 +4717,11 @@ rt_init_hostcache(struct rtable_private *tab)
   hc->trie = f_new_trie(hc->lp, 0);
 
   hc->tab = RT_PUB(tab);
-
-  tab->hcu_event = ev_new_init(tab->rp, rt_update_hostcache, tab);
-  tab->hcu_uncork_event = ev_new_init(tab->rp, rt_hcu_uncork, tab);
   tab->hostcache = hc;
 
-  ev_send_loop(tab->loop, tab->hcu_event);
+  rt_lock_table(tab);
+  callback_init(&hc->update, rt_hcu_update, tab->loop);
+  callback_activate(&hc->update);
 }
 
 static void
@@ -4877,20 +4871,9 @@ done:
 }
 
 static void
-rt_hcu_uncork(void *_tab)
+rt_update_hostcache(struct hostcache *hc, rtable **nhu_pending)
 {
-  RT_LOCKED((rtable *) _tab, tab)
-    ev_send_loop(tab->loop, tab->hcu_event);
-}
-
-static void
-rt_update_hostcache(void *data)
-{
-  rtable **nhu_pending;
-
-  RT_LOCKED((rtable *) data, tab)
-  {
-  struct hostcache *hc = tab->hostcache;
+  RT_LOCK(hc->tab, tab);
 
   /* Finish initialization */
   if (!hc->req.name)
@@ -4913,19 +4896,6 @@ rt_update_hostcache(void *data)
     rtex_export_subscribe(&tab->export_best, &hc->req);
   }
 
-  /* Shutdown shortcut */
-  if (rt_export_get_state(&hc->req) == TES_DOWN)
-    return;
-
-  if (rt_cork_check(tab->hcu_uncork_event))
-  {
-    rt_trace(tab, D_STATES, "Hostcache update corked");
-    return;
-  }
-
-  /* Destination schedule map */
-  nhu_pending = tmp_allocz(sizeof(rtable *) * rtable_max_id);
-
   struct hostentry *he;
   node *n, *x;
 
@@ -4947,12 +4917,52 @@ rt_update_hostcache(void *data)
     }
   }
 
+static void
+rt_hcu_update(struct callback *cb)
+{
+  SKIP_BACK_DECLARE(struct hostcache, hc, update, cb);
+
+  /* Still corked, do nothing */
+  if (hc->corked)
+    return;
+
+  /* Shutdown shortcut */
+  if (hc->req.name && (rt_export_get_state(&hc->req) == TES_DOWN))
+  {
+    RT_LOCK(hc->tab, tab);
+    rt_unlock_table(tab);
+    return;
+  }
+
+  /* Cork check */
+  if (rt_cork_check(&hc->uncork))
+  {
+    hc->corked = 1;
+    rt_trace(tab, D_STATES, "Hostcache update corked");
+    return;
+  }
+
+  /* Destination schedule map */
+  rtable **nhu_pending = tmp_allocz(sizeof(rtable *) * rtable_max_id);
+
+  /* Find which destinations we have to ping */
+  rt_update_hostcache(hc, &nhu_pending);
+
+  /* And do the pinging */
   for (uint i=0; i<rtable_max_id; i++)
     if (nhu_pending[i])
       RT_LOCKED(nhu_pending[i], dst)
        rt_schedule_nhu(dst);
 }
 
+static void
+rt_hcu_uncork(struct callback *cb)
+{
+  SKIP_BACK_DECLARE(struct hostcache, hc, uncork, cb);
+  hc->corked = 0;
+  callback_activate(&hc->update);
+}
+
 static struct hostentry *
 rt_get_hostentry(struct rtable_private *tab, ip_addr a, ip_addr ll, rtable *dep)
 {