0
0
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:
Maria Matejka 2020-03-10 16:13:41 +01:00
parent 7930c03a23
commit 3357e0a199
16 changed files with 252 additions and 250 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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:

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);