summaryrefslogtreecommitdiff
path: root/nest/rt-attr.c
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2021-09-27 17:44:19 +0200
committerMaria Matejka <mq@ucw.cz>2021-11-22 19:05:44 +0100
commit038fcf1c8b7716415235384de5dc47d07dc45b85 (patch)
tree835ce12854356d7341e00338bb00969aae02454a /nest/rt-attr.c
parentf0507f05ce57398e135651896dace4cb68eeed54 (diff)
Locking route attributes cache
To access route attribute cache from multiple threads at once, we have to lock the cache on writing. The route attributes data structures are safe to read unless somebody tries to tamper with the cache itself.
Diffstat (limited to 'nest/rt-attr.c')
-rw-r--r--nest/rt-attr.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index f7e33d72..20f9835d 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -1281,9 +1281,16 @@ rta_lookup(rta *o)
ea_normalize(o->eattrs);
h = rta_hash(o);
+
+ RTA_LOCK;
+
for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next)
if (r->hash_key == h && rta_same(r, o))
- return rta_clone(r);
+ {
+ atomic_fetch_add_explicit(&r->uc, 1, memory_order_acq_rel);
+ RTA_UNLOCK;
+ return r;
+ }
r = rta_copy(o);
r->hash_key = h;
@@ -1294,12 +1301,21 @@ rta_lookup(rta *o)
if (++rta_cache_count > rta_cache_limit)
rta_rehash();
+ RTA_UNLOCK;
return r;
}
void
rta__free(rta *a)
{
+ RTA_LOCK;
+ if (atomic_load_explicit(&a->uc, memory_order_acquire))
+ {
+ /* Somebody has cloned this rta inbetween. This sometimes happens. */
+ RTA_UNLOCK;
+ return;
+ }
+
ASSERT(rta_cache_count && a->cached);
rta_cache_count--;
*a->pprev = a->next;
@@ -1311,6 +1327,7 @@ rta__free(rta *a)
ea_free(a->eattrs);
a->cached = 0;
sl_free(rta_slab(a), a);
+ RTA_UNLOCK;
}
rta *
@@ -1335,7 +1352,7 @@ rta_do_cow(rta *o, linpool *lp)
* This function takes a &rta and dumps its contents to the debug output.
*/
void
-rta_dump(rta *a)
+rta_dump(const rta *a)
{
static char *rts[] = { "", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE",
"RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP",
@@ -1350,7 +1367,7 @@ rta_dump(rta *a)
debug(" !CACHED");
debug(" <-%I", a->from);
if (a->dest == RTD_UNICAST)
- for (struct nexthop *nh = &(a->nh); nh; nh = nh->next)
+ for (const struct nexthop *nh = &(a->nh); nh; nh = nh->next)
{
if (ipa_nonzero(nh->gw)) debug(" ->%I", nh->gw);
if (nh->labels) debug(" L %d", nh->label[0]);
@@ -1377,6 +1394,8 @@ rta_dump_all(void)
rta *a;
uint h;
+ RTA_LOCK;
+
debug("Route attribute cache (%d entries, rehash at %d):\n", rta_cache_count, rta_cache_limit);
for(h=0; h<rta_cache_size; h++)
for(a=rta_hash_table[h]; a; a=a->next)
@@ -1386,10 +1405,12 @@ rta_dump_all(void)
debug("\n");
}
debug("\n");
+
+ RTA_UNLOCK;
}
void
-rta_show(struct cli *c, rta *a)
+rta_show(struct cli *c, const rta *a)
{
cli_printf(c, -1008, "\tType: %s %s", rta_src_names[a->source], ip_scope_text(a->scope));