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:
parent
622d406087
commit
cacf743dcb
10
nest/route.h
10
nest/route.h
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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 = {
|
||||||
|
@ -3815,8 +3815,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);
|
||||||
@ -4226,7 +4226,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
|
||||||
@ -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);
|
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
|
||||||
@ -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. */
|
/* 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4272,14 +4272,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
|
||||||
@ -4293,7 +4292,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4429,7 +4428,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;
|
||||||
@ -4448,7 +4447,7 @@ 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;
|
||||||
@ -4465,36 +4464,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)
|
||||||
{
|
{
|
||||||
@ -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))
|
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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user