From: Maria Matejka Date: Tue, 10 Mar 2020 15:13:41 +0000 (+0100) Subject: Route export: Common export function. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52b6e352512b1cee627854e1ab9619f87f3622e1;p=thirdparty%2Fbird.git Route export: Common export function. Also: * Feeding request by net. * Passing only net_addr in export structure. * Cleanup of krt_replace_rte() call. --- diff --git a/nest/proto.c b/nest/proto.c index 84d96273e..1b6995d4c 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -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); } diff --git a/nest/protocol.h b/nest/protocol.h index 21339daa1..8e94fcd57 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -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); diff --git a/nest/route.h b/nest/route.h index 3a44f4a1c..bb6677e1f 100644 --- a/nest/route.h +++ b/nest/route.h @@ -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); diff --git a/nest/rt-table.c b/nest/rt-table.c index f666bd92a..5d23ba0ac 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -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->pub.old && !bmap_test(&c->export_map, e->pub.old->id)) - e->pub.old = NULL; + 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.new && !e->pub.old) - return 0; + if (e->old && bmap_test(&c->export_map, e->old->id)) + { + e->pub.old = e->old; + e->pub.old_src = e->old->attrs->src; + } - 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; - - 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); + struct rte_export_internal rei = { + .new_best = n->routes, + .refeed = 1, + }; - /* 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 diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 0cc633fa6..6765b8952 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -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; diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 281b98890..e8bbafc64 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -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); diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 8e591022c..23e42ec33 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -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: diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 3822e4c02..959e73396 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -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; } diff --git a/proto/perf/perf.c b/proto/perf/perf.c index 452821b8c..a6681592a 100644 --- a/proto/perf/perf.c +++ b/proto/perf/perf.c @@ -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"); } diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index e5b27717f..4942cbc92 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -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); } diff --git a/proto/radv/radv.c b/proto/radv/radv.c index 2f95a0bbc..c924ef84f 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -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) diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 5ac8a1066..d19588bdf 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -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; diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index bca2d9d25..ec9284808 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -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; diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index ae33a1449..87c157fa6 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -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; diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 16b3d2e14..e6176b3a7 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -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 diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 310a2d113..72659a3a6 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -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);