diff options
author | Maria Matejka <mq@ucw.cz> | 2022-05-15 15:53:35 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2022-05-26 14:53:09 +0200 |
commit | 4fe9881d625f10e44109a649e369a413bd98de71 (patch) | |
tree | ec9b7c5c5e59eba5684fc9df5b41c1ef20e14e05 /nest/rt-attr.c | |
parent | f15f2fcee7eeb5a100bd204a0e67018e25953420 (diff) |
Moved hostentry to eattr
Diffstat (limited to 'nest/rt-attr.c')
-rw-r--r-- | nest/rt-attr.c | 56 |
1 files changed, 46 insertions, 10 deletions
diff --git a/nest/rt-attr.c b/nest/rt-attr.c index bd7ca425..cf3ab659 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -114,10 +114,48 @@ struct ea_class ea_gen_nexthop = { .type = T_NEXTHOP_LIST, }; -struct ea_class ea_mpls_labels = { - .name = "mpls_labels", - .type = T_CLIST, +/* + * ea_set_hostentry() acquires hostentry from hostcache. + * New hostentry has zero use count. Cached rta locks its + * hostentry (increases its use count), uncached rta does not lock it. + * Hostentry with zero use count is removed asynchronously + * during host cache update, therefore it is safe to hold + * such hostentry temporarily as long as you hold the table lock. + * + * There is no need to hold a lock for hostentry->dep table, because that table + * contains routes responsible for that hostentry, and therefore is non-empty if + * given hostentry has non-zero use count. If the hostentry has zero use count, + * the entry is removed before dep is referenced. + * + * The protocol responsible for routes with recursive next hops should hold a + * lock for a 'source' table governing that routes (argument tab), + * because its routes reference hostentries related to the governing table. + * When all such routes are + * removed, rtas are immediately removed achieving zero uc. Then the 'source' + * table lock could be immediately released, although hostentries may still + * exist - they will be freed together with the 'source' table. + */ + + static void +ea_gen_hostentry_stored(const eattr *ea) +{ + struct hostentry_adata *had = (struct hostentry_adata *) ea->u.ptr; + 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--; +} + +struct ea_class ea_gen_hostentry = { + .name = "hostentry", + .type = T_HOSTENTRY, .readonly = 1, + .stored = ea_gen_hostentry_stored, + .freed = ea_gen_hostentry_freed, }; const char * rta_dest_names[RTD_MAX] = { @@ -876,6 +914,8 @@ ea_list_ref(ea_list *l) struct ea_class *cl = ea_class_global[a->id]; ASSERT_DIE(cl && cl->uc); + + CALL(cl->stored, a); cl->uc++; } } @@ -890,6 +930,8 @@ ea_list_unref(ea_list *l) struct ea_class *cl = ea_class_global[a->id]; ASSERT_DIE(cl && cl->uc); + + CALL(cl->freed, a); if (!--cl->uc) ea_class_free(cl); } @@ -1206,9 +1248,7 @@ rta_hash(rta *a) { u64 h; mem_hash_init(&h); -#define MIX(f) mem_hash_mix(&h, &(a->f), sizeof(a->f)); #define BMIX(f) mem_hash_mix_num(&h, a->f); - MIX(hostentry); BMIX(dest); #undef MIX @@ -1219,7 +1259,6 @@ static inline int rta_same(rta *x, rta *y) { return (x->dest == y->dest && - x->hostentry == y->hostentry && ea_same(x->eattrs, y->eattrs)); } @@ -1303,7 +1342,6 @@ rta_lookup(rta *o) r = rta_copy(o); r->hash_key = h; r->cached = 1; - rt_lock_hostentry(r->hostentry); rta_insert(r); if (++rta_cache_count > rta_cache_limit) @@ -1320,7 +1358,6 @@ rta__free(rta *a) *a->pprev = a->next; if (a->next) a->next->pprev = a->pprev; - rt_unlock_hostentry(a->hostentry); ea_free(a->eattrs); a->cached = 0; sl_free(a); @@ -1411,8 +1448,7 @@ rta_init(void) ea_register_init(&ea_gen_from); ea_register_init(&ea_gen_source); ea_register_init(&ea_gen_nexthop); - - ea_register_init(&ea_mpls_labels); + ea_register_init(&ea_gen_hostentry); } /* |