diff --git a/nest/protocol.h b/nest/protocol.h index a934c047..e478d8f3 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -624,18 +624,4 @@ void *channel_config_new(const struct channel_class *cc, const char *name, uint 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); - -/* Moved from route.h to avoid dependency conflicts */ -static inline void rte_update(struct proto *p, const net_addr *n, rte *new) { rte_update2(p->main_channel, n, new, p->main_source); } - -static inline void -rte_update3(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) -{ - if (c->in_table && !rte_update_in(c, n, new, src)) - return; - - rte_update2(c, n, new, src); -} - - #endif diff --git a/nest/route.h b/nest/route.h index 1b4f2866..045e4524 100644 --- a/nest/route.h +++ b/nest/route.h @@ -286,6 +286,51 @@ static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED); #define RIC_REJECT -1 /* Rejected by protocol */ #define RIC_DROP -2 /* Silently dropped by protocol */ +/** + * rte_update - enter a new update to a routing table + * @c: channel doing the update + * @net: network address + * @rte: a &rte representing the new route + * + * This function imports a new route to the appropriate table (via the channel). + * Table keys are @net (obligatory) and @rte->attrs->src. + * Both the @net and @rte pointers can be local. + * + * The route attributes (@rte->attrs) are obligatory. They can be also allocated + * locally. Anyway, if you use an already-cached attribute object, you shall + * call rta_clone() on that object yourself. (This semantics may change in future.) + * + * If the route attributes are local, you may set @rte->attrs->src to NULL, then + * the protocol's default route source will be supplied. + * + * When rte_update() gets a route, it automatically validates it. This includes + * checking for validity of the given network and next hop addresses and also + * checking for host-scope or link-scope routes. Then the import filters are + * processed and if accepted, the route is passed to route table recalculation. + * + * The accepted routes are then inserted into the table, replacing the old route + * (key is the @net together with @rte->attrs->src). Then the route is announced + * to all the channels connected to the table using the standard export mechanism. + * + * 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, const net_addr *net, struct rte *rte); + +/** + * rte_withdraw - withdraw a route from a routing table + * @c: channel doing the withdraw + * @net: network address + * @src: the route source identifier + * + * This function withdraws a previously announced route from the table. + * No import filter is called. This function is idempotent. If no route + * is found under the given key, it does nothing. + * + * If @src is NULL, the protocol's default route source is used. + */ +void rte_withdraw(struct channel *c, const net_addr *net, struct rte_src *src); + extern list routing_tables; struct config; @@ -302,9 +347,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); -rte *rte_get_temp(struct rta *); -void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src); -/* rte_update() moved to protocol.h to avoid dependency conflicts */ int rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter); 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); @@ -314,6 +356,7 @@ void rt_schedule_prune(rtable *t); void rte_dump(rte *); void rte_free(rte *); rte *rte_do_cow(rte *); +rte *rte_store(rte *); static inline rte * rte_cow(rte *r) { return (r->flags & REF_COW) ? rte_do_cow(r) : r; } rte *rte_cow_rta(rte *r, linpool *lp); void rte_init_tmp_attrs(struct rte *r, linpool *lp, uint max); @@ -324,7 +367,6 @@ void rt_dump(rtable *); void rt_dump_all(void); int rt_feed_channel(struct channel *c); void rt_feed_channel_abort(struct channel *c); -int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src); int rt_reload_channel(struct channel *c); void rt_reload_channel_abort(struct channel *c); void rt_prune_sync(rtable *t, int all); diff --git a/nest/rt-dev.c b/nest/rt-dev.c index 61f025ce..240cc8fc 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -66,34 +66,27 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad) DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip); /* Use iface ID as local source ID */ - struct rte_src *src = rt_get_source(P, ad->iface->index); - rte_update2(c, net, NULL, src); + rte_withdraw(c, net, rt_get_source(P, ad->iface->index)); } else if (flags & IF_CHANGE_UP) { - rta *a; - rte *e; - DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip); if (cf->check_link && !(ad->iface->flags & IF_LINK_UP)) return; - /* Use iface ID as local source ID */ - struct rte_src *src = rt_get_source(P, ad->iface->index); - rta a0 = { - .src = src, + /* Use iface ID as local source ID */ + .src = rt_get_source(P, ad->iface->index), .source = RTS_DEVICE, .scope = SCOPE_UNIVERSE, .dest = RTD_UNICAST, .nh.iface = ad->iface, }; - - a = rta_lookup(&a0); - e = rte_get_temp(a); - e->pflags = 0; - rte_update2(c, net, e, src); + rte e0 = { + .attrs = rta_lookup(&a0), + }; + rte_update(c, net, &e0); } } diff --git a/nest/rt-table.c b/nest/rt-table.c index ae5a8444..8b0faf91 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -267,27 +267,6 @@ rte_find(net *net, struct rte_src *src) return e; } -/** - * rte_get_temp - get a temporary &rte - * @a: attributes to assign to the new route (a &rta; in case it's - * un-cached, rte_update() will create a cached copy automatically) - * - * Create a temporary &rte and bind it with the attributes @a. - * Also set route preference to the default preference set for - * the protocol. - */ -rte * -rte_get_temp(rta *a) -{ - rte *e = sl_alloc(rte_slab); - - e->attrs = a; - e->id = 0; - e->flags = 0; - e->pref = 0; - return e; -} - rte * rte_do_cow(rte *r) { @@ -299,6 +278,18 @@ rte_do_cow(rte *r) return e; } +rte * +rte_store(rte *r) +{ + rte *e = sl_alloc(rte_slab); + memcpy(e, r, sizeof(rte)); + if (e->attrs->aflags & RTAF_CACHED) + e->attrs = rta_clone(r->attrs); + else + e->attrs = rta_lookup(r->attrs); + return e; +} + /** * rte_cow_rta - get a private writable copy of &rte with writable &rta * @r: a route entry to be copied @@ -1382,49 +1373,7 @@ rte_unhide_dummy_routes(net *net, rte **dummy) } } -/** - * rte_update - enter a new update to a routing table - * @table: table to be updated - * @c: channel doing the update - * @net: network node - * @p: protocol submitting the update - * @src: protocol originating the update - * @new: a &rte representing the new route or %NULL for route removal. - * - * This function is called by the routing protocols whenever they discover - * a new route or wish to update/remove an existing route. The right announcement - * sequence is to build route attributes first (either un-cached with @aflags set - * to zero or a cached one using rta_lookup(); in this case please note that - * you need to increase the use count of the attributes yourself by calling - * rta_clone()), call rte_get_temp() to obtain a temporary &rte, fill in all - * the appropriate data and finally submit the new &rte by calling rte_update(). - * - * @src specifies the protocol that originally created the route and the meaning - * of protocol-dependent data of @new. If @new is not %NULL, @src have to be the - * same value as @new->attrs->proto. @p specifies the protocol that called - * rte_update(). In most cases it is the same protocol as @src. rte_update() - * stores @p in @new->sender; - * - * When rte_update() gets any route, it automatically validates it (checks, - * whether the network and next hop address are valid IP addresses and also - * whether a normal routing protocol doesn't try to smuggle a host or link - * scope route to the table), converts all protocol dependent attributes stored - * in the &rte to temporary extended attributes, consults import filters of the - * protocol to see if the route should be accepted and/or its attributes modified, - * stores the temporary attributes back to the &rte. - * - * Now, having a "public" version of the route, we - * automatically find any old route defined by the protocol @src - * for network @n, replace it by the new one (or removing it if @new is %NULL), - * recalculate the optimal route for this destination and finally broadcast - * the change (if any) to all routing protocols by calling rte_announce(). - * - * All memory used for attribute lists and other temporary allocations is taken - * from a special linear pool @rte_update_pool and freed when rte_update() - * finishes. - */ - -void +static void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) { struct proto *p = c->proto; @@ -1528,6 +1477,29 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) rte_update_unlock(); } +static int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src); + +void +rte_withdraw(struct channel *c, const net_addr *n, struct rte_src *src) +{ + if (!c->in_table || rte_update_in(c, n, NULL, src)) + rte_update2(c, n, NULL, src ?: c->proto->main_source); +} + +void +rte_update(struct channel *c, const net_addr *n, struct rte *new) +{ + ASSERT(new); + ASSERT(new->attrs); + ASSERT(new->attrs->src); + + rte *e = sl_alloc(rte_slab); + *e = *new; + + if (!c->in_table || rte_update_in(c, n, e, e->attrs->src)) + rte_update2(c, n, e, e->attrs->src); +} + /* Independent call to rte_announce(), used from next hop recalculation, outside of rte_update(). new must be non-NULL */ static inline void @@ -2415,7 +2387,7 @@ rt_feed_channel_abort(struct channel *c) * Import table */ -int +static int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) { struct rtable *tab = c->in_table; diff --git a/proto/babel/babel.c b/proto/babel/babel.c index ebd5f7cc..21fef030 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -640,15 +640,18 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) .nh.iface = r->neigh->ifa->iface, }; - rta *a = rta_lookup(&a0); - rte *rte = rte_get_temp(a); - rte->u.babel.seqno = r->seqno; - rte->u.babel.metric = r->metric; - rte->u.babel.router_id = r->router_id; - rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID); + rte e0 = { + .attrs = rta_lookup(&a0), + .u.babel = { + .seqno = r->seqno, + .metric = r->metric, + .router_id = r->router_id, + }, + .pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID), + }; e->unreachable = 0; - rte_update2(c, e->n.addr, rte, p->p.main_source); + rte_update(c, e->n.addr, &e0); } else if (e->valid && (e->router_id != p->router_id)) { @@ -660,20 +663,19 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) .dest = RTD_UNREACHABLE, }; - rta *a = rta_lookup(&a0); - rte *rte = rte_get_temp(a); - memset(&rte->u.babel, 0, sizeof(rte->u.babel)); - rte->pflags = 0; - rte->pref = 1; + rte e0 = { + .attrs = &a0, + .pref = 1, + }; e->unreachable = 1; - rte_update2(c, e->n.addr, rte, p->p.main_source); + rte_update(c, e->n.addr, &e0); } else { /* Retraction */ e->unreachable = 0; - rte_update2(c, e->n.addr, NULL, p->p.main_source); + rte_withdraw(c, e->n.addr, p->p.main_source); } } @@ -683,7 +685,7 @@ babel_announce_retraction(struct babel_proto *p, struct babel_entry *e) { struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel; e->unreachable = 0; - rte_update2(c, e->n.addr, NULL, p->p.main_source); + rte_withdraw(c, e->n.addr, p->p.main_source); } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index ee031c05..49cbadab 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1304,7 +1304,7 @@ bgp_rte_update(struct bgp_parse_state *s, net_addr *n, u32 path_id, rta *a0) if (!a0) { /* Route withdraw */ - rte_update3(&s->channel->c, n, NULL, s->last_src); + rte_withdraw(&(s->channel->c), n, s->last_src); return; } @@ -1319,13 +1319,12 @@ bgp_rte_update(struct bgp_parse_state *s, net_addr *n, u32 path_id, rta *a0) a0->eattrs = ea; } - rta *a = rta_clone(s->cached_rta); - rte *e = rte_get_temp(a); + rte e0 = { + .attrs = rta_clone(s->cached_rta), + .u.bgp.stale = -1, + }; - e->pflags = 0; - e->u.bgp.suppressed = 0; - e->u.bgp.stale = -1; - rte_update3(&s->channel->c, n, e, s->last_src); + rte_update(&(s->channel->c), n, &e0); } static void diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index b5787b54..81157761 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -2052,27 +2052,29 @@ again1: if (reload || ort_changed(nf, &a0)) { - rta *a = rta_lookup(&a0); - rte *e = rte_get_temp(a); + rte e0 = { + .attrs = rta_lookup(&a0), + .u.ospf.metric1 = nf->old_metric1 = nf->n.metric1, + .u.ospf.metric2 = nf->old_metric2 = nf->n.metric2, + .u.ospf.tag = nf->old_tag = nf->n.tag, + .u.ospf.router_id = nf->old_rid = nf->n.rid, + .pflags = EA_ID_FLAG(EA_OSPF_METRIC1) | EA_ID_FLAG(EA_OSPF_ROUTER_ID), + }; rta_free(nf->old_rta); - nf->old_rta = rta_clone(a); - e->u.ospf.metric1 = nf->old_metric1 = nf->n.metric1; - e->u.ospf.metric2 = nf->old_metric2 = nf->n.metric2; - e->u.ospf.tag = nf->old_tag = nf->n.tag; - e->u.ospf.router_id = nf->old_rid = nf->n.rid; - e->pflags = EA_ID_FLAG(EA_OSPF_METRIC1) | EA_ID_FLAG(EA_OSPF_ROUTER_ID); + nf->old_rta = rta_clone(e0.attrs); if (nf->n.type == RTS_OSPF_EXT2) - e->pflags |= EA_ID_FLAG(EA_OSPF_METRIC2); + e0.pflags |= EA_ID_FLAG(EA_OSPF_METRIC2); /* Perhaps onfly if tag is non-zero? */ if ((nf->n.type == RTS_OSPF_EXT1) || (nf->n.type == RTS_OSPF_EXT2)) - e->pflags |= EA_ID_FLAG(EA_OSPF_TAG); + e0.pflags |= EA_ID_FLAG(EA_OSPF_TAG); 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, nf->fn.addr, e); + + rte_update(p->p.main_channel, nf->fn.addr, &e0); } } else if (nf->old_rta) @@ -2081,7 +2083,7 @@ again1: rta_free(nf->old_rta); nf->old_rta = NULL; - rte_update(&p->p, nf->fn.addr, NULL); + rte_withdraw(p->p.main_channel, nf->fn.addr, p->p.main_source); } /* Remove unused rt entry, some special entries are persistent */ @@ -2097,7 +2099,6 @@ again1: } FIB_ITERATE_END; - WALK_LIST(oa, p->area_list) { /* Cleanup ASBR hash tables */ diff --git a/proto/perf/perf.c b/proto/perf/perf.c index ba401a8a..a72023b3 100644 --- a/proto/perf/perf.c +++ b/proto/perf/perf.c @@ -160,18 +160,17 @@ perf_loop(void *data) clock_gettime(CLOCK_MONOTONIC, &ts_generated); - for (uint i=0; idata[i].a); - e->pflags = 0; - - rte_update(P, &(p->data[i].net), e); + for (uint i=0; idata[i].a, }; + rte_update(P->main_channel, &(p->data[i].net), &e0); } clock_gettime(CLOCK_MONOTONIC, &ts_update); if (!p->keep) for (uint i=0; idata[i].net), NULL); + rte_withdraw(P->main_channel, &(p->data[i].net), p->p.main_source); clock_gettime(CLOCK_MONOTONIC, &ts_withdraw); diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index efb992ca..e09e2c27 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -50,7 +50,7 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o struct channel *dst = (src_ch == p->pri) ? p->sec : p->pri; struct rte_src *src; - rte *e; + rte e0 = {}, *e = &e0; rta *a; if (!new && !old) @@ -70,7 +70,8 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o a->aflags = 0; a->hostentry = NULL; - e = rte_get_temp(a); + + e->attrs = rta_lookup(a); e->pflags = 0; /* Copy protocol specific embedded attributes. */ @@ -93,7 +94,10 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o } src_ch->table->pipe_busy = 1; - rte_update2(dst, n->n.addr, e, src); + if (e) + rte_update(dst, n->n.addr, e); + else + rte_withdraw(dst, n->n.addr, src); src_ch->table->pipe_busy = 0; } diff --git a/proto/rip/rip.c b/proto/rip/rip.c index ae8007d9..81dab810 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -187,21 +187,20 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) a0.nh.iface = rt->from->ifa->iface; } - rta *a = rta_lookup(&a0); - rte *e = rte_get_temp(a); + rte e0 = { + .attrs = rta_lookup(&a0), + .u.rip = { + .from = a0.nh.iface, + .metric = rt_metric, + .tag = rt_tag, + }, + .pflags = EA_ID_FLAG(EA_RIP_METRIC) | EA_ID_FLAG(EA_RIP_TAG) + }; - e->u.rip.from = a0.nh.iface; - e->u.rip.metric = rt_metric; - e->u.rip.tag = rt_tag; - e->pflags = EA_ID_FLAG(EA_RIP_METRIC) | EA_ID_FLAG(EA_RIP_TAG); - - rte_update(&p->p, en->n.addr, e); + rte_update(p->p.main_channel, en->n.addr, &e0); } else - { - /* Withdraw */ - rte_update(&p->p, en->n.addr, NULL); - } + 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 aa07f7d9..ba1cdfdf 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -127,19 +127,16 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_ .dest = RTD_NONE, }; - rta *a = rta_lookup(&a0); - rte *e = rte_get_temp(a); + rte e0 = { .attrs = rta_lookup(&a0) }; - e->pflags = 0; - - rte_update2(channel, &pfxr->n, e, a0.src); + rte_update(channel, &pfxr->n, &e0); } void rpki_table_remove_roa(struct rpki_cache *cache, struct channel *channel, const net_addr_union *pfxr) { struct rpki_proto *p = cache->p; - rte_update2(channel, &pfxr->n, NULL, p->p.main_source); + rte_withdraw(channel, &pfxr->n, p->p.main_source); } diff --git a/proto/static/static.c b/proto/static/static.c index c899cc87..f68e9a44 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -99,13 +99,12 @@ static_announce_rte(struct static_proto *p, struct static_route *r) return; /* We skip rta_lookup() here */ - rte *e = rte_get_temp(a); - e->pflags = 0; + rte e0 = { .attrs = a }, *e = &e0; if (r->cmds) f_eval_rte(r->cmds, &e, static_lp); - rte_update(&p->p, r->net, e); + rte_update(p->p.main_channel, r->net, e); r->state = SRS_CLEAN; if (r->cmds) @@ -117,7 +116,7 @@ withdraw: if (r->state == SRS_DOWN) return; - rte_update(&p->p, r->net, NULL); + rte_withdraw(p->p.main_channel, r->net, p->p.main_source); r->state = SRS_DOWN; } @@ -250,7 +249,7 @@ static void static_remove_rte(struct static_proto *p, struct static_route *r) { if (r->state) - rte_update(&p->p, r->net, NULL); + rte_withdraw(p->p.main_channel, r->net, NULL); static_reset_rte(p, r); } diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index c2faa23d..b55df047 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -374,7 +374,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) /* p is NULL iff KRT_SHARED_SOCKET and !scan */ int ipv6; - rte *e; net *net; sockaddr dst, gate, mask; ip_addr idst, igate, imask; @@ -495,7 +494,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) net = net_get(p->p.main_channel->table, &ndst); rta a = { - .src = p->p.main_source, .source = RTS_INHERIT, .scope = SCOPE_UNIVERSE, }; @@ -549,14 +547,12 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) } } - done: - e = rte_get_temp(&a); + done:; + rte e0 = {}, *e = &e0; + e->attrs = &a; e->net = net; e->u.krt.src = src; e->u.krt.proto = src2; - e->u.krt.seen = 0; - e->u.krt.best = 0; - e->u.krt.metric = 0; if (scan) krt_got_route(p, e); diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index a9e711b4..235e2dd7 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -1455,12 +1455,11 @@ nl_mergable_route(struct nl_parse_state *s, net *net, struct krt_proto *p, uint static void nl_announce_route(struct nl_parse_state *s) { - rte *e = rte_get_temp(s->attrs); + rte e0 = {}, *e = &e0; + e->attrs = s->attrs; e->net = s->net; e->u.krt.src = s->krt_src; e->u.krt.proto = s->krt_proto; - e->u.krt.seen = 0; - e->u.krt.best = 0; e->u.krt.metric = s->krt_metric; if (s->scan) @@ -1626,7 +1625,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) nl_announce_route(s); rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE); - ra->src = p->p.main_source; ra->source = RTS_INHERIT; ra->scope = SCOPE_UNIVERSE; diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index cccee456..fd0d6f68 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -298,18 +298,19 @@ krt_uptodate(rte *a, rte *b) static void krt_learn_announce_update(struct krt_proto *p, rte *e) { - net *n = e->net; - rta *aa = rta_clone(e->attrs); - rte *ee = rte_get_temp(aa); - ee->pflags = EA_ID_FLAG(EA_KRT_SOURCE) | EA_ID_FLAG(EA_KRT_METRIC); - ee->u.krt = e->u.krt; - rte_update(&p->p, n->n.addr, ee); + rte e0 = { + .attrs = rta_clone(e->attrs), + .pflags = EA_ID_FLAG(EA_KRT_SOURCE) | EA_ID_FLAG(EA_KRT_METRIC), + .u.krt = e->u.krt, + }; + + rte_update(p->p.main_channel, e->net->n.addr, &e0); } static void -krt_learn_announce_delete(struct krt_proto *p, net *n) +krt_learn_announce_delete(struct krt_proto *p, net_addr *n) { - rte_update(&p->p, n->n.addr, NULL); + rte_withdraw(p->p.main_channel, n, p->p.main_source); } /* Called when alien route is discovered during scan */ @@ -320,7 +321,7 @@ krt_learn_scan(struct krt_proto *p, rte *e) net *n = net_get(&p->krt_table, n0->n.addr); rte *m, **mm; - e->attrs = rta_lookup(e->attrs); + e = rte_store(e); for(mm=&n->routes; m = *mm; mm=&m->next) if (krt_same_key(m, e)) @@ -401,7 +402,7 @@ again: { DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen); if (old_best) - krt_learn_announce_delete(p, n); + krt_learn_announce_delete(p, n->n.addr); FIB_ITERATE_PUT(&fit); fib_delete(fib, n); @@ -433,7 +434,7 @@ krt_learn_async(struct krt_proto *p, rte *e, int new) net *n = net_get(&p->krt_table, n0->n.addr); rte *g, **gg, *best, **bestp, *old_best; - e->attrs = rta_lookup(e->attrs); + e = rte_store(e); old_best = n->routes; for(gg=&n->routes; g = *gg; gg = &g->next) @@ -499,7 +500,7 @@ krt_learn_async(struct krt_proto *p, rte *e, int new) if (best) krt_learn_announce_update(p, best); else - krt_learn_announce_delete(p, n); + krt_learn_announce_delete(p, n->n.addr); } } @@ -641,10 +642,7 @@ krt_got_route(struct krt_proto *p, rte *e) if (KRT_CF->learn) krt_learn_scan(p, e); else - { - krt_trace_in_rl(&rl_alien, p, e, "[alien] ignored"); - rte_free(e); - } + krt_trace_in_rl(&rl_alien, p, e, "[alien] ignored"); return; } #endif @@ -700,8 +698,6 @@ delete: goto done; done: - rte_free(e); - if (rt_free) rte_free(rt_free); @@ -779,7 +775,6 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new) } #endif } - rte_free(e); } /*