mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-09 12:48:43 +00:00
Route export: More elegant export dispatcher.
Also: * Feeding request by net. * Passing only net_addr in export structure. * Cleanup of krt_replace_rte() call.
This commit is contained in:
parent
7930c03a23
commit
3357e0a199
50
nest/proto.c
50
nest/proto.c
@ -186,6 +186,7 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
|
||||
c->reloadable = 1;
|
||||
|
||||
init_list(&c->roa_subscriptions);
|
||||
init_list(&c->net_feed);
|
||||
|
||||
CALL(c->channel->init, c, cf);
|
||||
|
||||
@ -304,9 +305,30 @@ channel_feed_loop(void *ptr)
|
||||
|
||||
/* Restart feeding */
|
||||
if (c->refeed_pending)
|
||||
channel_request_feeding(c);
|
||||
channel_request_feeding(c, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
channel_feed_net(void *data)
|
||||
{
|
||||
struct channel_net_feed *nf = data;
|
||||
|
||||
rt_feed_channel_net(nf->c, nf->addr);
|
||||
rem_node(&nf->n);
|
||||
mb_free(nf);
|
||||
}
|
||||
|
||||
static void
|
||||
channel_schedule_feed_net(struct channel *c, net_addr *n)
|
||||
{
|
||||
struct channel_net_feed *nf = mb_alloc(c->proto->pool, sizeof(struct channel_net_feed) + n->length);
|
||||
nf->n = (node) {};
|
||||
nf->e = (event) { .hook = channel_feed_net, .data = nf };
|
||||
nf->c = c;
|
||||
net_copy(nf->addr, n);
|
||||
add_tail(&c->net_feed, &nf->n);
|
||||
ev_schedule(&nf->e);
|
||||
}
|
||||
|
||||
static void
|
||||
channel_roa_in_changed(struct rt_subscription *s)
|
||||
@ -331,7 +353,7 @@ channel_roa_out_changed(struct rt_subscription *s)
|
||||
CD(c, "Feeding triggered by RPKI change%s", active ? " - already active" : "");
|
||||
|
||||
if (!active)
|
||||
channel_request_feeding(c);
|
||||
channel_request_feeding(c, NULL);
|
||||
else
|
||||
c->refeed_pending = 1;
|
||||
}
|
||||
@ -460,6 +482,16 @@ channel_stop_export(struct channel *c)
|
||||
if (c->export_state == ES_FEEDING)
|
||||
rt_feed_channel_abort(c);
|
||||
|
||||
/* Abort also all scheduled net feeds */
|
||||
struct channel_net_feed *n;
|
||||
node *nxt;
|
||||
WALK_LIST_DELSAFE(n, nxt, c->net_feed)
|
||||
{
|
||||
ev_postpone(&n->e);
|
||||
rem_node(&n->n);
|
||||
mb_free(n);
|
||||
}
|
||||
|
||||
c->export_state = ES_DOWN;
|
||||
c->stats.exp_routes = 0;
|
||||
bmap_reset(&c->export_map, 1024);
|
||||
@ -702,7 +734,7 @@ channel_set_state(struct channel *c, uint state)
|
||||
* even when feeding is already running, in that case it is restarted.
|
||||
*/
|
||||
void
|
||||
channel_request_feeding(struct channel *c)
|
||||
channel_request_feeding(struct channel *c, net_addr *n)
|
||||
{
|
||||
ASSERT(c->channel_state == CS_UP);
|
||||
|
||||
@ -719,9 +751,17 @@ channel_request_feeding(struct channel *c)
|
||||
if (!c->feed_active)
|
||||
return;
|
||||
|
||||
/* Unless only single net is requested */
|
||||
if (n)
|
||||
return channel_schedule_feed_net(c, n);
|
||||
|
||||
rt_feed_channel_abort(c);
|
||||
}
|
||||
|
||||
/* Single net refeed isn't counted */
|
||||
if (n)
|
||||
return channel_schedule_feed_net(c, n);
|
||||
|
||||
/* Track number of exported routes during refeed */
|
||||
c->refeed_count = 0;
|
||||
|
||||
@ -902,7 +942,7 @@ channel_reconfigure(struct channel *c, struct channel_config *cf)
|
||||
channel_request_reload(c);
|
||||
|
||||
if (export_changed)
|
||||
channel_request_feeding(c);
|
||||
channel_request_feeding(c, NULL);
|
||||
|
||||
done:
|
||||
CD(c, "Reconfigured");
|
||||
@ -2210,7 +2250,7 @@ proto_cmd_reload(struct proto *p, uintptr_t dir, int cnt UNUSED)
|
||||
if (dir != CMD_RELOAD_IN)
|
||||
WALK_LIST(c, p->channels)
|
||||
if (c->channel_state == CS_UP)
|
||||
channel_request_feeding(c);
|
||||
channel_request_feeding(c, NULL);
|
||||
|
||||
cli_msg(-15, "%s: reloading", p->name);
|
||||
}
|
||||
|
@ -542,16 +542,24 @@ struct channel {
|
||||
struct fib_iterator reload_fit; /* FIB iterator in in_table used during reloading */
|
||||
struct rte *reload_next_rte; /* Route iterator in in_table used during reloading */
|
||||
u8 reload_active; /* Iterator reload_fit is linked */
|
||||
|
||||
u8 reload_pending; /* Reloading and another reload is scheduled */
|
||||
u8 refeed_pending; /* Refeeding and another refeed is scheduled */
|
||||
u8 rpki_reload; /* RPKI changes trigger channel reload */
|
||||
|
||||
list net_feed; /* Active net feeders (struct channel_net_feed) */
|
||||
|
||||
struct rtable *out_table; /* Internal table for exported routes */
|
||||
|
||||
list roa_subscriptions; /* List of active ROA table subscriptions based on filters roa_check() */
|
||||
};
|
||||
|
||||
struct channel_net_feed {
|
||||
node n;
|
||||
struct event e;
|
||||
struct channel *c;
|
||||
net_addr addr[0];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Channel states
|
||||
@ -625,7 +633,7 @@ static inline void channel_init(struct channel *c) { channel_set_state(c, CS_STA
|
||||
static inline void channel_open(struct channel *c) { channel_set_state(c, CS_UP); }
|
||||
static inline void channel_close(struct channel *c) { channel_set_state(c, CS_FLUSHING); }
|
||||
|
||||
void channel_request_feeding(struct channel *c);
|
||||
void channel_request_feeding(struct channel *c, net_addr *n);
|
||||
void *channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto);
|
||||
void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto);
|
||||
int channel_reconfigure(struct channel *c, struct channel_config *cf);
|
||||
|
@ -240,12 +240,13 @@ typedef struct rte {
|
||||
|
||||
/* Route export structure. Protocols get this structure as an information about
|
||||
* new routes on the channel. */
|
||||
|
||||
struct rte_export {
|
||||
net *net; /* Network information */
|
||||
struct rte_src *new_src; /* New route src (NULL for withdraw) */
|
||||
net_addr *net; /* Network information */
|
||||
rte *new; /* New route (NULL for withdraw) */
|
||||
struct rte_src *new_src; /* New route src (kept if route is rejected by preexport or filter) */
|
||||
rte *old; /* Old route (only if export table is on) */
|
||||
struct rte_src *old_src; /* Old route src */
|
||||
rte *old; /* Old route */
|
||||
};
|
||||
|
||||
#define REF_COW 1 /* Copy this rte on write */
|
||||
@ -337,7 +338,6 @@ static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) f
|
||||
void *net_route(rtable *tab, const net_addr *n);
|
||||
int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
|
||||
rte *rte_find(net *net, struct rte_src *src);
|
||||
int rt_examine(struct channel *c, net_addr *a);
|
||||
rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent);
|
||||
void rt_refresh_begin(rtable *t, struct channel *c);
|
||||
void rt_refresh_end(rtable *t, struct channel *c);
|
||||
@ -352,6 +352,7 @@ rte *rte_cow_rta(rte *r, linpool *lp);
|
||||
void rt_dump(rtable *);
|
||||
void rt_dump_all(void);
|
||||
int rt_feed_channel(struct channel *c);
|
||||
void rt_feed_channel_net(struct channel *c, net_addr *n);
|
||||
void rt_feed_channel_abort(struct channel *c);
|
||||
int rt_reload_channel(struct channel *c);
|
||||
void rt_reload_channel_abort(struct channel *c);
|
||||
|
332
nest/rt-table.c
332
nest/rt-table.c
@ -358,11 +358,11 @@ rte_free_quick(rte *e)
|
||||
}
|
||||
|
||||
struct rte_export_internal {
|
||||
struct rte_export pub;
|
||||
rte *new_best;
|
||||
rte *old_best;
|
||||
net *net;
|
||||
rte *new, *old, *new_best, *old_best;
|
||||
rte *rt_free;
|
||||
uint refeed:1;
|
||||
struct rte_export pub;
|
||||
_Bool refeed;
|
||||
};
|
||||
|
||||
static int /* Actually better or at least as good as */
|
||||
@ -442,6 +442,7 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
|
||||
const struct filter *filter = c->out_filter;
|
||||
struct proto_stats *stats = &c->stats;
|
||||
rte *rt;
|
||||
int v;
|
||||
|
||||
rt = rt0;
|
||||
*rt_free = NULL;
|
||||
@ -450,28 +451,28 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
|
||||
if (silent && bmap_test(&c->export_reject_map, rt0->id))
|
||||
return NULL;
|
||||
|
||||
int pv = p->preexport ? p->preexport(p, &rt, pool) : 0;
|
||||
if (pv < 0)
|
||||
v = p->preexport ? p->preexport(p, &rt, pool) : 0;
|
||||
if (v < 0)
|
||||
{
|
||||
if (silent)
|
||||
goto reject;
|
||||
|
||||
stats->exp_updates_rejected++;
|
||||
if (pv == RIC_REJECT)
|
||||
if (v == RIC_REJECT)
|
||||
rte_trace_out(D_FILTERS, c, rt, "rejected by protocol");
|
||||
goto reject;
|
||||
}
|
||||
if (pv > 0)
|
||||
if (v > 0)
|
||||
{
|
||||
if (!silent)
|
||||
rte_trace_out(D_FILTERS, c, rt, "forced accept by protocol");
|
||||
goto accept;
|
||||
}
|
||||
|
||||
int fv = filter && ((filter == FILTER_REJECT) ||
|
||||
v = filter && ((filter == FILTER_REJECT) ||
|
||||
(f_run(filter, &rt, pool,
|
||||
(silent ? FF_SILENT : 0)) > F_ACCEPT));
|
||||
if (fv)
|
||||
if (v)
|
||||
{
|
||||
if (silent)
|
||||
goto reject;
|
||||
@ -491,9 +492,8 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si
|
||||
return rt;
|
||||
|
||||
reject:
|
||||
/* We have rejected the route by filter */
|
||||
if (pv == 0)
|
||||
bmap_set(&c->export_reject_map, rt0->id);
|
||||
/* We have rejected the route */
|
||||
bmap_set(&c->export_reject_map, rt0->id);
|
||||
|
||||
/* Discard temporary rte */
|
||||
if (rt != rt0)
|
||||
@ -508,13 +508,12 @@ export_filter(struct channel *c, rte *rt0, rte **rt_free, int silent)
|
||||
}
|
||||
|
||||
static void
|
||||
do_rt_notify(struct channel *c, struct rte_export_internal *e)
|
||||
do_rt_notify(struct channel *c, struct rte_export *ep, _Bool refeed)
|
||||
{
|
||||
struct proto *p = c->proto;
|
||||
struct proto_stats *stats = &c->stats;
|
||||
struct rte_export *ep = &(e->pub);
|
||||
|
||||
if (e->refeed && ep->new)
|
||||
if (refeed && ep->new)
|
||||
c->refeed_count++;
|
||||
|
||||
/* Apply export limit */
|
||||
@ -536,7 +535,7 @@ do_rt_notify(struct channel *c, struct rte_export_internal *e)
|
||||
rte *old_exported = NULL;
|
||||
if (c->out_table)
|
||||
{
|
||||
if (!rte_update_out(c, ep->net->n.addr, ep->old_src, ep->new, &(old_exported), e->refeed))
|
||||
if (!rte_update_out(c, ep->net, ep->old_src, ep->new, &(old_exported), refeed))
|
||||
return;
|
||||
}
|
||||
else if (c->out_filter == FILTER_ACCEPT)
|
||||
@ -580,21 +579,26 @@ do_rt_notify(struct channel *c, struct rte_export_internal *e)
|
||||
USE_RESULT static _Bool
|
||||
rt_notify_basic(struct channel *c, struct rte_export_internal *e)
|
||||
{
|
||||
if (e->pub.new)
|
||||
struct rte_export *ep = &e->pub;
|
||||
|
||||
if (e->new)
|
||||
c->stats.exp_updates_received++;
|
||||
else
|
||||
c->stats.exp_withdraws_received++;
|
||||
|
||||
if (e->pub.new)
|
||||
e->pub.new = export_filter(c, e->pub.new, &e->rt_free, 0);
|
||||
if (e->new)
|
||||
{
|
||||
ep->new = export_filter(c, e->new, &e->rt_free, 0);
|
||||
ep->new_src = e->new->attrs->src;
|
||||
}
|
||||
|
||||
if (e->pub.old && !bmap_test(&c->export_map, e->pub.old->id))
|
||||
e->pub.old = NULL;
|
||||
if (e->old && bmap_test(&c->export_map, e->old->id))
|
||||
{
|
||||
ep->old = e->old;
|
||||
ep->old_src = e->old->attrs->src;
|
||||
}
|
||||
|
||||
if (!e->pub.new && !e->pub.old)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return (ep->new || ep->old);
|
||||
}
|
||||
|
||||
USE_RESULT static _Bool
|
||||
@ -603,6 +607,7 @@ rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
|
||||
// struct proto *p = c->proto;
|
||||
rte *new_best = NULL;
|
||||
rte *old_best = NULL;
|
||||
rte *new_filtered = NULL;
|
||||
int new_first = 0;
|
||||
|
||||
/*
|
||||
@ -621,17 +626,17 @@ rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
|
||||
* old_best is after new_changed -> try new_changed, otherwise old_best
|
||||
*/
|
||||
|
||||
if (e->pub.net->routes)
|
||||
if (e->net->routes)
|
||||
c->stats.exp_updates_received++;
|
||||
else
|
||||
c->stats.exp_withdraws_received++;
|
||||
|
||||
/* Find old_best - either old_changed, or route for net->routes */
|
||||
if (e->pub.old && bmap_test(&c->export_map, e->pub.old->id))
|
||||
old_best = e->pub.old;
|
||||
if (e->old && bmap_test(&c->export_map, e->old->id))
|
||||
old_best = e->old;
|
||||
else
|
||||
{
|
||||
for (rte *r = e->pub.net->routes; rte_is_valid(r); r = r->next)
|
||||
for (rte *r = e->net->routes; rte_is_valid(r); r = r->next)
|
||||
{
|
||||
if (bmap_test(&c->export_map, r->id))
|
||||
{
|
||||
@ -640,24 +645,24 @@ rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
|
||||
}
|
||||
|
||||
/* Note if new_changed found before old_best */
|
||||
if (r == e->pub.new)
|
||||
if (r == e->new)
|
||||
new_first = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find new_best */
|
||||
if ((e->pub.new == e->pub.old) || (old_best == e->pub.old))
|
||||
if ((e->new == e->old) || (old_best == e->old))
|
||||
{
|
||||
/* Feed or old_best changed -> find first accepted by filters */
|
||||
for (rte *r = e->pub.net->routes; rte_is_valid(r); r = r->next)
|
||||
for (rte *r = e->net->routes; rte_is_valid(r); r = r->next)
|
||||
if (new_best = export_filter(c, r, &e->rt_free, 0))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Other cases -> either new_changed, or old_best (and nothing changed) */
|
||||
if (new_first && (e->pub.new = export_filter(c, e->pub.new, &e->rt_free, 0)))
|
||||
new_best = e->pub.new;
|
||||
if (new_first && (new_filtered = export_filter(c, e->new, &e->rt_free, 0)))
|
||||
new_best = new_filtered;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@ -665,10 +670,12 @@ rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
|
||||
if (!new_best && !old_best)
|
||||
return 0;
|
||||
|
||||
e->pub.new = new_best;
|
||||
e->pub.new_src = new_best ? new_best->attrs->src : NULL;
|
||||
e->pub.old = old_best;
|
||||
e->pub.old_src = old_best ? old_best->attrs->src : NULL;
|
||||
e->pub = (struct rte_export) {
|
||||
.new = new_best,
|
||||
.new_src = new_best ? new_best->attrs->src : NULL,
|
||||
.old = old_best,
|
||||
.old_src = old_best ? old_best->attrs->src : NULL,
|
||||
};
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -744,9 +751,9 @@ rt_notify_merged(struct channel *c, struct rte_export_internal *e)
|
||||
|
||||
/* Check whether the change is relevant to the merged route */
|
||||
if ((e->new_best == e->old_best) &&
|
||||
(e->pub.new != e->pub.old) &&
|
||||
!rte_mergable(e->new_best, e->pub.new) &&
|
||||
!rte_mergable(e->old_best, e->pub.old))
|
||||
(e->new != e->old) &&
|
||||
!rte_mergable(e->new_best, e->new) &&
|
||||
!rte_mergable(e->old_best, e->old))
|
||||
return 0;
|
||||
|
||||
if (e->new_best)
|
||||
@ -754,23 +761,70 @@ rt_notify_merged(struct channel *c, struct rte_export_internal *e)
|
||||
else
|
||||
c->stats.exp_withdraws_received++;
|
||||
|
||||
struct rte_export *ep = &e->pub;
|
||||
|
||||
/* Prepare new merged route */
|
||||
if (e->new_best)
|
||||
e->pub.new = rt_export_merged(c, e->pub.net, &(e->rt_free), rte_update_pool, 0);
|
||||
{
|
||||
ep->new = rt_export_merged(c, e->net, &(e->rt_free), rte_update_pool, 0);
|
||||
ep->new_src = e->net->routes->attrs->src;
|
||||
}
|
||||
|
||||
/* Check old merged route */
|
||||
if (e->old_best && !bmap_test(&c->export_map, e->old_best->id))
|
||||
e->pub.old = NULL;
|
||||
if (e->old_best)
|
||||
ep->old = bmap_test(&c->export_map, e->old_best->id) ? e->old_best : NULL;
|
||||
|
||||
if (!e->pub.new && !e->pub.old)
|
||||
if (!ep->new && !ep->old)
|
||||
return 0;
|
||||
|
||||
e->pub.new_src = e->pub.new ? e->pub.new->attrs->src : NULL;
|
||||
e->pub.old_src = e->pub.old ? e->pub.old->attrs->src : NULL;
|
||||
|
||||
ep->old_src = ep->old ? ep->old->attrs->src : NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
rte_export(struct channel *c, struct rte_export_internal *e)
|
||||
{
|
||||
uint ra_mode = c->ra_mode;
|
||||
_Bool accepted = 0;
|
||||
|
||||
switch (ra_mode)
|
||||
{
|
||||
case RA_OPTIMAL:
|
||||
if (e->new_best == e->old_best)
|
||||
break;
|
||||
|
||||
e->new = e->new_best;
|
||||
e->old = e->old_best;
|
||||
/* fall through */
|
||||
case RA_ANY:
|
||||
accepted = rt_notify_basic(c, e);
|
||||
break;
|
||||
|
||||
case RA_ACCEPTED:
|
||||
accepted = rt_notify_accepted(c, e);
|
||||
break;
|
||||
|
||||
case RA_MERGED:
|
||||
accepted = rt_notify_merged(c, e);
|
||||
break;
|
||||
|
||||
default:
|
||||
bug("Strange channel route announcement mode");
|
||||
}
|
||||
|
||||
if (accepted)
|
||||
{
|
||||
e->pub.net = e->net->n.addr;
|
||||
do_rt_notify(c, &e->pub, e->refeed);
|
||||
}
|
||||
|
||||
if (e->rt_free)
|
||||
rte_free(e->rt_free);
|
||||
|
||||
if (e->old && (!e->new || (e->new->id != e->old->id)))
|
||||
bmap_clear(&c->export_reject_map, e->old->id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rte_announce - announce a routing table change
|
||||
@ -861,60 +915,13 @@ rte_announce(rtable *tab, uint type, net *net, rte *new, rte *old,
|
||||
continue;
|
||||
}
|
||||
|
||||
struct rte_export_internal e = {
|
||||
.pub = {
|
||||
.net = net,
|
||||
.new_src = new ? new->attrs->src : NULL,
|
||||
.new = new,
|
||||
.old_src = old ? old->attrs->src : NULL,
|
||||
.old = old,
|
||||
},
|
||||
.new_best = new_best,
|
||||
.old_best = old_best,
|
||||
struct rte_export_internal rei = {
|
||||
.net = net,
|
||||
.new = new, .old = old,
|
||||
.new_best = new_best, .old_best = old_best,
|
||||
};
|
||||
|
||||
switch (c->ra_mode)
|
||||
{
|
||||
case RA_OPTIMAL:
|
||||
if (new_best != old_best)
|
||||
{
|
||||
e.pub.new = new_best;
|
||||
e.pub.new_src = new_best ? new_best->attrs->src : NULL;
|
||||
e.pub.old = old_best;
|
||||
e.pub.old_src = old_best ? old_best->attrs->src : NULL;
|
||||
if (!rt_notify_basic(c, &e))
|
||||
goto next_channel;
|
||||
}
|
||||
break;
|
||||
|
||||
case RA_ANY:
|
||||
if (new != old)
|
||||
if (!rt_notify_basic(c, &e))
|
||||
goto next_channel;
|
||||
break;
|
||||
|
||||
case RA_ACCEPTED:
|
||||
if (!rt_notify_accepted(c, &e))
|
||||
goto next_channel;
|
||||
break;
|
||||
|
||||
case RA_MERGED:
|
||||
if (!rt_notify_merged(c, &e))
|
||||
goto next_channel;
|
||||
break;
|
||||
}
|
||||
|
||||
do_rt_notify(c, &e);
|
||||
|
||||
next_channel:
|
||||
/* Discard temporary rte */
|
||||
if (e.rt_free)
|
||||
rte_free(e.rt_free);
|
||||
|
||||
/* Drop the old stored rejection if applicable.
|
||||
* new->id == old->id happens when updating hostentries. */
|
||||
if (old && (!new || (new->id != old->id)))
|
||||
bmap_clear(&c->export_reject_map, old->id);
|
||||
|
||||
rte_export(c, &rei);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1427,37 +1434,6 @@ rte_modify(rte *old)
|
||||
rte_update_unlock();
|
||||
}
|
||||
|
||||
/* Check channel for best route to given net whether it would be exported */
|
||||
int
|
||||
rt_examine(struct channel *c, net_addr *a)
|
||||
{
|
||||
net *n = net_find(c->table, a);
|
||||
rte *rt = n ? n->routes : NULL;
|
||||
|
||||
if (!rte_is_valid(rt))
|
||||
return 0;
|
||||
|
||||
if (bmap_test(&c->export_reject_map, rt->id))
|
||||
return 0;
|
||||
|
||||
rte_update_lock();
|
||||
|
||||
struct proto *p = c->proto;
|
||||
/* Rest is stripped down export_filter() */
|
||||
int v = p->preexport ? p->preexport(p, &rt, rte_update_pool) : 0;
|
||||
if (v == RIC_PROCESS)
|
||||
v = (f_run(c->out_filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
|
||||
|
||||
/* Discard temporary rte */
|
||||
if (rt != n->routes)
|
||||
rte_free(rt);
|
||||
|
||||
rte_update_unlock();
|
||||
|
||||
return v > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rt_refresh_begin - start a refresh cycle
|
||||
* @t: related routing table
|
||||
@ -2247,6 +2223,43 @@ rt_commit(struct config *new, struct config *old)
|
||||
DBG("\tdone\n");
|
||||
}
|
||||
|
||||
static uint
|
||||
rt_feed_channel_net_internal(struct channel *c, net *nn)
|
||||
{
|
||||
struct rte_export_internal rei = {
|
||||
.net = nn,
|
||||
.new_best = nn->routes,
|
||||
.new = nn->routes,
|
||||
.refeed = 1,
|
||||
};
|
||||
|
||||
rte_update_lock();
|
||||
if (c->ra_mode == RA_ANY)
|
||||
{
|
||||
uint cnt = 0;
|
||||
for (rei.new = nn->routes; rei.new; rei.new = rei.new->next)
|
||||
if (rte_is_valid(rei.new))
|
||||
rte_export(c, &rei), cnt++;
|
||||
return cnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
rte_export(c, &rei);
|
||||
return 1;
|
||||
}
|
||||
rte_update_unlock();
|
||||
}
|
||||
|
||||
void
|
||||
rt_feed_channel_net(struct channel *c, net_addr *n)
|
||||
{
|
||||
net *nn = net_find(c->table, n);
|
||||
if (!nn)
|
||||
return;
|
||||
|
||||
rt_feed_channel_net_internal(c, nn);
|
||||
}
|
||||
|
||||
/**
|
||||
* rt_feed_channel - advertise all routes to a channel
|
||||
* @c: channel to be fed
|
||||
@ -2278,61 +2291,10 @@ rt_feed_channel(struct channel *c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (rte *e = n->routes; e; e = e->next)
|
||||
{
|
||||
if (c->export_state != ES_FEEDING)
|
||||
goto done;
|
||||
|
||||
if (rte_is_valid(e))
|
||||
{
|
||||
max_feed--;
|
||||
|
||||
struct rte_export_internal ee = {
|
||||
.pub = {
|
||||
.net = n,
|
||||
},
|
||||
.new_best = n->routes,
|
||||
.old_best = n->routes,
|
||||
.refeed = c->refeeding,
|
||||
};
|
||||
|
||||
switch (c->ra_mode) {
|
||||
case RA_OPTIMAL:
|
||||
case RA_ANY:
|
||||
ee.pub.new = e;
|
||||
ee.pub.new_src = e->attrs->src;
|
||||
ee.pub.old = e;
|
||||
ee.pub.old_src = e->attrs->src;
|
||||
if (!rt_notify_basic(c, &ee))
|
||||
goto next_rte;
|
||||
break;
|
||||
case RA_ACCEPTED:
|
||||
if (!rt_notify_accepted(c, &ee))
|
||||
goto next_rte;
|
||||
break;
|
||||
case RA_MERGED:
|
||||
if (!rt_notify_merged(c, &ee))
|
||||
goto next_rte;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
do_rt_notify(c, &ee);
|
||||
|
||||
/* Discard temporary rte */
|
||||
next_rte:
|
||||
if (ee.rt_free)
|
||||
rte_free(ee.rt_free);
|
||||
}
|
||||
|
||||
if (c->ra_mode != RA_ANY)
|
||||
break;
|
||||
}
|
||||
max_feed -= rt_feed_channel_net_internal(c, n);
|
||||
}
|
||||
FIB_ITERATE_END;
|
||||
|
||||
done:
|
||||
c->feed_active = 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -2137,11 +2137,11 @@ babel_rt_notify(struct channel *c, struct rte_export *export)
|
||||
if (rt_metric > BABEL_INFINITY)
|
||||
{
|
||||
log(L_WARN "%s: Invalid babel_metric value %u for route %N",
|
||||
p->p.name, rt_metric, export->net->n.addr);
|
||||
p->p.name, rt_metric, export->net);
|
||||
rt_metric = BABEL_INFINITY;
|
||||
}
|
||||
|
||||
e = babel_get_entry(p, export->net->n.addr);
|
||||
e = babel_get_entry(p, export->net);
|
||||
|
||||
/* Activate triggered updates */
|
||||
if ((e->valid != BABEL_ENTRY_VALID) ||
|
||||
@ -2159,7 +2159,7 @@ babel_rt_notify(struct channel *c, struct rte_export *export)
|
||||
else
|
||||
{
|
||||
/* Withdraw */
|
||||
e = babel_find_entry(p, export->net->n.addr);
|
||||
e = babel_find_entry(p, export->net);
|
||||
|
||||
if (!e || e->valid != BABEL_ENTRY_VALID)
|
||||
return;
|
||||
|
@ -1857,7 +1857,7 @@ bgp_rt_notify(struct channel *C, struct rte_export *e)
|
||||
path = e->old_src->global_id;
|
||||
}
|
||||
|
||||
px = bgp_get_prefix(c, e->net->n.addr, c->add_path_tx ? path : 0);
|
||||
px = bgp_get_prefix(c, e->net, c->add_path_tx ? path : 0);
|
||||
add_tail(&buck->prefixes, &px->buck_node);
|
||||
|
||||
bgp_schedule_packet(p->conn, c, PKT_UPDATE);
|
||||
|
@ -2695,7 +2695,7 @@ bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, uint len)
|
||||
{
|
||||
case BGP_RR_REQUEST:
|
||||
BGP_TRACE(D_PACKETS, "Got ROUTE-REFRESH");
|
||||
channel_request_feeding(&c->c);
|
||||
channel_request_feeding(&c->c, NULL);
|
||||
break;
|
||||
|
||||
case BGP_RR_BEGIN:
|
||||
|
@ -1319,7 +1319,7 @@ ospf_rt_notify(struct channel *ch, struct rte_export *e)
|
||||
|
||||
if (!e->new)
|
||||
{
|
||||
nf = fib_find(&p->rtf, e->net->n.addr);
|
||||
nf = fib_find(&p->rtf, e->net);
|
||||
|
||||
if (!nf || !nf->external_rte)
|
||||
return;
|
||||
@ -1346,14 +1346,14 @@ ospf_rt_notify(struct channel *ch, struct rte_export *e)
|
||||
if (m1 > LSINFINITY)
|
||||
{
|
||||
log(L_WARN "%s: Invalid ospf_metric1 value %u for route %N",
|
||||
p->p.name, m1, e->net->n.addr);
|
||||
p->p.name, m1, e->net);
|
||||
m1 = LSINFINITY;
|
||||
}
|
||||
|
||||
if (m2 > LSINFINITY)
|
||||
{
|
||||
log(L_WARN "%s: Invalid ospf_metric2 value %u for route %N",
|
||||
p->p.name, m2, e->net->n.addr);
|
||||
p->p.name, m2, e->net);
|
||||
m2 = LSINFINITY;
|
||||
}
|
||||
|
||||
@ -1377,12 +1377,12 @@ ospf_rt_notify(struct channel *ch, struct rte_export *e)
|
||||
if (ipa_zero(fwd))
|
||||
{
|
||||
log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %N",
|
||||
p->p.name, e->net->n.addr);
|
||||
p->p.name, e->net);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nf = fib_get(&p->rtf, e->net->n.addr);
|
||||
nf = fib_get(&p->rtf, e->net);
|
||||
ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1, p->vpn_pe);
|
||||
nf->external_rte = 1;
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ perf_feed_end(struct channel *c)
|
||||
p->feed_begin = NULL;
|
||||
|
||||
if (p->run < p->repeat)
|
||||
channel_request_feeding(c);
|
||||
channel_request_feeding(c, NULL);
|
||||
else
|
||||
PLOG("feed done");
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ pipe_rt_notify(struct channel *src_ch, struct rte_export *export)
|
||||
if (dst->table->pipe_busy)
|
||||
{
|
||||
log(L_ERR "Pipe loop detected when sending %N to table %s",
|
||||
export->net->n.addr, dst->table->name);
|
||||
export->net, dst->table->name);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -77,13 +77,13 @@ pipe_rt_notify(struct channel *src_ch, struct rte_export *export)
|
||||
};
|
||||
|
||||
src_ch->table->pipe_busy = 1;
|
||||
rte_update(dst, export->net->n.addr, &e0);
|
||||
rte_update(dst, export->net, &e0);
|
||||
src_ch->table->pipe_busy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_ch->table->pipe_busy = 1;
|
||||
rte_withdraw(dst, export->net->n.addr, export->old_src);
|
||||
rte_withdraw(dst, export->net, export->old_src);
|
||||
src_ch->table->pipe_busy = 0;
|
||||
}
|
||||
}
|
||||
@ -105,7 +105,7 @@ pipe_reload_routes(struct channel *C)
|
||||
struct pipe_proto *p = (void *) C->proto;
|
||||
|
||||
/* Route reload on one channel is just refeed on the other */
|
||||
channel_request_feeding((C == p->pri) ? p->sec : p->pri);
|
||||
channel_request_feeding((C == p->pri) ? p->sec : p->pri, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
* The RAdv protocol could receive routes (through radv_preexport() and
|
||||
* radv_rt_notify()), but only the configured trigger route is tracked (in
|
||||
* &active var). When a radv protocol is reconfigured, the connected routing
|
||||
* table is examined (in radv_check_active()) to have proper &active value in
|
||||
* table is examined to have proper &active value in
|
||||
* case of the specified trigger prefix was changed.
|
||||
*
|
||||
* Supported standards:
|
||||
@ -385,9 +385,9 @@ radv_trigger_valid(struct radv_config *cf)
|
||||
}
|
||||
|
||||
static inline int
|
||||
radv_net_match_trigger(struct radv_config *cf, net *n)
|
||||
radv_net_match_trigger(struct radv_config *cf, net_addr *n)
|
||||
{
|
||||
return radv_trigger_valid(cf) && net_equal(n->n.addr, &cf->trigger);
|
||||
return radv_trigger_valid(cf) && net_equal(n, &cf->trigger);
|
||||
}
|
||||
|
||||
int
|
||||
@ -396,7 +396,7 @@ radv_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
|
||||
// struct radv_proto *p = (struct radv_proto *) P;
|
||||
struct radv_config *cf = (struct radv_config *) (P->cf);
|
||||
|
||||
if (radv_net_match_trigger(cf, (*new)->net))
|
||||
if (radv_net_match_trigger(cf, (*new)->net->n.addr))
|
||||
return RIC_PROCESS;
|
||||
|
||||
if (cf->propagate_routes)
|
||||
@ -457,14 +457,14 @@ radv_rt_notify(struct channel *ch, struct rte_export *e)
|
||||
(preference != RA_PREF_HIGH))
|
||||
{
|
||||
log(L_WARN "%s: Invalid ra_preference value %u on route %N",
|
||||
p->p.name, preference, e->net->n.addr);
|
||||
p->p.name, preference, e->net);
|
||||
preference = RA_PREF_MEDIUM;
|
||||
preference_set = 1;
|
||||
lifetime = 0;
|
||||
lifetime_set = 1;
|
||||
}
|
||||
|
||||
rt = fib_get(&p->routes, e->net->n.addr);
|
||||
rt = fib_get(&p->routes, e->net);
|
||||
|
||||
/* Ignore update if nothing changed */
|
||||
if (rt->valid &&
|
||||
@ -487,7 +487,7 @@ radv_rt_notify(struct channel *ch, struct rte_export *e)
|
||||
else
|
||||
{
|
||||
/* Withdraw */
|
||||
rt = fib_find(&p->routes, e->net->n.addr);
|
||||
rt = fib_find(&p->routes, e->net);
|
||||
|
||||
if (!rt || !rt->valid)
|
||||
return;
|
||||
@ -546,18 +546,6 @@ again:
|
||||
p->prune_time = next;
|
||||
}
|
||||
|
||||
static int
|
||||
radv_check_active(struct radv_proto *p)
|
||||
{
|
||||
struct radv_config *cf = (struct radv_config *) (p->p.cf);
|
||||
|
||||
if (!radv_trigger_valid(cf))
|
||||
return 1;
|
||||
|
||||
struct channel *c = p->p.main_channel;
|
||||
return rt_examine(c, &cf->trigger);
|
||||
}
|
||||
|
||||
static void
|
||||
radv_postconfig(struct proto_config *CF)
|
||||
{
|
||||
@ -650,15 +638,21 @@ radv_reconfigure(struct proto *P, struct proto_config *CF)
|
||||
if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
|
||||
return 0;
|
||||
|
||||
P->cf = CF; /* radv_check_active() requires proper P->cf */
|
||||
p->active = radv_check_active(p);
|
||||
P->cf = CF;
|
||||
|
||||
/* Allocate or free FIB */
|
||||
radv_set_fib(p, new->propagate_routes);
|
||||
|
||||
/* We started to accept routes so we need to refeed them */
|
||||
if (!old->propagate_routes && new->propagate_routes)
|
||||
channel_request_feeding(p->p.main_channel);
|
||||
channel_request_feeding(p->p.main_channel, NULL);
|
||||
else if (!net_equal(&old->trigger, &new->trigger))
|
||||
{
|
||||
/* On trigger change, refeed the routes for which the preexport may have changed */
|
||||
channel_request_feeding(p->p.main_channel, &old->trigger);
|
||||
channel_request_feeding(p->p.main_channel, &new->trigger);
|
||||
}
|
||||
|
||||
|
||||
struct iface *iface;
|
||||
WALK_LIST(iface, iface_list)
|
||||
|
@ -327,14 +327,14 @@ rip_rt_notify(struct channel *ch, struct rte_export *e)
|
||||
if (rt_metric > p->infinity)
|
||||
{
|
||||
log(L_WARN "%s: Invalid rip_metric value %u for route %N",
|
||||
p->p.name, rt_metric, e->net->n.addr);
|
||||
p->p.name, rt_metric, e->net);
|
||||
rt_metric = p->infinity;
|
||||
}
|
||||
|
||||
if (rt_tag > 0xffff)
|
||||
{
|
||||
log(L_WARN "%s: Invalid rip_tag value %u for route %N",
|
||||
p->p.name, rt_tag, e->net->n.addr);
|
||||
p->p.name, rt_tag, e->net);
|
||||
rt_metric = p->infinity;
|
||||
rt_tag = 0;
|
||||
}
|
||||
@ -346,7 +346,7 @@ rip_rt_notify(struct channel *ch, struct rte_export *e)
|
||||
* collection.
|
||||
*/
|
||||
|
||||
en = fib_get(&p->rtable, e->net->n.addr);
|
||||
en = fib_get(&p->rtable, e->net);
|
||||
|
||||
old_metric = en->valid ? en->metric : -1;
|
||||
|
||||
@ -360,7 +360,7 @@ rip_rt_notify(struct channel *ch, struct rte_export *e)
|
||||
else
|
||||
{
|
||||
/* Withdraw */
|
||||
en = fib_find(&p->rtable, e->net->n.addr);
|
||||
en = fib_find(&p->rtable, e->net);
|
||||
|
||||
if (!en || en->valid != RIP_ENTRY_VALID)
|
||||
return;
|
||||
|
@ -347,7 +347,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
||||
}
|
||||
|
||||
void
|
||||
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
|
||||
krt_replace_rte(struct krt_proto *p, rte *new, rte *old)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
|
@ -1427,7 +1427,7 @@ nl_replace_rte(struct krt_proto *p, rte *e)
|
||||
|
||||
|
||||
void
|
||||
krt_replace_rte(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
|
||||
krt_replace_rte(struct krt_proto *p, rte *new, rte *old)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
|
@ -552,7 +552,7 @@ krt_flush_routes(struct krt_proto *p)
|
||||
if (krt_is_installed(p, n))
|
||||
{
|
||||
/* FIXME: this does not work if gw is changed in export filter */
|
||||
krt_replace_rte(p, n, NULL, n->routes);
|
||||
krt_replace_rte(p, NULL, n->routes);
|
||||
}
|
||||
}
|
||||
FIB_WALK_END;
|
||||
@ -682,12 +682,12 @@ ignore:
|
||||
|
||||
update:
|
||||
krt_trace_in(p, new, "updating");
|
||||
krt_replace_rte(p, n, new, e);
|
||||
krt_replace_rte(p, new, e);
|
||||
goto done;
|
||||
|
||||
delete:
|
||||
krt_trace_in(p, e, "deleting");
|
||||
krt_replace_rte(p, n, NULL, e);
|
||||
krt_replace_rte(p, NULL, e);
|
||||
goto done;
|
||||
|
||||
done:
|
||||
@ -719,7 +719,7 @@ krt_prune(struct krt_proto *p)
|
||||
if (new)
|
||||
{
|
||||
krt_trace_in(p, new, "installing");
|
||||
krt_replace_rte(p, n, new, NULL);
|
||||
krt_replace_rte(p, new, NULL);
|
||||
}
|
||||
|
||||
if (rt_free)
|
||||
@ -742,8 +742,6 @@ krt_prune(struct krt_proto *p)
|
||||
void
|
||||
krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
|
||||
{
|
||||
net *net = e->net;
|
||||
|
||||
switch (src)
|
||||
{
|
||||
case KRT_SRC_BIRD:
|
||||
@ -754,7 +752,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
|
||||
if (new)
|
||||
{
|
||||
krt_trace_in(p, e, "[redirect] deleting");
|
||||
krt_replace_rte(p, net, NULL, e);
|
||||
krt_replace_rte(p, NULL, e);
|
||||
}
|
||||
/* If !new, it is probably echo of our deletion */
|
||||
break;
|
||||
@ -903,13 +901,12 @@ krt_rt_notify(struct channel *ch, struct rte_export *e)
|
||||
* but if we processed the update as usual, we would send withdraw to the
|
||||
* kernel, which would remove the new imported route instead.
|
||||
*/
|
||||
rte *best = e->net->routes;
|
||||
if (!e->new && best && (best->attrs->src->proto == ch->proto))
|
||||
if (!e->new && (e->new_src->proto == ch->proto))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (p->initialized) /* Before first scan we don't touch the routes */
|
||||
krt_replace_rte(p, e->net, e->new, e->old);
|
||||
krt_replace_rte(p, e->new, e->old);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -143,7 +143,7 @@ void krt_sys_copy_config(struct krt_config *, struct krt_config *);
|
||||
|
||||
int krt_capable(rte *e);
|
||||
void krt_do_scan(struct krt_proto *);
|
||||
void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old);
|
||||
void krt_replace_rte(struct krt_proto *p, rte *new, rte *old);
|
||||
int krt_sys_get_attr(const eattr *a, byte *buf, int buflen);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user