From: Maria Matejka Date: Tue, 10 Mar 2020 15:13:41 +0000 (+0100) Subject: Route export: More elegant export dispatcher. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3357e0a199868a27af8936f06b6efbc8f81706ee;p=thirdparty%2Fbird.git Route export: More elegant export dispatcher. 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 b3b048193..5ecbe9a22 100644 --- a/nest/proto.c +++ b/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); } diff --git a/nest/protocol.h b/nest/protocol.h index ea063326c..9dc7a085e 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -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); diff --git a/nest/route.h b/nest/route.h index 2759bc172..bcaf15c01 100644 --- a/nest/route.h +++ b/nest/route.h @@ -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); diff --git a/nest/rt-table.c b/nest/rt-table.c index 921608056..e831a77fa 100644 --- a/nest/rt-table.c +++ b/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->pub.old && !bmap_test(&c->export_map, e->pub.old->id)) - e->pub.old = NULL; + if (e->new) + { + ep->new = export_filter(c, e->new, &e->rt_free, 0); + ep->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)) + { + ep->old = e->old; + ep->old_src = e->old->attrs->src; + } - 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; } diff --git a/proto/babel/babel.c b/proto/babel/babel.c index f00cd08fe..9693025d1 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -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; diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 4d1bd3f16..f2810fd1d 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -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); diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 841b42fba..005c73977 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -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: diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 4c757c864..e1ddc1063 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -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; } 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 a8a335f7f..7cf1524ad 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 9c84d7351..cf50a4a82 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -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; 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 3b9fa81a4..6a5d64872 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -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; diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 333b482ed..bf6e43a20 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);