mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 02:01:55 +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); \
|
SAME_TYPE(&_ptr->i, _orig); \
|
||||||
_ptr; })
|
_ptr; })
|
||||||
#define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1))
|
#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 CPU_STRUCT_ALIGN (MAX_(_Alignof(void*), _Alignof(u64)))
|
||||||
#define BIRD_CPU_ALIGN(s) BIRD_ALIGN((s), CPU_STRUCT_ALIGN)
|
#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;
|
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_request {
|
||||||
struct rt_export_hook *hook; /* Table part of the export */
|
struct rt_export_hook *hook; /* Table part of the export */
|
||||||
char *name;
|
char *name;
|
||||||
@ -570,6 +578,8 @@ void rt_flowspec_link(rtable *src, rtable *dst);
|
|||||||
void rt_flowspec_unlink(rtable *src, rtable *dst);
|
void rt_flowspec_unlink(rtable *src, rtable *dst);
|
||||||
rtable *rt_setup(pool *, struct rtable_config *);
|
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);
|
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);
|
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 *);
|
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);
|
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 *
|
static rte *
|
||||||
export_filter(struct channel *c, rte *rt, int silent)
|
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 */
|
struct rt_export_feed *
|
||||||
int
|
rt_net_feed(rtable *t, net_addr *a)
|
||||||
rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter)
|
{
|
||||||
|
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 = {};
|
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);
|
const struct netindex *i = net_find_index(t->netindex, a);
|
||||||
net *n = i ? net_find(tr, i) : NULL;
|
net *n = i ? net_find(tr, i) : NULL;
|
||||||
|
if (!n)
|
||||||
|
return rt;
|
||||||
|
|
||||||
struct rte_storage *e = NET_READ_BEST_ROUTE(tr, n);
|
struct rte_storage *e = NET_READ_BEST_ROUTE(tr, n);
|
||||||
|
|
||||||
if (!e || !rte_is_valid(&e->rte))
|
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;
|
int v = c->proto->preexport ? c->proto->preexport(c, &rt) : 0;
|
||||||
if (v == RIC_PROCESS)
|
if (v == RIC_PROCESS)
|
||||||
v = (f_run(filter, &rt, FF_SILENT) <= F_ACCEPT);
|
v = (f_run(filter, &rt, FF_SILENT) <= F_ACCEPT);
|
||||||
|
Loading…
Reference in New Issue
Block a user