mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Lockless feed of a single net
This commit is contained in:
parent
93c3923462
commit
de3bd705f8
@ -32,6 +32,10 @@
|
||||
SAME_TYPE(&_ptr->i, _orig); \
|
||||
_ptr; })
|
||||
#define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1))
|
||||
#define BIRD_SET_ALIGNED_POINTER(ptr, val) do { \
|
||||
size_t _alignment = _Alignof(typeof(*ptr)); \
|
||||
ptr = (typeof(ptr)) BIRD_ALIGN((uintptr_t)(val), _alignment); \
|
||||
} while (0)
|
||||
#define CPU_STRUCT_ALIGN (MAX_(_Alignof(void*), _Alignof(u64)))
|
||||
#define BIRD_CPU_ALIGN(s) BIRD_ALIGN((s), CPU_STRUCT_ALIGN)
|
||||
|
||||
|
10
nest/route.h
10
nest/route.h
@ -298,6 +298,14 @@ struct rt_pending_export {
|
||||
const rte *new, *new_best, *old, *old_best;
|
||||
};
|
||||
|
||||
struct rt_export_feed {
|
||||
uint count_routes, count_exports;
|
||||
struct netindex *ni;
|
||||
rte *block;
|
||||
u64 *exports;
|
||||
char data[0];
|
||||
};
|
||||
|
||||
struct rt_export_request {
|
||||
struct rt_export_hook *hook; /* Table part of the export */
|
||||
char *name;
|
||||
@ -570,6 +578,8 @@ void rt_flowspec_link(rtable *src, rtable *dst);
|
||||
void rt_flowspec_unlink(rtable *src, rtable *dst);
|
||||
rtable *rt_setup(pool *, struct rtable_config *);
|
||||
|
||||
struct rt_export_feed *rt_net_feed(rtable *t, net_addr *a);
|
||||
rte rt_net_best(rtable *t, net_addr *a);
|
||||
int rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter);
|
||||
rte *rt_export_merged(struct channel *c, const net_addr *n, const rte ** feed, uint count, linpool *pool, int silent);
|
||||
void rt_refresh_begin(struct rt_import_request *);
|
||||
|
120
nest/rt-table.c
120
nest/rt-table.c
@ -696,6 +696,23 @@ rte_feed_obtain(struct rtable_reading *tr, net *n, const rte **feed, uint count)
|
||||
RT_READ_RETRY(tr);
|
||||
}
|
||||
|
||||
static void
|
||||
rte_feed_obtain_copy(struct rtable_reading *tr, net *n, rte *feed, uint count)
|
||||
{
|
||||
uint i = 0;
|
||||
NET_READ_WALK_ROUTES(tr, n, ep, e)
|
||||
{
|
||||
if (i >= count)
|
||||
RT_READ_RETRY(tr);
|
||||
|
||||
feed[i++] = e->rte;
|
||||
ea_free_later(ea_ref(e->rte.attrs));
|
||||
}
|
||||
|
||||
if (i != count)
|
||||
RT_READ_RETRY(tr);
|
||||
}
|
||||
|
||||
static rte *
|
||||
export_filter(struct channel *c, rte *rt, int silent)
|
||||
{
|
||||
@ -2023,9 +2040,89 @@ rte_import(struct rt_import_request *req, const net_addr *n, rte *new, struct rt
|
||||
}
|
||||
}
|
||||
|
||||
/* Check rtable for best route to given net whether it would be exported do p */
|
||||
int
|
||||
rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter)
|
||||
struct rt_export_feed *
|
||||
rt_net_feed(rtable *t, net_addr *a)
|
||||
{
|
||||
RT_READ(t, tr);
|
||||
|
||||
const struct netindex *i = net_find_index(t->netindex, a);
|
||||
net *n = i ? net_find(tr, i) : NULL;
|
||||
if (!n)
|
||||
return 0;
|
||||
|
||||
/* Get the feed itself. It may change under our hands tho. */
|
||||
struct rt_pending_export *first = atomic_load_explicit(&n->first, memory_order_acquire);
|
||||
struct rt_pending_export *last = atomic_load_explicit(&n->last, memory_order_acquire);
|
||||
|
||||
/* Count the elements */
|
||||
uint rcnt = rte_feed_count(tr, n);
|
||||
uint ecnt = 0;
|
||||
uint ocnt = 0;
|
||||
for (struct rt_pending_export *rpe = first; rpe;
|
||||
rpe = atomic_load_explicit(&rpe->next, memory_order_acquire))
|
||||
{
|
||||
ecnt++;
|
||||
if (rpe->old)
|
||||
ocnt++;
|
||||
}
|
||||
|
||||
struct rt_export_feed *feed = NULL;
|
||||
|
||||
if (rcnt || ocnt || ecnt)
|
||||
{
|
||||
uint size = sizeof *feed
|
||||
+ (rcnt+ocnt) * sizeof *feed->block + _Alignof(typeof(*feed->block))
|
||||
+ ecnt * sizeof *feed->exports + _Alignof(typeof(*feed->exports));
|
||||
|
||||
feed = tmp_alloc(size);
|
||||
|
||||
feed->ni = i;
|
||||
feed->count_routes = rcnt+ocnt;
|
||||
feed->count_exports = ecnt;
|
||||
BIRD_SET_ALIGNED_POINTER(feed->block, feed->data);
|
||||
BIRD_SET_ALIGNED_POINTER(feed->exports, &feed->block[rcnt+ocnt]);
|
||||
|
||||
/* Consistency check */
|
||||
ASSERT_DIE(((void *) &feed->exports[ecnt]) <= ((void *) feed) + size);
|
||||
|
||||
if (rcnt)
|
||||
rte_feed_obtain_copy(tr, n, feed->block, rcnt);
|
||||
|
||||
if (ecnt)
|
||||
{
|
||||
uint e = 0;
|
||||
uint rpos = rcnt;
|
||||
for (struct rt_pending_export *rpe = first; rpe;
|
||||
rpe = atomic_load_explicit(&rpe->next, memory_order_acquire))
|
||||
if (e >= ecnt)
|
||||
RT_READ_RETRY(tr);
|
||||
else
|
||||
{
|
||||
feed->exports[e++] = rpe->seq;
|
||||
|
||||
/* Copy also obsolete routes */
|
||||
if (rpe->old)
|
||||
{
|
||||
ASSERT_DIE(rpos < rcnt + ocnt);
|
||||
feed->block[rpos++] = *rpe->old;
|
||||
ea_free_later(ea_ref(rpe->old->attrs));
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_DIE(e == ecnt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that it indeed didn't change and the last export is still the same. */
|
||||
if (last != atomic_load_explicit(&n->last, memory_order_acquire) ||
|
||||
first != atomic_load_explicit(&n->first, memory_order_acquire))
|
||||
RT_READ_RETRY(tr);
|
||||
|
||||
return feed;
|
||||
}
|
||||
|
||||
rte
|
||||
rt_net_best(rtable *t, net_addr *a)
|
||||
{
|
||||
rte rt = {};
|
||||
|
||||
@ -2033,12 +2130,23 @@ rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filte
|
||||
|
||||
const struct netindex *i = net_find_index(t->netindex, a);
|
||||
net *n = i ? net_find(tr, i) : NULL;
|
||||
if (!n)
|
||||
return rt;
|
||||
|
||||
struct rte_storage *e = NET_READ_BEST_ROUTE(tr, n);
|
||||
|
||||
if (!e || !rte_is_valid(&e->rte))
|
||||
return 0;
|
||||
return rt;
|
||||
|
||||
ea_free_later(ea_ref(e->rte.attrs));
|
||||
return RTE_COPY(e);
|
||||
}
|
||||
|
||||
/* Check rtable for best route to given net whether it would be exported do p */
|
||||
int
|
||||
rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter)
|
||||
{
|
||||
rte rt = rt_net_best(t, a);
|
||||
|
||||
rt = RTE_COPY(e);
|
||||
int v = c->proto->preexport ? c->proto->preexport(c, &rt) : 0;
|
||||
if (v == RIC_PROCESS)
|
||||
v = (f_run(filter, &rt, FF_SILENT) <= F_ACCEPT);
|
||||
|
Loading…
Reference in New Issue
Block a user