0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

Hostentry usecount converted to lfuc

This commit is contained in:
Maria Matejka 2024-03-05 14:25:52 +01:00
parent e0a1bbdf65
commit 728d19703d
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 */ \
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 */
ea_list *src; /* Source attributes */
byte nexthop_linkable; /* Nexthop list is completely non-device */
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 {
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 */
};

View 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 = {

View File

@ -3812,8 +3812,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);
@ -4223,7 +4223,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
@ -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);
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
@ -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. */
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);
}
}
@ -4269,14 +4269,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
@ -4290,7 +4289,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);
}
@ -4426,7 +4425,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;
@ -4445,11 +4444,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;
@ -4462,36 +4461,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)
{
@ -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))
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;
}