mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-09 20:58:44 +00:00
Merge commit '93509af4' into HEAD
This commit is contained in:
commit
198fb23a3a
26
nest/proto.c
26
nest/proto.c
@ -343,6 +343,7 @@ struct roa_subscription {
|
|||||||
struct settle settle;
|
struct settle settle;
|
||||||
struct channel *c;
|
struct channel *c;
|
||||||
struct rt_export_request req;
|
struct rt_export_request req;
|
||||||
|
struct f_trie* trie;
|
||||||
struct channel_feeding_request cfr[2];
|
struct channel_feeding_request cfr[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -364,6 +365,8 @@ channel_roa_out_changed(struct settle *se)
|
|||||||
|
|
||||||
CD(c, "Feeding triggered by RPKI change");
|
CD(c, "Feeding triggered by RPKI change");
|
||||||
|
|
||||||
|
/* TODO feed by trie */
|
||||||
|
|
||||||
/* Refeed already pending */
|
/* Refeed already pending */
|
||||||
if ((s->cfr[0].state == CFRS_PENDING) || (s->cfr[1].state == CFRS_PENDING))
|
if ((s->cfr[0].state == CFRS_PENDING) || (s->cfr[1].state == CFRS_PENDING))
|
||||||
return;
|
return;
|
||||||
@ -384,11 +387,22 @@ channel_roa_out_changed(struct settle *se)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
channel_export_one_roa(struct rt_export_request *req, const net_addr *net UNUSED, struct rt_pending_export *first)
|
channel_export_one_roa(struct rt_export_request *req, const net_addr *net, struct rt_pending_export *first)
|
||||||
{
|
{
|
||||||
struct roa_subscription *s = SKIP_BACK(struct roa_subscription, req, req);
|
struct roa_subscription *s = SKIP_BACK(struct roa_subscription, req, req);
|
||||||
|
|
||||||
/* TODO: use the information about what roa has changed */
|
switch (net->type)
|
||||||
|
{
|
||||||
|
case NET_ROA4:
|
||||||
|
trie_add_prefix(s->trie, net, net_pxlen(net), 32);
|
||||||
|
break;
|
||||||
|
case NET_ROA6:
|
||||||
|
trie_add_prefix(s->trie, net, net_pxlen(net), 128);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bug("ROA table sent us a non-roa export");
|
||||||
|
}
|
||||||
|
|
||||||
settle_kick(&s->settle, s->c->proto->loop);
|
settle_kick(&s->settle, s->c->proto->loop);
|
||||||
|
|
||||||
rpe_mark_seen_all(req->hook, first, NULL, NULL);
|
rpe_mark_seen_all(req->hook, first, NULL, NULL);
|
||||||
@ -435,6 +449,7 @@ channel_roa_subscribe(struct channel *c, rtable *tab, int dir)
|
|||||||
*s = (struct roa_subscription) {
|
*s = (struct roa_subscription) {
|
||||||
.settle = SETTLE_INIT(&c->roa_settle, dir ? channel_roa_in_changed : channel_roa_out_changed, NULL),
|
.settle = SETTLE_INIT(&c->roa_settle, dir ? channel_roa_in_changed : channel_roa_out_changed, NULL),
|
||||||
.c = c,
|
.c = c,
|
||||||
|
.trie = f_new_trie(lp_new(c->proto->pool), 0),
|
||||||
.req = {
|
.req = {
|
||||||
.name = mb_sprintf(c->proto->pool, "%s.%s.roa-%s.%s",
|
.name = mb_sprintf(c->proto->pool, "%s.%s.roa-%s.%s",
|
||||||
c->proto->name, c->name, dir ? "in" : "out", tab->name),
|
c->proto->name, c->name, dir ? "in" : "out", tab->name),
|
||||||
@ -465,6 +480,7 @@ channel_roa_unsubscribed(struct rt_export_request *req)
|
|||||||
static void
|
static void
|
||||||
channel_roa_unsubscribe(struct roa_subscription *s)
|
channel_roa_unsubscribe(struct roa_subscription *s)
|
||||||
{
|
{
|
||||||
|
rfree(s->trie->lp);
|
||||||
rt_stop_export(&s->req, channel_roa_unsubscribed);
|
rt_stop_export(&s->req, channel_roa_unsubscribed);
|
||||||
settle_cancel(&s->settle);
|
settle_cancel(&s->settle);
|
||||||
}
|
}
|
||||||
@ -570,8 +586,10 @@ channel_start_export(struct channel *c)
|
|||||||
.list = proto_work_list(c->proto),
|
.list = proto_work_list(c->proto),
|
||||||
.pool = c->proto->pool,
|
.pool = c->proto->pool,
|
||||||
.feed_block_size = c->feed_block_size,
|
.feed_block_size = c->feed_block_size,
|
||||||
|
.prefilter = {
|
||||||
|
.mode = c->out_subprefix ? TE_ADDR_IN : TE_ADDR_NONE,
|
||||||
.addr = c->out_subprefix,
|
.addr = c->out_subprefix,
|
||||||
.addr_mode = c->out_subprefix ? TE_ADDR_IN : TE_ADDR_NONE,
|
},
|
||||||
.trace_routes = c->debug | c->proto->debug,
|
.trace_routes = c->debug | c->proto->debug,
|
||||||
.dump_req = channel_dump_export_req,
|
.dump_req = channel_dump_export_req,
|
||||||
.log_state_change = channel_export_log_state_change,
|
.log_state_change = channel_export_log_state_change,
|
||||||
@ -1149,7 +1167,7 @@ channel_reconfigure(struct channel *c, struct channel_config *cf)
|
|||||||
// c->ra_mode = cf->ra_mode;
|
// c->ra_mode = cf->ra_mode;
|
||||||
c->merge_limit = cf->merge_limit;
|
c->merge_limit = cf->merge_limit;
|
||||||
c->preference = cf->preference;
|
c->preference = cf->preference;
|
||||||
c->out_req.addr = c->out_subprefix = cf->out_subprefix;
|
c->out_req.prefilter.addr = c->out_subprefix = cf->out_subprefix;
|
||||||
c->debug = cf->debug;
|
c->debug = cf->debug;
|
||||||
c->in_req.trace_routes = c->out_req.trace_routes = c->debug | c->proto->debug;
|
c->in_req.trace_routes = c->out_req.trace_routes = c->debug | c->proto->debug;
|
||||||
c->rpki_reload = cf->rpki_reload;
|
c->rpki_reload = cf->rpki_reload;
|
||||||
|
@ -285,14 +285,14 @@ rt_show_cont(struct rt_show_data *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
d->req = (struct rt_export_request) {
|
d->req = (struct rt_export_request) {
|
||||||
.addr = d->addr,
|
.prefilter.addr = d->addr,
|
||||||
.name = "CLI Show Route",
|
.name = "CLI Show Route",
|
||||||
.list = &global_work_list,
|
.list = &global_work_list,
|
||||||
.pool = c->pool,
|
.pool = c->pool,
|
||||||
.export_bulk = rt_show_net_export_bulk,
|
.export_bulk = rt_show_net_export_bulk,
|
||||||
.dump_req = rt_show_dump_req,
|
.dump_req = rt_show_dump_req,
|
||||||
.log_state_change = rt_show_log_state_change,
|
.log_state_change = rt_show_log_state_change,
|
||||||
.addr_mode = d->addr_mode,
|
.prefilter.mode = d->addr_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
d->table_counter++;
|
d->table_counter++;
|
||||||
|
@ -1261,28 +1261,13 @@ rte_export(struct rt_table_export_hook *th, struct rt_pending_export *rpe)
|
|||||||
|
|
||||||
const net_addr *n = rpe->new_best ? rpe->new_best->rte.net : rpe->old_best->rte.net;
|
const net_addr *n = rpe->new_best ? rpe->new_best->rte.net : rpe->old_best->rte.net;
|
||||||
|
|
||||||
switch (hook->req->addr_mode)
|
/* Check export eligibility of this net */
|
||||||
{
|
if (!rt_prefilter_net(&hook->req->prefilter, n))
|
||||||
case TE_ADDR_NONE:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TE_ADDR_IN:
|
|
||||||
if (!net_in_netX(n, hook->req->addr))
|
|
||||||
goto ignore;
|
goto ignore;
|
||||||
break;
|
|
||||||
|
|
||||||
case TE_ADDR_EQUAL:
|
if (hook->req->prefilter.mode == TE_ADDR_FOR)
|
||||||
if (!net_equal(n, hook->req->addr))
|
|
||||||
goto ignore;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TE_ADDR_FOR:
|
|
||||||
bug("Continuos export of best prefix match not implemented yet.");
|
bug("Continuos export of best prefix match not implemented yet.");
|
||||||
|
|
||||||
default:
|
|
||||||
bug("Strange table export address mode: %d", hook->req->addr_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rpe->new)
|
if (rpe->new)
|
||||||
hook->stats.updates_received++;
|
hook->stats.updates_received++;
|
||||||
else
|
else
|
||||||
@ -2229,20 +2214,21 @@ rt_table_export_start_feed(struct rtable_private *tab, struct rt_table_export_ho
|
|||||||
struct rt_export_request *req = hook->h.req;
|
struct rt_export_request *req = hook->h.req;
|
||||||
|
|
||||||
/* stats zeroed by mb_allocz */
|
/* stats zeroed by mb_allocz */
|
||||||
switch (req->addr_mode)
|
switch (req->prefilter.mode)
|
||||||
{
|
{
|
||||||
case TE_ADDR_IN:
|
case TE_ADDR_IN:
|
||||||
if (tab->trie && net_val_match(tab->addr_type, NB_IP))
|
if (tab->trie && net_val_match(tab->addr_type, NB_IP))
|
||||||
{
|
{
|
||||||
hook->walk_state = mb_allocz(hook->h.pool, sizeof (struct f_trie_walk_state));
|
hook->walk_state = mb_allocz(hook->h.pool, sizeof (struct f_trie_walk_state));
|
||||||
hook->walk_lock = rt_lock_trie(tab);
|
hook->walk_lock = rt_lock_trie(tab);
|
||||||
trie_walk_init(hook->walk_state, tab->trie, req->addr);
|
trie_walk_init(hook->walk_state, tab->trie, req->prefilter.addr);
|
||||||
hook->h.event.hook = rt_feed_by_trie;
|
hook->h.event.hook = rt_feed_by_trie;
|
||||||
hook->walk_last.type = 0;
|
hook->walk_last.type = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case TE_ADDR_NONE:
|
case TE_ADDR_NONE:
|
||||||
|
case TE_ADDR_TRIE:
|
||||||
FIB_ITERATE_INIT(&hook->feed_fit, &tab->fib);
|
FIB_ITERATE_INIT(&hook->feed_fit, &tab->fib);
|
||||||
hook->h.event.hook = rt_feed_by_fib;
|
hook->h.event.hook = rt_feed_by_fib;
|
||||||
break;
|
break;
|
||||||
@ -2328,7 +2314,7 @@ rt_table_export_stop_locked(struct rt_export_hook *hh)
|
|||||||
rt_trace(tab, D_EVENTS, "Stopping export hook %s must wait for uncorking", hook->h.req->name);
|
rt_trace(tab, D_EVENTS, "Stopping export hook %s must wait for uncorking", hook->h.req->name);
|
||||||
return 0;
|
return 0;
|
||||||
case TES_FEEDING:
|
case TES_FEEDING:
|
||||||
switch (hh->req->addr_mode)
|
switch (hh->req->prefilter.mode)
|
||||||
{
|
{
|
||||||
case TE_ADDR_IN:
|
case TE_ADDR_IN:
|
||||||
if (hook->walk_lock)
|
if (hook->walk_lock)
|
||||||
@ -2341,8 +2327,12 @@ rt_table_export_stop_locked(struct rt_export_hook *hh)
|
|||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case TE_ADDR_NONE:
|
case TE_ADDR_NONE:
|
||||||
|
case TE_ADDR_TRIE:
|
||||||
fit_get(&tab->fib, &hook->feed_fit);
|
fit_get(&tab->fib, &hook->feed_fit);
|
||||||
break;
|
break;
|
||||||
|
case TE_ADDR_EQUAL:
|
||||||
|
case TE_ADDR_FOR:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -4422,7 +4412,7 @@ rt_feed_by_fib(void *data)
|
|||||||
|
|
||||||
FIB_ITERATE_START(&tab->fib, fit, net, n)
|
FIB_ITERATE_START(&tab->fib, fit, net, n)
|
||||||
{
|
{
|
||||||
if ((c->h.req->addr_mode == TE_ADDR_NONE) || net_in_netX(n->n.addr, c->h.req->addr))
|
if (rt_prefilter_net(&c->h.req->prefilter, n->n.addr))
|
||||||
{
|
{
|
||||||
if (!rt_prepare_feed(c, n, &block))
|
if (!rt_prepare_feed(c, n, &block))
|
||||||
{
|
{
|
||||||
@ -4497,9 +4487,9 @@ rt_feed_equal(void *data)
|
|||||||
RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab)
|
RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab)
|
||||||
{
|
{
|
||||||
ASSERT_DIE(atomic_load_explicit(&c->h.export_state, memory_order_relaxed) == TES_FEEDING);
|
ASSERT_DIE(atomic_load_explicit(&c->h.export_state, memory_order_relaxed) == TES_FEEDING);
|
||||||
ASSERT_DIE(c->h.req->addr_mode == TE_ADDR_EQUAL);
|
ASSERT_DIE(c->h.req->prefilter.mode == TE_ADDR_EQUAL);
|
||||||
|
|
||||||
if (n = net_find(tab, c->h.req->addr))
|
if (n = net_find(tab, c->h.req->prefilter.addr))
|
||||||
ASSERT_DIE(rt_prepare_feed(c, n, &block));
|
ASSERT_DIE(rt_prepare_feed(c, n, &block));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4519,9 +4509,9 @@ rt_feed_for(void *data)
|
|||||||
RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab)
|
RT_LOCKED(RT_PUB(SKIP_BACK(struct rtable_private, exporter, c->table)), tab)
|
||||||
{
|
{
|
||||||
ASSERT_DIE(atomic_load_explicit(&c->h.export_state, memory_order_relaxed) == TES_FEEDING);
|
ASSERT_DIE(atomic_load_explicit(&c->h.export_state, memory_order_relaxed) == TES_FEEDING);
|
||||||
ASSERT_DIE(c->h.req->addr_mode == TE_ADDR_FOR);
|
ASSERT_DIE(c->h.req->prefilter.mode == TE_ADDR_FOR);
|
||||||
|
|
||||||
if (n = net_route(tab, c->h.req->addr))
|
if (n = net_route(tab, c->h.req->prefilter.addr))
|
||||||
ASSERT_DIE(rt_prepare_feed(c, n, &block));
|
ASSERT_DIE(rt_prepare_feed(c, n, &block));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
nest/rt.h
42
nest/rt.h
@ -22,6 +22,8 @@
|
|||||||
#include "lib/io-loop.h"
|
#include "lib/io-loop.h"
|
||||||
#include "lib/settle.h"
|
#include "lib/settle.h"
|
||||||
|
|
||||||
|
#include "filter/data.h"
|
||||||
|
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
struct ea_list;
|
struct ea_list;
|
||||||
@ -298,13 +300,27 @@ struct rt_pending_export {
|
|||||||
u64 seq; /* Sequential ID (table-local) of the pending export */
|
u64 seq; /* Sequential ID (table-local) of the pending export */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rt_prefilter {
|
||||||
|
union {
|
||||||
|
const struct f_trie *trie;
|
||||||
|
const net_addr *addr; /* Network prefilter address */
|
||||||
|
};
|
||||||
|
/* Network prefilter mode (TE_ADDR_*) */
|
||||||
|
enum {
|
||||||
|
TE_ADDR_NONE = 0, /* No address matching */
|
||||||
|
TE_ADDR_EQUAL, /* Exact query - show route <addr> */
|
||||||
|
TE_ADDR_FOR, /* Longest prefix match - show route for <addr> */
|
||||||
|
TE_ADDR_IN, /* Interval query - show route in <addr> */
|
||||||
|
TE_ADDR_TRIE, /* Query defined by trie */
|
||||||
|
} mode;
|
||||||
|
} PACKED;
|
||||||
|
|
||||||
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; /* Network prefilter address */
|
||||||
const net_addr *addr; /* Network prefilter address */
|
|
||||||
u8 trace_routes;
|
u8 trace_routes;
|
||||||
u8 addr_mode; /* Network prefilter mode (TE_ADDR_*) */
|
|
||||||
uint feed_block_size; /* How many routes to feed at once */
|
uint feed_block_size; /* How many routes to feed at once */
|
||||||
|
struct rt_prefilter prefilter;
|
||||||
|
|
||||||
event_list *list; /* Where to schedule export events */
|
event_list *list; /* Where to schedule export events */
|
||||||
pool *pool; /* Pool to use for allocations */
|
pool *pool; /* Pool to use for allocations */
|
||||||
@ -327,6 +343,20 @@ struct rt_export_request {
|
|||||||
void (*log_state_change)(struct rt_export_request *req, u8);
|
void (*log_state_change)(struct rt_export_request *req, u8);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int rt_prefilter_net(const struct rt_prefilter *p, const net_addr *n)
|
||||||
|
{
|
||||||
|
switch (p->mode)
|
||||||
|
{
|
||||||
|
case TE_ADDR_NONE: return 1;
|
||||||
|
case TE_ADDR_IN: return net_in_netX(n, p->addr);
|
||||||
|
case TE_ADDR_EQUAL: return net_equal(n, p->addr);
|
||||||
|
case TE_ADDR_FOR: return net_in_netX(p->addr, n);
|
||||||
|
case TE_ADDR_TRIE: return trie_match_net(p->trie, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
bug("Crazy prefilter application attempt failed wildly.");
|
||||||
|
}
|
||||||
|
|
||||||
struct rt_export_hook {
|
struct rt_export_hook {
|
||||||
node n;
|
node n;
|
||||||
struct rt_exporter *table; /* The connected table */
|
struct rt_exporter *table; /* The connected table */
|
||||||
@ -396,12 +426,6 @@ struct rt_table_export_hook {
|
|||||||
#define TES_STOP 4
|
#define TES_STOP 4
|
||||||
#define TES_MAX 5
|
#define TES_MAX 5
|
||||||
|
|
||||||
/* Value of addr_mode */
|
|
||||||
#define TE_ADDR_NONE 0 /* No address matching */
|
|
||||||
#define TE_ADDR_EQUAL 1 /* Exact query - show route <addr> */
|
|
||||||
#define TE_ADDR_FOR 2 /* Longest prefix match - show route for <addr> */
|
|
||||||
#define TE_ADDR_IN 3 /* Interval query - show route in <addr> */
|
|
||||||
|
|
||||||
|
|
||||||
#define TFT_FIB 1
|
#define TFT_FIB 1
|
||||||
#define TFT_TRIE 2
|
#define TFT_TRIE 2
|
||||||
|
@ -1896,16 +1896,17 @@ bgp_out_table_feed(void *data)
|
|||||||
|
|
||||||
int max = 512;
|
int max = 512;
|
||||||
|
|
||||||
const net_addr *neq = (hook->h.req->addr_mode == TE_ADDR_EQUAL) ? hook->h.req->addr : NULL;
|
const net_addr *neq = (hook->h.req->prefilter.mode == TE_ADDR_EQUAL) ? hook->h.req->prefilter.addr : NULL;
|
||||||
const net_addr *cand = NULL;
|
const net_addr *cand = NULL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
HASH_WALK_ITER(c->prefix_hash, PXH, n, hook->hash_iter)
|
HASH_WALK_ITER(c->prefix_hash, PXH, n, hook->hash_iter)
|
||||||
{
|
{
|
||||||
switch (hook->h.req->addr_mode)
|
switch (hook->h.req->prefilter.mode)
|
||||||
{
|
{
|
||||||
|
case TE_ADDR_TRIE:
|
||||||
case TE_ADDR_IN:
|
case TE_ADDR_IN:
|
||||||
if (!net_in_netX(n->net, hook->h.req->addr))
|
if (!rt_prefilter_net(&hook->h.req->prefilter, n->net))
|
||||||
continue;
|
continue;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case TE_ADDR_NONE:
|
case TE_ADDR_NONE:
|
||||||
@ -1917,7 +1918,7 @@ bgp_out_table_feed(void *data)
|
|||||||
case TE_ADDR_FOR:
|
case TE_ADDR_FOR:
|
||||||
if (!neq)
|
if (!neq)
|
||||||
{
|
{
|
||||||
if (net_in_netX(hook->h.req->addr, n->net) && (!cand || (n->net->length > cand->length)))
|
if (net_in_netX(hook->h.req->prefilter.addr, n->net) && (!cand || (n->net->length > cand->length)))
|
||||||
cand = n->net;
|
cand = n->net;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user