diff --git a/nest/route.h b/nest/route.h index 92b9cb3a..0c588f66 100644 --- a/nest/route.h +++ b/nest/route.h @@ -231,6 +231,7 @@ typedef struct rte { struct rta *attrs; /* Attributes of this route */ const net_addr *net; /* Network this RTE belongs to */ struct rte_src *src; /* Route source that created the route */ + struct channel *sender; /* Channel used to send the route to the routing table */ byte flags; /* Flags (REF_...) */ byte pflags; /* Protocol-specific flags */ } rte; @@ -241,8 +242,8 @@ struct rte_storage { struct rta *attrs; /* Attributes of this route */ net *net; /* Network this RTE belongs to */ struct rte_src *src; /* Route source that created the route */ - struct channel *sender; /* Channel used to send the route to the routing table */ + u32 id; /* Table specific route id */ byte flags; /* Flags (REF_...) */ byte pflags; /* Protocol-specific flags */ @@ -300,7 +301,6 @@ struct rte_export { /** * rte_update - enter a new update to a routing table - * @c: channel doing the update * @rte: a &rte representing the new route * * This function imports a new route to the appropriate table (via the channel). @@ -326,10 +326,10 @@ struct rte_export { * All memory used for temporary allocations is taken from a special linpool * @rte_update_pool and freed when rte_update() finishes. */ -void rte_update(struct channel *c, struct rte *rte) NONNULL(1,2); +void rte_update(struct rte *rte) NONNULL(1); static inline void rte_withdraw(struct channel *c, const net_addr *net, struct rte_src *src) { - rte e = { .net = net, .src = src}; rte_update(c, &e); + rte e = { .sender = c, .net = net, .src = src}; rte_update(&e); } extern list routing_tables; @@ -365,6 +365,7 @@ static inline rte rte_copy(const struct rte_storage *r) .attrs = r->attrs, .net = r->net->n.addr, .src = r->src, + .sender = r->sender, .flags = r->flags, .pflags = r->pflags } : (rte) {}; diff --git a/nest/rt-dev.c b/nest/rt-dev.c index f40c588e..698893aa 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -87,8 +87,9 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad) .src = rt_get_source(P, ad->iface->index), .net = net, .attrs = &a0, + .sender = c, }; - rte_update(c, &e0); + rte_update(&e0); } } diff --git a/nest/rt-table.c b/nest/rt-table.c index e0898bc6..ad33f0a6 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -291,6 +291,7 @@ rte_store(const rte *r, net *n) .attrs = r->attrs, .net = n, .src = r->src, + .sender = r->sender, }; rt_lock_source(e->src); @@ -306,7 +307,6 @@ rte_store(const rte *r, net *n) void rte_copy_metadata(struct rte_storage *dest, struct rte_storage *src) { - dest->sender = src->sender; dest->flags = src->flags & REF_FILTERED; dest->pflags = src->pflags; dest->lastmod = src->lastmod; @@ -891,9 +891,10 @@ rte_same(struct rte_storage *x, rte *y, _Bool fy) rte_is_filtered(x) == fy; } -static void NONNULL(1,2,3) -rte_recalculate(struct channel *c, net *net, rte *new, _Bool filtered) +static void NONNULL(1,2) +rte_recalculate(net *net, rte *new, _Bool filtered) { + struct channel *c = new->sender; struct proto *p = c->proto; struct rtable *table = c->table; struct proto_stats *stats = &c->stats; @@ -1028,7 +1029,6 @@ rte_recalculate(struct channel *c, net *net, rte *new, _Bool filtered) if (new->attrs) { new_stored = rte_store(new, net); - new_stored->sender = c; if (filtered) new_stored->flags |= REF_FILTERED; @@ -1184,31 +1184,33 @@ rte_update_unlock(void) lp_flush(rte_update_pool); } -static int NONNULL(1,2) rte_update_in(struct channel *c, rte *new); -static void NONNULL(1,2) rte_update2(struct channel *c, rte *new); +static int NONNULL(1) rte_update_in(rte *new); +static void NONNULL(1) rte_update2(rte *new); -void NONNULL(1,2) -rte_update(struct channel *c, rte *new) +void NONNULL(1) +rte_update(rte *new) { - ASSERT(c->channel_state == CS_UP); + ASSERT(new->sender); + ASSERT(new->sender->channel_state == CS_UP); ASSERT(new->net); ASSERT(new->src); if (new->attrs && !new->attrs->pref) { ASSERT(!new->attrs->cached); - new->attrs->pref = c->preference; + new->attrs->pref = new->sender->preference; } - if (c->in_table && !rte_update_in(c, new)) + if (new->sender->in_table && !rte_update_in(new)) return; - rte_update2(c, new); + rte_update2(new); } -static void NONNULL(1,2) -rte_update2(struct channel *c, rte *new) +static void NONNULL(1) +rte_update2(rte *new) { + struct channel *c = new->sender; // struct proto *p = c->proto; struct proto_stats *stats = &c->stats; const struct filter *filter = c->in_filter; @@ -1288,7 +1290,7 @@ rte_update2(struct channel *c, rte *new) } /* And recalculate the best route */ - rte_recalculate(c, nn, new, filtered); + rte_recalculate(nn, new, filtered); rte_update_unlock(); return; @@ -1327,10 +1329,11 @@ rte_modify(struct rte_storage *old) .net = old->net->n.addr, .src = old->src, .attrs = old->sender->proto->rte_modify(old, rte_update_pool), + .sender = old->sender, }; if (new.attrs != old->attrs) - rte_recalculate(old->sender, old->net, &new, old->src); + rte_recalculate(old->net, &new, old->src); rte_update_unlock(); } @@ -1682,8 +1685,8 @@ again: /* Discard the route */ rte_update_lock(); - rte ew = { .net = e->net->n.addr, .src = e->src }; - rte_recalculate(e->sender, e->net, &ew, 0); + rte ew = { .net = e->net->n.addr, .src = e->src, .sender = e->sender, }; + rte_recalculate(e->net, &ew, 0); rte_update_unlock(); limit--; @@ -1880,6 +1883,7 @@ rt_next_hop_update_rte(struct rte_storage *old) .attrs = a, .net = old->net->n.addr, .src = old->src, + .sender = old->sender, }; rte_trace_in(D_ROUTES, old->sender, &e, "updated"); @@ -2240,8 +2244,9 @@ rt_feed_channel_abort(struct channel *c) */ static int -rte_update_in(struct channel *c, rte *new) +rte_update_in(rte *new) { + struct channel *c = new->sender; struct rtable *tab = c->in_table; struct rte_storage *old, **pos; net *net; @@ -2312,7 +2317,6 @@ rte_update_in(struct channel *c, rte *new) /* Insert the new rte */ struct rte_storage *e = rte_store(new, net); - e->sender = c; e->lastmod = current_time(); e->next = *pos; *pos = e; @@ -2356,7 +2360,7 @@ rt_reload_channel(struct channel *c) } rte eloc = rte_copy(e); - rte_update2(c, &eloc); + rte_update2(&eloc); } c->reload_next_rte = NULL; @@ -2508,7 +2512,6 @@ rte_update_out(struct channel *c, struct rte_export_internal *e) if (new->attrs) { struct rte_storage *es = rte_store(new, net); - es->sender = c; es->lastmod = current_time(); es->id = e->new->id; es->next = *pos; diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 95e9e1ee..01a74655 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -674,10 +674,11 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) .net = e->n.addr, .src = p->p.main_source, .attrs = &a0, + .sender = c, }; e->unreachable = 0; - rte_update(c, &e0); + rte_update(&e0); } else if (e->valid && (e->router_id != p->router_id)) { @@ -693,10 +694,11 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) .net = e->n.addr, .src = p->p.main_source, .attrs = &a0, + .sender = c, }; e->unreachable = 1; - rte_update(c, &e0); + rte_update(&e0); } else { diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index f5411f9f..073108a3 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1362,9 +1362,10 @@ bgp_rte_update(struct bgp_parse_state *s, net_addr *n, u32 path_id, rta *a0) .net = n, .src = s->last_src, .attrs = s->cached_rta, + .sender = &(s->channel->c), }; - rte_update(&(s->channel->c), &e0); + rte_update(&e0); } static void diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index f3b7e20b..2601cfca 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -2098,7 +2098,8 @@ again1: rte e0 = { .attrs = rta_lookup(&a0), .src = p->p.main_source, - .net = nf->fn.addr, + .net = nf->fn.addr, + .sender = p->p.main_channel, }; rta_free(nf->old_rta); @@ -2107,7 +2108,7 @@ again1: DBG("Mod rte type %d - %N via %I on iface %s, met %d\n", a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1); - rte_update(p->p.main_channel, &e0); + rte_update(&e0); } } else if (nf->old_rta) diff --git a/proto/perf/perf.c b/proto/perf/perf.c index 15ffd109..0f847d1b 100644 --- a/proto/perf/perf.c +++ b/proto/perf/perf.c @@ -166,8 +166,9 @@ perf_loop(void *data) .attrs = p->data[i].a, .src = p->p.main_source, .net = &(p->data[i].net), + .sender = P->main_channel, }; - rte_update(P->main_channel, &e0); + rte_update(&e0); } clock_gettime(CLOCK_MONOTONIC, &ts_update); diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index f6fe7e69..8d457821 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -78,10 +78,11 @@ pipe_rt_notify(struct channel *src_ch, struct rte_export *export) .attrs = a, .src = export->new.src, .net = net, + .sender = dst, }; src_ch->table->pipe_busy = 1; - rte_update(dst, &e0); + rte_update(&e0); src_ch->table->pipe_busy = 0; } else @@ -93,7 +94,7 @@ pipe_rt_notify(struct channel *src_ch, struct rte_export *export) } static int -pipe_preexport(struct channel *src_ch, rte *e UNUSED) +pipe_preexport(struct channel *src_ch, rte *e) { struct pipe_proto *p = (void *) src_ch->proto; struct channel *dst = (src_ch == p->pri) ? p->sec : p->pri; @@ -102,6 +103,10 @@ pipe_preexport(struct channel *src_ch, rte *e UNUSED) if (dst->table->pipe_busy) return -1; + /* Avoid direct loopbacks */ + if (e->sender == src_ch) + return -1; + return 0; } diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 53696af0..9567cb80 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -210,10 +210,11 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) rte e0 = { .attrs = &a0, .src = p->p.main_source, - .net = en->n.addr, + .net = en->n.addr, + .sender = p->p.main_channel, }; - rte_update(p->p.main_channel, &e0); + rte_update(&e0); } else rte_withdraw(p->p.main_channel, en->n.addr, p->p.main_source); diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index 79204387..a5de7e3f 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -130,10 +130,11 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_ rte e0 = { .attrs = &a0, .src = p->p.main_source, - .net = &pfxr->n, + .net = &pfxr->n, + .sender = channel, }; - rte_update(channel, &e0); + rte_update(&e0); } void diff --git a/proto/static/static.c b/proto/static/static.c index 9c5886d5..a46c7464 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -105,12 +105,13 @@ static_announce_rte(struct static_proto *p, struct static_route *r) .attrs = a, .src = static_get_source(p, r->index), .net = r->net, + .sender = p->p.main_channel, }; if (r->cmds) f_eval_rte(r->cmds, &e0, static_lp); - rte_update(p->p.main_channel, &e0); + rte_update(&e0); r->state = SRS_CLEAN; if (r->cmds) diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index e3421ce4..c9e37a3c 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -303,9 +303,10 @@ krt_learn_announce_update(struct krt_proto *p, struct rte_storage *e) .attrs = e->attrs, .src = p->p.main_source, .net = e->net->n.addr, + .sender = p->p.main_channel, }; - rte_update(p->p.main_channel, &e0); + rte_update(&e0); } static void