0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-09-19 11:55:21 +00:00

Route export: Common export function.

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 e64fd37675
commit 52b6e35251
16 changed files with 250 additions and 237 deletions

View File

@ -168,6 +168,8 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
c->last_tx_filter_change = current_time();
c->reloadable = 1;
init_list(&c->net_feed);
CALL(c->channel->init, c, cf);
add_tail(&p->channels, &c->n);
@ -279,6 +281,27 @@ channel_feed_loop(void *ptr)
c->proto->feed_end(c);
}
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_start_export(struct channel *c)
@ -296,6 +319,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);
@ -515,7 +548,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);
@ -530,9 +563,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;
@ -702,7 +743,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);
return 1;
}
@ -1998,7 +2039,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

@ -536,9 +536,18 @@ struct channel {
struct rte *reload_next_rte; /* Route iterator in in_table used during reloading */
u8 reload_active; /* Iterator reload_fit is linked */
list net_feed; /* Active net feeders (struct channel_net_feed) */
struct rtable *out_table; /* Internal table for exported routes */
};
struct channel_net_feed {
node n;
struct event e;
struct channel *c;
net_addr addr[0];
};
/*
* Channel states
@ -612,7 +621,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

@ -225,12 +225,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 */
@ -320,7 +321,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);
@ -335,6 +335,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

@ -353,12 +353,13 @@ rte_free_quick(rte *e)
struct rte_export_internal {
struct rte_export pub;
rte *new_best;
rte *old_best;
rte *new, *old, *new_best, *old_best;
rte *rt_free;
uint refeed:1;
_Bool refeed;
};
//_Thread_local static struct rte_export_internal rei;
static int /* Actually better or at least as good as */
rte_better(rte *new, rte *old)
{
@ -434,6 +435,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;
@ -442,28 +444,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, p, rt, "rejected by protocol");
goto reject;
}
if (pv > 0)
if (v > 0)
{
if (!silent)
rte_trace_out(D_FILTERS, p, 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;
@ -483,9 +485,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)
@ -500,13 +501,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 */
@ -528,7 +528,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)
@ -572,25 +572,28 @@ 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)
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)
{
e->pub.new = export_filter(c, e->new, &e->rt_free, 0);
e->pub.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))
{
e->pub.old = e->old;
e->pub.old_src = e->old->attrs->src;
}
if (!e->pub.new && !e->pub.old)
return 0;
return 1;
return e->pub.new || e->pub.old;
}
USE_RESULT static _Bool
rt_notify_accepted(struct channel *c, struct rte_export_internal *e)
rt_notify_accepted(struct channel *c, net *net, struct rte_export_internal *e)
{
// struct proto *p = c->proto;
rte *new_best = NULL;
@ -613,17 +616,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 (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 = net->routes; rte_is_valid(r); r = r->next)
{
if (bmap_test(&c->export_map, r->id))
{
@ -632,23 +635,23 @@ 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 = 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)))
if (new_first && (e->pub.new = export_filter(c, e->new, &e->rt_free, 0)))
new_best = e->pub.new;
else
return 0;
@ -726,7 +729,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int
USE_RESULT static _Bool
rt_notify_merged(struct channel *c, struct rte_export_internal *e)
rt_notify_merged(struct channel *c, net *net, struct rte_export_internal *e)
{
/* We assume that all rte arguments are either NULL or rte_is_valid() */
@ -736,9 +739,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)
@ -748,7 +751,10 @@ rt_notify_merged(struct channel *c, struct rte_export_internal *e)
/* 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);
{
e->pub.new = rt_export_merged(c, net, &(e->rt_free), rte_update_pool, 0);
e->pub.new_src = net->routes->attrs->src;
}
/* Check old merged route */
if (e->old_best && !bmap_test(&c->export_map, e->old_best->id))
@ -757,12 +763,84 @@ rt_notify_merged(struct channel *c, struct rte_export_internal *e)
if (!e->pub.new && !e->pub.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;
return 1;
}
static inline void
rte_export_finish(struct channel *c, struct rte_export_internal *e)
{
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);
}
static uint
rte_export(struct channel *c, net *n, struct rte_export_internal *e)
{
e->pub.net = n->n.addr;
uint ra_mode = c->ra_mode;
switch (ra_mode)
{
case RA_OPTIMAL:
if (e->new_best == e->old_best)
return 0;
e->new = e->new_best;
e->old = e->old_best;
/* fall through */
case RA_ANY:
if (!e->new && !e->old)
break;
if (rt_notify_basic(c, e))
do_rt_notify(c, &e->pub, e->refeed);
rte_export_finish(c, e);
return 1;
case RA_ACCEPTED:
if (rt_notify_accepted(c, n, e))
do_rt_notify(c, &e->pub, e->refeed);
rte_export_finish(c, e);
return 1;
case RA_MERGED:
if (rt_notify_merged(c, n, e))
do_rt_notify(c, &e->pub, e->refeed);
rte_export_finish(c, e);
return 1;
}
uint cnt = 0;
for (rte *ee = n->routes; ee; ee = ee->next)
{
if (!rte_is_valid(ee))
continue;
switch (ra_mode)
{
case RA_ANY:
cnt++;
e->new = ee;
e->old = ee;
rte_export(c, n, e);
break;
default:
bug("strange export mode");
}
}
return cnt;
}
/**
* rte_announce - announce a routing table change
@ -851,60 +929,12 @@ 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 = {
.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, net, &rei);
}
}
@ -1408,37 +1438,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
@ -2182,65 +2181,37 @@ 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;
struct rte_export_internal rei = {
.new_best = n->routes,
.refeed = 1,
};
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;
}
rte_update_lock();
max_feed -= rte_export(c, n, &rei);
rte_update_unlock();
}
FIB_ITERATE_END;
done:
c->feed_active = 0;
return 1;
}
void rt_feed_channel_net(struct channel *c, net_addr *n)
{
net *nn = net_find(c->table, n);
if (!nn)
return;
struct rte_export_internal rei = {
.new_best = nn->routes,
.refeed = 1,
};
rte_update_lock();
rte_export(c, nn, &rei);
rte_update_unlock();
}
/**
* rt_feed_baby_abort - abort protocol feeding
* @c: channel

View File

@ -2142,11 +2142,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) ||
@ -2164,7 +2164,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

@ -1826,7 +1826,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

@ -2651,7 +2651,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

@ -1322,7 +1322,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;
@ -1349,14 +1349,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;
}
@ -1380,12 +1380,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

@ -326,14 +326,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;
}
@ -345,7 +345,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;
@ -359,7 +359,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

@ -1394,7 +1394,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);