0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00

Hostentry usecount converted to lfuc

This commit is contained in:
Maria Matejka 2024-03-05 14:25:52 +01:00 committed by Katerina Kubecova
parent a3b125e223
commit 7c4db11b9f
3 changed files with 33 additions and 60 deletions

View File

@ -92,6 +92,7 @@ extern uint rtable_max_id;
struct birdloop *loop; /* Service thread */ \ struct birdloop *loop; /* Service thread */ \
netindex_hash *netindex; /* Prefix index for this table */ \ netindex_hash *netindex; /* Prefix index for this table */ \
event *nhu_event; /* Nexthop updater */ \ event *nhu_event; /* Nexthop updater */ \
event *hcu_event; /* Hostcache updater */ \
/* The complete rtable structure */ /* The complete rtable structure */
struct rtable_private { struct rtable_private {
@ -121,6 +122,7 @@ struct rtable_private {
* obstacle from this routing table. * obstacle from this routing table.
*/ */
struct event *nhu_uncork_event; /* Helper event to schedule NHU on uncork */ 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 timer *prune_timer; /* Timer for periodic pruning / GC */
struct event *prune_event; /* Event for prune execution */ struct event *prune_event; /* Event for prune execution */
struct birdloop_flag_handler fh; /* Handler for simple events */ struct birdloop_flag_handler fh; /* Handler for simple events */
@ -503,14 +505,15 @@ struct hostentry {
rtable *owner; /* Nexthop owner table */ rtable *owner; /* Nexthop owner table */
struct hostentry *next; /* Next in hash chain */ struct hostentry *next; /* Next in hash chain */
unsigned hash_key; /* Hash key */ unsigned hash_key; /* Hash key */
unsigned uc; /* Use count */
ea_list *src; /* Source attributes */
byte nexthop_linkable; /* Nexthop list is completely non-device */
u32 igp_metric; /* Chosen route IGP metric */ 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 */
}; };
struct hostcache { struct hostcache {
slab *slab; /* Slab holding all hostentries */ slab *slab; /* Slab holding all hostentries */
rtable *tab; /* Parent routing table */
struct hostentry **hash_table; /* Hash table for hostentries */ struct hostentry **hash_table; /* Hash table for hostentries */
unsigned hash_order, hash_shift; unsigned hash_order, hash_shift;
unsigned hash_max, hash_min; unsigned hash_max, hash_min;
@ -518,7 +521,6 @@ struct hostcache {
linpool *lp; /* Linpool for trie */ linpool *lp; /* Linpool for trie */
struct f_trie *trie; /* Trie of prefixes that might affect hostentries */ struct f_trie *trie; /* Trie of prefixes that might affect hostentries */
list hostentries; /* List of all hostentries */ list hostentries; /* List of all hostentries */
event update;
struct rt_export_request req; /* Notifier */ struct rt_export_request req; /* Notifier */
}; };

View File

@ -143,14 +143,14 @@ struct ea_class ea_gen_nexthop = {
ea_gen_hostentry_stored(const eattr *ea) ea_gen_hostentry_stored(const eattr *ea)
{ {
struct hostentry_adata *had = (struct hostentry_adata *) ea->u.ptr; struct hostentry_adata *had = (struct hostentry_adata *) ea->u.ptr;
had->he->uc++; lfuc_lock(&had->he->uc);
} }
static void static void
ea_gen_hostentry_freed(const eattr *ea) ea_gen_hostentry_freed(const eattr *ea)
{ {
struct hostentry_adata *had = (struct hostentry_adata *) ea->u.ptr; 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 = { struct ea_class ea_gen_hostentry = {

View File

@ -3812,8 +3812,8 @@ rt_commit(struct config *new, struct config *old)
rt_check_cork_low(tab); rt_check_cork_low(tab);
if (tab->hostcache && ev_get_list(&tab->hostcache->update) == &rt_cork.queue) if (tab->hcu_event && (ev_get_list(tab->hcu_event) == &rt_cork.queue))
ev_postpone(&tab->hostcache->update); ev_postpone(tab->hcu_event);
/* Force one more loop run */ /* Force one more loop run */
birdloop_flag(tab->loop, RTF_DELETE); birdloop_flag(tab->loop, RTF_DELETE);
@ -4223,7 +4223,7 @@ static void
hc_notify_log_state_change(struct rt_export_request *req, u8 state) hc_notify_log_state_change(struct rt_export_request *req, u8 state)
{ {
struct hostcache *hc = SKIP_BACK(struct hostcache, req, req); 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 static void
@ -4231,8 +4231,8 @@ hc_notify_export_one(struct rt_export_request *req, const net_addr *net, struct
{ {
struct hostcache *hc = SKIP_BACK(struct hostcache, req, req); struct hostcache *hc = SKIP_BACK(struct hostcache, req, req);
RT_LOCKED((rtable *) hc->update.data, tab) RT_LOCKED(hc->tab, tab)
if (ev_active(&hc->update) || !trie_match_net(hc->trie, net)) if (ev_active(tab->hcu_event) || !trie_match_net(hc->trie, net))
/* No interest in this update, mark seen only */ /* No interest in this update, mark seen only */
rpe_mark_seen_all(req->hook, first, NULL, NULL); rpe_mark_seen_all(req->hook, first, NULL, NULL);
else else
@ -4250,8 +4250,8 @@ hc_notify_export_one(struct rt_export_request *req, const net_addr *net, struct
/* Yes, something has actually changed. Do the hostcache update. */ /* Yes, something has actually changed. Do the hostcache update. */
if ((o != RTE_VALID_OR_NULL(new_best)) if ((o != RTE_VALID_OR_NULL(new_best))
&& (atomic_load_explicit(&req->hook->export_state, memory_order_acquire) == TES_READY) && (atomic_load_explicit(&req->hook->export_state, memory_order_acquire) == TES_READY)
&& !ev_active(&hc->update)) && !ev_active(tab->hcu_event))
ev_send_loop(tab->loop, &hc->update); ev_send_loop(tab->loop, tab->hcu_event);
} }
} }
@ -4269,14 +4269,13 @@ rt_init_hostcache(struct rtable_private *tab)
hc->lp = lp_new(tab->rp); hc->lp = lp_new(tab->rp);
hc->trie = f_new_trie(hc->lp, 0); hc->trie = f_new_trie(hc->lp, 0);
hc->update = (event) { hc->tab = RT_PUB(tab);
.hook = rt_update_hostcache,
.data = 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; tab->hostcache = hc;
ev_send_loop(tab->loop, &hc->update); ev_send_loop(tab->loop, tab->hcu_event);
} }
static void static void
@ -4290,7 +4289,7 @@ rt_free_hostcache(struct rtable_private *tab)
struct hostentry *he = SKIP_BACK(struct hostentry, ln, n); struct hostentry *he = SKIP_BACK(struct hostentry, ln, n);
rta_free(he->src); rta_free(he->src);
if (he->uc) if (!lfuc_finished(&he->uc))
log(L_ERR "Hostcache is not empty in table %s", tab->name); log(L_ERR "Hostcache is not empty in table %s", tab->name);
} }
@ -4426,7 +4425,7 @@ rt_update_hostcache(void *data)
if (!hc->req.hook) if (!hc->req.hook)
return; return;
if (rt_cork_check(&hc->update)) if (rt_cork_check(tab->hcu_uncork_event))
{ {
rt_trace(tab, D_STATES, "Hostcache update corked"); rt_trace(tab, D_STATES, "Hostcache update corked");
return; return;
@ -4445,11 +4444,11 @@ rt_update_hostcache(void *data)
WALK_LIST_DELSAFE(n, x, hc->hostentries) WALK_LIST_DELSAFE(n, x, hc->hostentries)
{ {
he = SKIP_BACK(struct hostentry, ln, n); he = SKIP_BACK(struct hostentry, ln, n);
if (!he->uc) if (lfuc_finished(&he->uc))
{ {
hc_delete_hostentry(hc, tab->rp, he); hc_delete_hostentry(hc, tab->rp, he);
continue; continue;
} }
if (rt_update_hostentry(tab, he)) if (rt_update_hostentry(tab, he))
nhu_pending[he->tab->id] = he->tab; nhu_pending[he->tab->id] = he->tab;
@ -4462,36 +4461,6 @@ rt_update_hostcache(void *data)
rt_schedule_nhu(dst); 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 * static struct hostentry *
rt_get_hostentry(struct rtable_private *tab, ip_addr a, ip_addr ll, rtable *dep) rt_get_hostentry(struct rtable_private *tab, ip_addr a, ip_addr ll, rtable *dep)
{ {
@ -4507,17 +4476,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)) if (ipa_equal(he->addr, a) && ipa_equal(he->link, link) && (he->tab == dep))
break; break;
if (!he) if (he)
lfuc_lock(&he->uc);
else
{ {
he = hc_new_hostentry(hc, tab->rp, a, link, dep, k); he = hc_new_hostentry(hc, tab->rp, a, link, dep, k);
lfuc_lock_revive(&he->uc);
he->owner = RT_PUB(tab); he->owner = RT_PUB(tab);
rt_update_hostentry(tab, he); rt_update_hostentry(tab, he);
} }
struct hostentry_tmp_lock *l = ralloc(tmp_res.pool, &hostentry_tmp_lock_class); /* Free the hostentry if filtered out */
l->he = he; lfuc_unlock(&he->uc, birdloop_event_list(tab->loop), tab->hcu_event);
l->tab = RT_PUB(tab);
l->he->uc++;
return he; return he;
} }