mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Route attributes async free
This commit is contained in:
parent
60267ddeca
commit
42132be5a8
16
nest/route.h
16
nest/route.h
@ -447,7 +447,8 @@ typedef struct rta {
|
|||||||
ip_addr from; /* Advertising router */
|
ip_addr from; /* Advertising router */
|
||||||
u32 igp_metric; /* IGP metric to next hop (for iBGP routes) */
|
u32 igp_metric; /* IGP metric to next hop (for iBGP routes) */
|
||||||
u16 cached:1; /* Are attributes cached? */
|
u16 cached:1; /* Are attributes cached? */
|
||||||
u16 source:7; /* Route source (RTS_...) */
|
u16 obsolete:1; /* This rta is going to be freed */
|
||||||
|
u16 source:6; /* Route source (RTS_...) */
|
||||||
u16 scope:4; /* Route scope (SCOPE_... -- see ip.h) */
|
u16 scope:4; /* Route scope (SCOPE_... -- see ip.h) */
|
||||||
u16 dest:4; /* Route destination type (RTD_...) */
|
u16 dest:4; /* Route destination type (RTD_...) */
|
||||||
word pref;
|
word pref;
|
||||||
@ -666,9 +667,16 @@ static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a
|
|||||||
#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
|
#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
|
||||||
rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */
|
rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */
|
||||||
static inline int rta_is_cached(rta *r) { return r->cached; }
|
static inline int rta_is_cached(rta *r) { return r->cached; }
|
||||||
static inline rta *rta_clone(rta *r) { r->uc++; return r; }
|
static inline rta *rta_clone(rta *r)
|
||||||
void rta__free(rta *r);
|
{
|
||||||
static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); }
|
if (r->obsolete)
|
||||||
|
return rta_lookup(r);
|
||||||
|
|
||||||
|
r->uc++;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
void rta_unlink(rta *r);
|
||||||
|
static inline void rta_free(rta *r) { if (r && !--r->uc) rta_unlink(r); }
|
||||||
rta *rta_do_cow(rta *o, linpool *lp);
|
rta *rta_do_cow(rta *o, linpool *lp);
|
||||||
static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; }
|
static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; }
|
||||||
void rta_dump(rta *);
|
void rta_dump(rta *);
|
||||||
|
116
nest/rt-attr.c
116
nest/rt-attr.c
@ -51,12 +51,14 @@
|
|||||||
#include "nest/cli.h"
|
#include "nest/cli.h"
|
||||||
#include "nest/attrs.h"
|
#include "nest/attrs.h"
|
||||||
#include "lib/alloca.h"
|
#include "lib/alloca.h"
|
||||||
|
#include "lib/gc.h"
|
||||||
#include "lib/hash.h"
|
#include "lib/hash.h"
|
||||||
#include "lib/idm.h"
|
#include "lib/idm.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
const adata null_adata; /* adata of length 0 */
|
const adata null_adata; /* adata of length 0 */
|
||||||
|
|
||||||
@ -1080,6 +1082,16 @@ static uint rta_cache_size = 32;
|
|||||||
static uint rta_cache_limit;
|
static uint rta_cache_limit;
|
||||||
static uint rta_cache_mask;
|
static uint rta_cache_mask;
|
||||||
static rta **rta_hash_table;
|
static rta **rta_hash_table;
|
||||||
|
static pthread_mutex_t rta_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
struct rta_gc_chain {
|
||||||
|
node n;
|
||||||
|
u64 round;
|
||||||
|
rta *chain;
|
||||||
|
};
|
||||||
|
|
||||||
|
static _Thread_local struct rta_gc_chain *rta_gc_current_chain = NULL;
|
||||||
|
static list rta_gc_chain_list;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rta_alloc_hash(void)
|
rta_alloc_hash(void)
|
||||||
@ -1136,6 +1148,7 @@ rta_copy(rta *o)
|
|||||||
rta *r = sl_alloc(rta_slab(o));
|
rta *r = sl_alloc(rta_slab(o));
|
||||||
|
|
||||||
memcpy(r, o, rta_size(o));
|
memcpy(r, o, rta_size(o));
|
||||||
|
r->obsolete = 0;
|
||||||
r->uc = 1;
|
r->uc = 1;
|
||||||
r->nh.next = nexthop_copy(o->nh.next);
|
r->nh.next = nexthop_copy(o->nh.next);
|
||||||
r->eattrs = ea_list_copy(o->eattrs);
|
r->eattrs = ea_list_copy(o->eattrs);
|
||||||
@ -1192,15 +1205,30 @@ rta_lookup(rta *o)
|
|||||||
rta *r;
|
rta *r;
|
||||||
uint h;
|
uint h;
|
||||||
|
|
||||||
|
if (o->cached && o->obsolete)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&rta_hash_mutex);
|
||||||
|
ASSERT(o->uc == 0);
|
||||||
|
h = o->hash_key;
|
||||||
|
goto copy;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(!o->cached);
|
ASSERT(!o->cached);
|
||||||
if (o->eattrs)
|
if (o->eattrs)
|
||||||
ea_normalize(o->eattrs);
|
ea_normalize(o->eattrs);
|
||||||
|
|
||||||
h = rta_hash(o);
|
h = rta_hash(o);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&rta_hash_mutex);
|
||||||
|
|
||||||
for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next)
|
for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next)
|
||||||
if (r->hash_key == h && rta_same(r, o))
|
if (r->hash_key == h && rta_same(r, o))
|
||||||
return rta_clone(r);
|
{
|
||||||
|
r = rta_clone(r);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy:
|
||||||
r = rta_copy(o);
|
r = rta_copy(o);
|
||||||
r->hash_key = h;
|
r->hash_key = h;
|
||||||
r->cached = 1;
|
r->cached = 1;
|
||||||
@ -1210,17 +1238,36 @@ rta_lookup(rta *o)
|
|||||||
if (++rta_cache_count > rta_cache_limit)
|
if (++rta_cache_count > rta_cache_limit)
|
||||||
rta_rehash();
|
rta_rehash();
|
||||||
|
|
||||||
|
done:
|
||||||
|
pthread_mutex_unlock(&rta_hash_mutex);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rta__free(rta *a)
|
rta_unlink(rta *a)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(&rta_hash_mutex);
|
||||||
ASSERT(rta_cache_count && a->cached);
|
ASSERT(rta_cache_count && a->cached);
|
||||||
|
ASSERT(rta_gc_current_chain);
|
||||||
|
|
||||||
|
a->obsolete = 1;
|
||||||
rta_cache_count--;
|
rta_cache_count--;
|
||||||
|
|
||||||
*a->pprev = a->next;
|
*a->pprev = a->next;
|
||||||
if (a->next)
|
if (a->next)
|
||||||
a->next->pprev = a->pprev;
|
a->next->pprev = a->pprev;
|
||||||
|
|
||||||
|
a->pprev = NULL;
|
||||||
|
a->next = rta_gc_current_chain->chain;
|
||||||
|
rta_gc_current_chain->chain = a;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&rta_hash_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rta_do_free(rta *a)
|
||||||
|
{
|
||||||
|
ASSERT(a->obsolete);
|
||||||
rt_unlock_hostentry(a->hostentry);
|
rt_unlock_hostentry(a->hostentry);
|
||||||
if (a->nh.next)
|
if (a->nh.next)
|
||||||
nexthop_free(a->nh.next);
|
nexthop_free(a->nh.next);
|
||||||
@ -1229,6 +1276,67 @@ rta__free(rta *a)
|
|||||||
sl_free(rta_slab(a), a);
|
sl_free(rta_slab(a), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rta_gc_enter(u64 round, struct gc_callback_set *gcs UNUSED)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&rta_hash_mutex);
|
||||||
|
ASSERT(rta_gc_current_chain == NULL);
|
||||||
|
rta_gc_current_chain = mb_alloc(rta_pool, sizeof(struct rta_gc_chain));
|
||||||
|
*rta_gc_current_chain = (struct rta_gc_chain) { .round = round };
|
||||||
|
|
||||||
|
add_tail(&rta_gc_chain_list, &rta_gc_current_chain->n);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&rta_hash_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rta_gc_exit(u64 round UNUSED, struct gc_callback_set *gcs UNUSED)
|
||||||
|
{
|
||||||
|
if (!rta_gc_current_chain->chain)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&rta_hash_mutex);
|
||||||
|
rem_node(&rta_gc_current_chain->n);
|
||||||
|
mb_free(rta_gc_current_chain);
|
||||||
|
pthread_mutex_unlock(&rta_hash_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
rta_gc_current_chain = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rta_gc_cleanup(u64 round, struct gc_callback_set *gcs UNUSED)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&rta_hash_mutex);
|
||||||
|
node *n = HEAD(rta_gc_chain_list);
|
||||||
|
if (!NODE_VALID(n))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
struct rta_gc_chain *rgc = SKIP_BACK(struct rta_gc_chain, n, n);
|
||||||
|
if (rgc->round > round)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
ASSERT(rgc->round == round);
|
||||||
|
rem_node(n);
|
||||||
|
|
||||||
|
rta *a, *nxt = rgc->chain;
|
||||||
|
while (a = nxt)
|
||||||
|
{
|
||||||
|
nxt = a->next;
|
||||||
|
rta_do_free(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
mb_free(rgc);
|
||||||
|
|
||||||
|
done:
|
||||||
|
pthread_mutex_unlock(&rta_hash_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct gc_callback_set rta_gc_callback_set = {
|
||||||
|
.enter = rta_gc_enter,
|
||||||
|
.exit = rta_gc_exit,
|
||||||
|
.cleanup = rta_gc_cleanup,
|
||||||
|
};
|
||||||
|
|
||||||
rta *
|
rta *
|
||||||
rta_do_cow(rta *o, linpool *lp)
|
rta_do_cow(rta *o, linpool *lp)
|
||||||
{
|
{
|
||||||
@ -1336,8 +1444,12 @@ rta_init(void)
|
|||||||
nexthop_slab_[2] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*2);
|
nexthop_slab_[2] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*2);
|
||||||
nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK);
|
nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK);
|
||||||
|
|
||||||
|
init_list(&rta_gc_chain_list);
|
||||||
|
gc_register(&rta_gc_callback_set);
|
||||||
|
|
||||||
rta_alloc_hash();
|
rta_alloc_hash();
|
||||||
rte_src_init();
|
rte_src_init();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user