]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Hostentry usecount converted to lfuc
authorMaria Matejka <mq@ucw.cz>
Tue, 5 Mar 2024 13:25:52 +0000 (14:25 +0100)
committerMaria Matejka <mq@ucw.cz>
Sat, 6 Apr 2024 16:28:43 +0000 (18:28 +0200)
nest/route.h
nest/rt-attr.c
nest/rt-table.c

index 0e5cd20f45ec298d60162acdc6307641fb5cd04e..7850a54cf408d85e7dd5f7c984f88747b27518fd 100644 (file)
@@ -92,6 +92,7 @@ extern uint rtable_max_id;
     struct birdloop *loop;             /* Service thread */                                    \
     netindex_hash *netindex;           /* Prefix index for this table */                       \
     event *nhu_event;                  /* Nexthop updater */                                   \
+    event *hcu_event;                  /* Hostcache updater */                                 \
 
 /* The complete rtable structure */
 struct rtable_private {
@@ -121,6 +122,7 @@ struct rtable_private {
                                         * obstacle from this routing table.
                                         */
   struct event *nhu_uncork_event;      /* Helper event to schedule NHU on uncork */
+  struct event *hcu_uncork_event;      /* Helper event to schedule HCU on uncork */
   struct timer *prune_timer;           /* Timer for periodic pruning / GC */
   struct event *prune_event;           /* Event for prune execution */
   struct birdloop_flag_handler fh;     /* Handler for simple events */
@@ -503,14 +505,15 @@ struct hostentry {
   rtable *owner;                       /* Nexthop owner table */
   struct hostentry *next;              /* Next in hash chain */
   unsigned hash_key;                   /* Hash key */
-  unsigned uc;                         /* Use count */
+  u32 igp_metric;                      /* Chosen route IGP metric */
   ea_list *src;                                /* Source attributes */
+  struct lfuc uc;                      /* Use count */
   byte nexthop_linkable;               /* Nexthop list is completely non-device */
-  u32 igp_metric;                      /* Chosen route IGP metric */
 };
 
 struct hostcache {
   slab *slab;                          /* Slab holding all hostentries */
+  rtable *tab;                         /* Parent routing table */
   struct hostentry **hash_table;       /* Hash table for hostentries */
   unsigned hash_order, hash_shift;
   unsigned hash_max, hash_min;
@@ -518,7 +521,6 @@ struct hostcache {
   linpool *lp;                         /* Linpool for trie */
   struct f_trie *trie;                 /* Trie of prefixes that might affect hostentries */
   list hostentries;                    /* List of all hostentries */
-  event update;
   struct rt_export_request req;                /* Notifier */
 };
 
index 546c67dba0bb774c75b0d92bee186fbc5f843497..50283f4212c8126fd0f01487adf1aa582b2d3927 100644 (file)
@@ -143,14 +143,14 @@ struct ea_class ea_gen_nexthop = {
 ea_gen_hostentry_stored(const eattr *ea)
 {
   struct hostentry_adata *had = (struct hostentry_adata *) ea->u.ptr;
-  had->he->uc++;
+  lfuc_lock(&had->he->uc);
 }
 
 static void
 ea_gen_hostentry_freed(const eattr *ea)
 {
   struct hostentry_adata *had = (struct hostentry_adata *) ea->u.ptr;
-  had->he->uc--;
+  lfuc_unlock(&had->he->uc, birdloop_event_list(had->he->owner->loop), had->he->owner->hcu_event);
 }
 
 struct ea_class ea_gen_hostentry = {
index e37c8005b311b6fd0fbccb76623f92afcf291329..ef849e625cc1996bc283e60d4c9922f12daf35d4 100644 (file)
@@ -3815,8 +3815,8 @@ rt_commit(struct config *new, struct config *old)
 
          rt_check_cork_low(tab);
 
-         if (tab->hostcache && ev_get_list(&tab->hostcache->update) == &rt_cork.queue)
-           ev_postpone(&tab->hostcache->update);
+         if (tab->hcu_event && (ev_get_list(tab->hcu_event) == &rt_cork.queue))
+           ev_postpone(tab->hcu_event);
 
          /* Force one more loop run */
          birdloop_flag(tab->loop, RTF_DELETE);
@@ -4226,7 +4226,7 @@ static void
 hc_notify_log_state_change(struct rt_export_request *req, u8 state)
 {
   struct hostcache *hc = SKIP_BACK(struct hostcache, req, req);
-  rt_trace((rtable *) hc->update.data, D_STATES, "HCU Export state changed to %s", rt_export_state_name(state));
+  rt_trace(hc->tab, D_STATES, "HCU Export state changed to %s", rt_export_state_name(state));
 }
 
 static void
@@ -4234,8 +4234,8 @@ hc_notify_export_one(struct rt_export_request *req, const net_addr *net, struct
 {
   struct hostcache *hc = SKIP_BACK(struct hostcache, req, req);
 
-  RT_LOCKED((rtable *) hc->update.data, tab)
-    if (ev_active(&hc->update) || !trie_match_net(hc->trie, net))
+  RT_LOCKED(hc->tab, tab)
+    if (ev_active(tab->hcu_event) || !trie_match_net(hc->trie, net))
       /* No interest in this update, mark seen only */
       rpe_mark_seen_all(req->hook, first, NULL, NULL);
     else
@@ -4253,8 +4253,8 @@ hc_notify_export_one(struct rt_export_request *req, const net_addr *net, struct
       /* Yes, something has actually changed. Do the hostcache update. */
       if ((o != RTE_VALID_OR_NULL(new_best))
          && (atomic_load_explicit(&req->hook->export_state, memory_order_acquire) == TES_READY)
-         && !ev_active(&hc->update))
-       ev_send_loop(tab->loop, &hc->update);
+         && !ev_active(tab->hcu_event))
+       ev_send_loop(tab->loop, tab->hcu_event);
     }
 }
 
@@ -4272,14 +4272,13 @@ rt_init_hostcache(struct rtable_private *tab)
   hc->lp = lp_new(tab->rp);
   hc->trie = f_new_trie(hc->lp, 0);
 
-  hc->update = (event) {
-    .hook = rt_update_hostcache,
-    .data = tab,
-  };
+  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_update_hostcache, tab);
   tab->hostcache = hc;
 
-  ev_send_loop(tab->loop, &hc->update);
+  ev_send_loop(tab->loop, tab->hcu_event);
 }
 
 static void
@@ -4293,7 +4292,7 @@ rt_free_hostcache(struct rtable_private *tab)
       struct hostentry *he = SKIP_BACK(struct hostentry, ln, n);
       rta_free(he->src);
 
-      if (he->uc)
+      if (!lfuc_finished(&he->uc))
        log(L_ERR "Hostcache is not empty in table %s", tab->name);
     }
 
@@ -4429,7 +4428,7 @@ rt_update_hostcache(void *data)
   if (!hc->req.hook)
     return;
 
-  if (rt_cork_check(&hc->update))
+  if (rt_cork_check(tab->hcu_uncork_event))
   {
     rt_trace(tab, D_STATES, "Hostcache update corked");
     return;
@@ -4448,11 +4447,11 @@ rt_update_hostcache(void *data)
   WALK_LIST_DELSAFE(n, x, hc->hostentries)
     {
       he = SKIP_BACK(struct hostentry, ln, n);
-      if (!he->uc)
-       {
-         hc_delete_hostentry(hc, tab->rp, he);
-         continue;
-       }
+      if (lfuc_finished(&he->uc))
+      {
+       hc_delete_hostentry(hc, tab->rp, he);
+       continue;
+      }
 
       if (rt_update_hostentry(tab, he))
        nhu_pending[he->tab->id] = he->tab;
@@ -4465,36 +4464,6 @@ rt_update_hostcache(void *data)
        rt_schedule_nhu(dst);
 }
 
-struct hostentry_tmp_lock {
-  resource r;
-  rtable *tab;
-  struct hostentry *he;
-};
-
-static void
-hostentry_tmp_unlock(resource *r)
-{
-  struct hostentry_tmp_lock *l = SKIP_BACK(struct hostentry_tmp_lock, r, r);
-  RT_LOCKED(l->tab, tab)
-    l->he->uc--;
-}
-
-static void
-hostentry_tmp_lock_dump(resource *r, unsigned indent UNUSED)
-{
-  struct hostentry_tmp_lock *l = SKIP_BACK(struct hostentry_tmp_lock, r, r);
-  debug("he=%p tab=%s\n", l->he, l->tab->name);
-}
-
-struct resclass hostentry_tmp_lock_class = {
-  .name = "Temporary hostentry lock",
-  .size = sizeof(struct hostentry_tmp_lock),
-  .free = hostentry_tmp_unlock,
-  .dump = hostentry_tmp_lock_dump,
-  .lookup = NULL,
-  .memsize = NULL,
-};
-
 static struct hostentry *
 rt_get_hostentry(struct rtable_private *tab, ip_addr a, ip_addr ll, rtable *dep)
 {
@@ -4510,17 +4479,19 @@ rt_get_hostentry(struct rtable_private *tab, ip_addr a, ip_addr ll, rtable *dep)
     if (ipa_equal(he->addr, a) && ipa_equal(he->link, link) && (he->tab == dep))
       break;
 
-  if (!he)
+  if (he)
+    lfuc_lock(&he->uc);
+  else
   {
     he = hc_new_hostentry(hc, tab->rp, a, link, dep, k);
+    lfuc_lock_revive(&he->uc);
+
     he->owner = RT_PUB(tab);
     rt_update_hostentry(tab, he);
   }
 
-  struct hostentry_tmp_lock *l = ralloc(tmp_res.pool, &hostentry_tmp_lock_class);
-  l->he = he;
-  l->tab = RT_PUB(tab);
-  l->he->uc++;
+  /* Free the hostentry if filtered out */
+  lfuc_unlock(&he->uc, birdloop_event_list(tab->loop), tab->hcu_event);
 
   return he;
 }