Hi Lars, Thanks for picking this up!
On Tue, Jan 06, 2026 at 04:43:41AM +0100, Lars Gierth via Bird-users wrote: > Hi all, > > happy new year and thanks for the fresh releases! > > We have been successfully running the Babel route selection patch [1] with > Bird 2.17 in our community mesh network with ~200 Babel nodes since Q3/2024. > It has allowed us to really fine-tune a mix of all kinds of wire types > connecting the locations: wifi at 60 / 5 / 2 GHz, tunnels over LTE or DSL, > fiber in a datacenter, etc. etc. With Babel being a critical part of our > network, the patch is running on a broad range of architectures: mips, > ppc64, x86_64, and various arm and aarch64 types. > > With dxld's consent I took his patch and rebased it on Bird 3.1, and we've > been testing that for 2 months on the live network. Today I rebased it on > 3.2 (thread-next branch), it applied cleanly but I haven't tested it yet. > Nevertheless I decided to share it now, see attachment. > > Kind regards, > Lars > Freifunk Berlin > > [1] https://bird.network.cz/pipermail/bird-users/2023-February/016705.html > From d2ee215ea7927fe5677990781bffe682b7e53719 Mon Sep 17 00:00:00 2001 > From: Packet Please <[email protected]> > Date: Sat, 8 Nov 2025 18:57:18 +0100 > Subject: [PATCH] Babel: Replace internal route selection by bird's nest > MIME-Version: 1.0 > Content-Type: text/plain; charset=UTF-8 > Content-Transfer-Encoding: 8bit > > This introduces the ability to filter routes from specific interfaces and > neighbours. With the current internal route selection proto babel exports > only up to one route and an admin cannot do fine-grained filtering. > > To fix this we rip out the internal route selection entirely and export > evey babel route as a distinct route into the bird's nest instead. > > In the presence of esoteric route filters this change may be observable by > users however we feel the additional filtering power is more important. A > release note entry for this change is recommended. > > Signed-off-by: Daniel GrM-CM-6ber <[email protected]> Also add a Co-authored-by/Co-developed-by please. Also Is the encoding broken? https://www.kernel.org/doc/html/latest/process/submitting-patches.html#when-to-use-acked-by-cc-and-co-developed-by > Signed-off-by: Lars Gierth <[email protected]> > --- > proto/babel/babel.c | 306 ++++++++++++++++++++++---------------------- > proto/babel/babel.h | 3 + > 2 files changed, 154 insertions(+), 155 deletions(-) > > diff --git a/proto/babel/babel.c b/proto/babel/babel.c > index c7d47c01f..5f3e94fe1 100644 The patch doesn't apply. On thread-next (0b91feeda): $ git am < babel.patch Applying: Babel: Replace internal route selection by bird's nest error: patch failed: proto/babel/babel.c:251 error: proto/babel/babel.c: patch does not apply error: patch failed: proto/babel/babel.h:25 error: proto/babel/babel.h: patch does not apply Patch failed at 0001 Babel: Replace internal route selection by bird's nest hint: Use 'git am --show-current-patch=diff' to see the failed patch hint: When you have resolved this problem, run "git am --continue". hint: If you prefer to skip this patch, run "git am --skip" instead. hint: To restore the original branch and stop patching, run "git am --abort". hint: Disable this message with "git config advice.mergeConflict false" Could you use git-send-email(1) please :> https://git-send-email.io > --- a/proto/babel/babel.c > +++ b/proto/babel/babel.c > @@ -28,10 +28,12 @@ > * possible routes for the prefix are tracked as &babel_route entries and the > * feasibility distance is maintained through &babel_source structures. > * > - * The main route selection is done in babel_select_route(). This is called > when > - * an entry is updated by receiving updates from the network or when > modified by > - * internal timers. The function selects from feasible and reachable routes > the > - * one with the lowest metric to be announced to the core. > + * The main route selection is done by bird's nest (heh). For each prefix we > + * export all feasible routes to the core with a distinct source (rte_src) > per > + * neihbour so bird handles them as distinct routes. Nest will then notify > us of > + * one best route for each prefix, either our own (internal) or from another > + * protocol, by calling babel_rt_notify. For internal best routes we remember > + * which babel_route it selected in babel_entry.selected. > * > * Supported standards: > * RFC 8966 - The Babel Routing Protocol > @@ -60,8 +62,8 @@ static inline int gt_mod64k(uint a, uint b) > { return ge_mod64k(a, b) && a != b; } > > static void babel_expire_requests(struct babel_proto *p, struct babel_entry > *e); > -static void babel_select_route(struct babel_proto *p, struct babel_entry *e, > struct babel_route *mod); > -static inline void babel_announce_retraction(struct babel_proto *p, struct > babel_entry *e); > +static void babel_announce_rte(struct babel_proto *p, struct babel_entry *e, > struct babel_route *r); > +static void babel_rte_update_unreachable(struct babel_proto *p, struct > babel_entry *e, u8 announce); > static void babel_send_route_request(struct babel_proto *p, struct > babel_entry *e, struct babel_neighbor *n); > static void babel_send_seqno_request(struct babel_proto *p, struct > babel_entry *e, struct babel_seqno_request *sr, struct babel_neighbor *n); > static void babel_update_cost(struct babel_neighbor *n); > @@ -181,9 +183,7 @@ static inline void > babel_retract_route(struct babel_proto *p, struct babel_route *r) > { > r->metric = r->advert_metric = BABEL_INFINITY; > - > - if (r == r->e->selected) > - babel_select_route(p, r->e, r); > + babel_announce_rte(p, r->e, r); > } > > static void > @@ -195,9 +195,6 @@ babel_flush_route(struct babel_proto *p UNUSED, struct > babel_route *r) > rem_node(NODE r); > rem_node(&r->neigh_route); > > - if (r->e->selected == r) > - r->e->selected = NULL; > - > sl_free(r); > } > > @@ -213,6 +210,7 @@ babel_expire_route(struct babel_proto *p, struct > babel_route *r) > { > r->metric = r->advert_metric = BABEL_INFINITY; > r->expires = current_time() + cf->hold_time; > + babel_announce_rte(p, r->e, r); > } > else > { > @@ -242,8 +240,6 @@ babel_expire_routes_(struct babel_proto *p, struct fib > *rtable) > loop: > FIB_ITERATE_START(rtable, &fit, struct babel_entry, e) > { > - int changed = 0; > - > WALK_LIST_DELSAFE(r, rx, e->routes) > { > if (r->refresh_time && r->refresh_time <= now_) > @@ -251,23 +247,12 @@ babel_expire_routes_(struct babel_proto *p, struct fib > *rtable) > > if (r->expires && r->expires <= now_) > { > - changed = changed || (r == e->selected); > + FIB_ITERATE_PUT(&fit); > babel_expire_route(p, r); > + goto loop; > } > } > > - if (changed) > - { > - /* > - * We have to restart the iteration because there may be a cascade of > - * synchronous events babel_select_route() -> nest table change -> > - * babel_rt_notify() -> rtable change, invalidating hidden variables. > - */ > - FIB_ITERATE_PUT(&fit); > - babel_select_route(p, e, NULL); > - goto loop; > - } > - > /* Clean up stale entries */ > if ((e->valid == BABEL_ENTRY_STALE) && ((e->updated + cf->hold_time) <= > now_)) > e->valid = BABEL_ENTRY_DUMMY; > @@ -276,7 +261,7 @@ babel_expire_routes_(struct babel_proto *p, struct fib > *rtable) > if (e->unreachable && (!e->valid || (e->router_id == p->router_id))) > { > FIB_ITERATE_PUT(&fit); > - babel_announce_retraction(p, e); > + babel_rte_update_unreachable(p, e, 0); > goto loop; > } > > @@ -461,6 +446,8 @@ babel_get_neighbor(struct babel_iface *ifa, ip_addr addr) > > nbr = mb_allocz(ifa->pool, sizeof(struct babel_neighbor)); > nbr->ifa = ifa; > + nbr->src = rt_get_source(&p->p, idm_alloc(&p->src_ids)); > + rt_lock_source(nbr->src); > nbr->addr = addr; > nbr->rxcost = BABEL_INFINITY; > nbr->txcost = BABEL_INFINITY; > @@ -488,6 +475,9 @@ babel_flush_neighbor(struct babel_proto *p, struct > babel_neighbor *nbr) > } > > nbr->ifa = NULL; > + > + rt_unlock_source(nbr->src); > + idm_free(&p->src_ids, nbr->src->private_id); > rem_node(NODE nbr); > mb_free(nbr); > } > @@ -667,11 +657,60 @@ babel_update_cost(struct babel_neighbor *nbr) > WALK_LIST2(r, n, nbr->routes, neigh_route) > { > r->metric = babel_compute_metric(nbr, r->advert_metric); > - babel_select_route(p, r->e, r); > + babel_announce_rte(p, r->e, r); > } > } > } > > +/** > + * This function handles announcing the special unreachable route we insert > for > + * a prefix whenever we have no more feasible routes available as per RFC8966 > + * section 3.5.4 as well as retracting it when such routes are available > + * again. > + * > + * We also remember if we inserted an unreachable route in e->unreachable in > + * order to clean it up later in babel_expire_routes_. > + */ > +static void > +babel_rte_update_unreachable(struct babel_proto *p, struct babel_entry *e, > u8 announce) > +{ > + struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : > p->ip6_channel; > + > + if (announce) { > + struct nexthop_adata nhad = NEXTHOP_DEST_LITERAL(RTD_UNREACHABLE); > + struct { > + ea_list l; > + eattr a[4]; > + } eattrs = { > + .l.count = ARRAY_SIZE(eattrs.a), > + .a = { > + EA_LITERAL_EMBEDDED(&ea_gen_preference, 0, 1), > + EA_LITERAL_EMBEDDED(&ea_gen_source, 0, RTS_BABEL), > + EA_LITERAL_STORE_ADATA(&ea_gen_nexthop, 0, nhad.ad.data, nhad.ad.length), > + EA_LITERAL_EMBEDDED(&ea_babel_metric, 0, 1), // XXX this one is just for > debugging > + } > + }; > + rte e0 = { > + .attrs = &eattrs.l, > + .src = p->p.main_source, > + }; > + > + e->unreachable = 1; > + rte_update(c, e->n.addr, &e0, p->p.main_source); > + } > + else > + { > + e->unreachable = 0; > + rte_update(c, e->n.addr, NULL, p->p.main_source); > + } > + > + /* Unlike the regular per-neighbour routes we only want one unreachable > route > + * for each prefix. This is mainly due to the lifetime of the unreachable > rte > + * exceeding that of the neighbour's rte_src ID as the babal neighbour may > be > + * flushed before the unreachable route is retracted. */ > + // rte_update(c, e->n.addr, rtee, p->p.main_source); > +} > + > /** > * babel_announce_rte - announce selected route to the core > * @p: Babel protocol instance > @@ -682,12 +721,11 @@ babel_update_cost(struct babel_neighbor *nbr) > * the entry is valid and ours, the unreachable route is announced instead. > */ > static void > -babel_announce_rte(struct babel_proto *p, struct babel_entry *e) > +babel_announce_rte(struct babel_proto *p, struct babel_entry *e, struct > babel_route *r) > { > - struct babel_route *r = e->selected; > struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : > p->ip6_channel; > > - if (r) > + if (r->metric != BABEL_INFINITY && r->feasible) > { > struct nexthop_adata nhad = { > .nh = { > @@ -706,7 +744,7 @@ babel_announce_rte(struct babel_proto *p, struct > babel_entry *e) > */ > if (!neigh_find(&p->p, r->next_hop, r->neigh->ifa->iface, 0)) > nhad.nh.flags = RNF_ONLINK; > - > + > struct { > ea_list l; > eattr a[7]; > @@ -725,124 +763,25 @@ babel_announce_rte(struct babel_proto *p, struct > babel_entry *e) > > rte e0 = { > .attrs = &eattrs.l, > - .src = p->p.main_source, > + .src = r->neigh->src, > }; > > - e->unreachable = 0; > - rte_update(c, e->n.addr, &e0, p->p.main_source); > - } > - else if (e->valid && (e->router_id != p->router_id)) > - { > - /* Unreachable */ > - ea_list *ea = NULL; > - > - ea_set_attr_u32(&ea, &ea_gen_preference, 0, 1); > - ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_BABEL); > - ea_set_dest(&ea, 0, RTD_UNREACHABLE); > - > - rte e0 = { > - .attrs = ea, > - .src = p->p.main_source, > - }; > - > - e->unreachable = 1; > - rte_update(c, e->n.addr, &e0, p->p.main_source); > - } > - else > - { > - /* Retraction */ > - e->unreachable = 0; > - rte_update(c, e->n.addr, NULL, p->p.main_source); > - } > -} > - > -/* Special case of babel_announce_rte() just for retraction */ > -static inline void > -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_update(c, e->n.addr, NULL, p->p.main_source); > -} > - > - > -/** > - * babel_select_route - select best route for given route entry > - * @p: Babel protocol instance > - * @e: Babel entry to select the best route for > - * @mod: Babel route that was modified or NULL if unspecified > - * > - * Select the best reachable and feasible route for a given prefix among the > - * routes received from peers, and propagate it to the nest. This just > selects > - * the reachable and feasible route with the lowest metric, but keeps > selected > - * the old one in case of tie. > - * > - * If no feasible route is available for a prefix that previously had a route > - * selected, a seqno request is sent to try to get a valid route. If the > entry > - * is valid and not owned by us, the unreachable route is announced to the > nest > - * (to blackhole packets going to it, as per section 2.8). It is later > removed > - * by babel_expire_routes(). Otherwise, the route is just removed from the > nest. > - * > - * Argument @mod is used to optimize best route calculation. When specified, > the > - * function can assume that only the @mod route was modified to avoid full > best > - * route selection and announcement when non-best route was modified in minor > - * way. The caller is advised to not call babel_select_route() when no > change is > - * done (e.g. periodic route updates) to avoid unnecessary announcements of > the > - * same best route. The caller is not required to call the function in case > of a > - * retraction of a non-best route. > - * > - * Note that the function does not active triggered updates. That is done by > - * babel_rt_notify() when the change is propagated back to Babel. > - */ > -static void > -babel_select_route(struct babel_proto *p, struct babel_entry *e, struct > babel_route *mod) > -{ > - struct babel_route *r, *best = e->selected; > - > - /* Shortcut if only non-best was modified */ > - if (mod && (mod != best)) > - { > - /* Either select modified route, or keep old best route */ > - if ((mod->metric < (best ? best->metric : BABEL_INFINITY)) && > mod->feasible) > - best = mod; > - else > - return; > + rte_update(c, e->n.addr, &e0, r->neigh->src); > + if (e->unreachable) > + babel_rte_update_unreachable(p, e, 0); > } > else > { > - /* Selected route may be modified and no longer admissible */ > - if (!best || (best->metric == BABEL_INFINITY) || !best->feasible) > - best = NULL; > + if (e->selected == r) > + /* We NULL e->selected here rather than wait for babel_rt_notify in > order > + * to stay in a sync context. This is to be prepared for async > rt_notify > + * in BIRD 3. This is critical as RFC8966 demands unfeasible or > infinite > + * metric routes never being selected (see section 3.6 Route > + * Selection). */ > + e->selected = NULL; > > - /* Find the best feasible route from all routes */ > - WALK_LIST(r, e->routes) > - if ((r->metric < (best ? best->metric : BABEL_INFINITY)) && > r->feasible) > - best = r; > + rte_update(c, e->n.addr, NULL, r->neigh->src); > } > - > - if (best) > - { > - if (best != e->selected) > - TRACE(D_EVENTS, "Picked new route for prefix %N: router-id %lR metric > %d", > - e->n.addr, best->router_id, best->metric); > - } > - else if (e->selected) > - { > - /* > - * We have lost all feasible routes. We have to broadcast seqno request > - * (Section 3.8.2.1) and keep unreachable route for a while (section > 2.8). > - * The later is done automatically by babel_announce_rte(). > - */ > - > - TRACE(D_EVENTS, "Lost feasible route for prefix %N", e->n.addr); > - if (e->valid && (e->selected->router_id == e->router_id)) > - babel_add_seqno_request(p, e, e->selected->router_id, > e->selected->seqno + 1, 0, NULL); > - } > - else > - return; > - > - e->selected = best; > - babel_announce_rte(p, e); > } > > /* > @@ -1414,7 +1353,12 @@ babel_handle_update(union babel_msg *m, struct > babel_iface *ifa) > /* > * RFC 8966 3.8.2.2 - dealing with unfeasible updates. Generate a one-off > * (not retransmitted) unicast seqno request to the originator of this > update. > - * Note: !feasible -> s exists, check for 's' is just for clarity / safety. > + * > + * Notes: > + * - (!feasible) implies (s) is non-NULL, check for (s) is just for > clarity > + * and safety. > + * - (!best) condition is not explicitly recommeded by RFCC8966 text but > was > + * in the old version, RFC6126. > */ > if (!feasible && s && (metric != BABEL_INFINITY) && > (!best || (r == best) || (metric < best->metric))) > @@ -1448,7 +1392,7 @@ babel_handle_update(union babel_msg *m, struct > babel_iface *ifa) > e->updated = current_time(); > } > > - babel_select_route(p, e, r); > + babel_announce_rte(p, e, r); > } > > void > @@ -2136,7 +2080,7 @@ static void > babel_dump_entry(struct dump_request *dreq, struct babel_entry *e) > { > struct babel_source *s; > - struct babel_route *r; > + struct babel_route *r, *best = e->selected; > > RDUMP("Babel: Entry %N:\n", e->n.addr); > > @@ -2146,7 +2090,7 @@ babel_dump_entry(struct dump_request *dreq, struct > babel_entry *e) > WALK_LIST(r,e->routes) > { > RDUMP(" "); > - if (r == e->selected) RDUMP("*"); > + if (r == best) RDUMP("*"); > babel_dump_route(dreq, r); > } > } > @@ -2324,7 +2268,7 @@ babel_show_entries_(struct babel_proto *p, struct fib > *rtable) > > FIB_WALK(rtable, struct babel_entry, e) > { > - struct babel_route *r = NULL; > + struct babel_route *r = NULL, *best = e->selected; > uint rts = 0, srcs = 0; > node *n; > > @@ -2337,7 +2281,7 @@ babel_show_entries_(struct babel_proto *p, struct fib > *rtable) > if (e->valid) > cli_msg(-1025, "%-*N %-23lR %6u %5u %7u %7u", width, > e->n.addr, e->router_id, e->metric, e->seqno, rts, srcs); > - else if (r = e->selected) > + else if (r = best) > cli_msg(-1025, "%-*N %-23lR %6u %5u %7u %7u", width, > e->n.addr, r->router_id, r->metric, r->seqno, rts, srcs); > else > @@ -2374,10 +2318,10 @@ babel_show_routes_(struct babel_proto *p, struct fib > *rtable) > > FIB_WALK(rtable, struct babel_entry, e) > { > - struct babel_route *r; > + struct babel_route *r, *best = e->selected; > WALK_LIST(r, e->routes) > { > - char c = (r == e->selected) ? '*' : (r->feasible ? '+' : ' '); > + char c = (r == best) ? '*' : (r->feasible ? '+' : ' '); > btime time = r->expires ? r->expires - current_time() : 0; > cli_msg(-1025, "%-*N %-25I %-10s %5u %c %5u %7t", width, > e->n.addr, r->next_hop, r->neigh->ifa->ifname, > @@ -2466,8 +2410,9 @@ babel_entry_invalidate(struct babel_entry *e) > > > /* > - * babel_rt_notify - core tells us about new route (possibly our own), > - * so store it into our data structures. > + * babel_rt_notify - BIRD core notifis us of changes in the selected optimal > + * route. We can either get one of the routes back we exported or one from a > + * different protocol. > */ > static void > babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr > *net, > @@ -2475,6 +2420,8 @@ babel_rt_notify(struct proto *P, struct channel *c > UNUSED, const net_addr *net, > { > struct babel_proto *p = (void *) P; > struct babel_entry *e; > + struct babel_iface *ifa; > + struct babel_neighbor *n; > > /* Ignore everything on shutdown */ > if (SHUTTING_DOWN) > @@ -2483,11 +2430,13 @@ babel_rt_notify(struct proto *P, struct channel *c > UNUSED, const net_addr *net, > if (new) > { > /* Update */ > + uint internal = new->src->owner == &P->sources; > uint rt_seqno; > uint rt_metric = ea_get_int(new->attrs, &ea_babel_metric, 0); > u64 rt_router_id = 0; > + struct babel_route *best; > > - if (new->src->owner == &P->sources) > + if (internal) > { > rt_seqno = ea_get_int(new->attrs, &ea_babel_seqno, 0); > eattr *e = ea_find(new->attrs, &ea_babel_router_id); > @@ -2496,6 +2445,8 @@ babel_rt_notify(struct proto *P, struct channel *c > UNUSED, const net_addr *net, > } > else > { > + /* If the selected route isn't one of ours we inject a new route into > the > + * babel domain as per RFC8966 section 3.7 */ > rt_seqno = p->update_seqno; > rt_router_id = p->router_id; > } > @@ -2509,6 +2460,29 @@ babel_rt_notify(struct proto *P, struct channel *c > UNUSED, const net_addr *net, > > e = babel_get_entry(p, net); > > + best = e->selected; > + if (internal) { > + eattr *ea = ea_find(new->attrs, &ea_gen_nexthop); > + struct nexthop_adata *nhad = (void *) ea->u.ptr; > + ifa = babel_find_iface(p, nhad->nh.iface); > + n = ifa ? babel_find_neighbor(ifa, ea_get_ip(new->attrs, &ea_gen_from, > IPA_NONE)) : NULL; > + best = n ? babel_get_route(p, e, n) : NULL; > + ASSERT(best); /* Note: We think this can't happen but the lifetimes of > the > + * involved objects are complicated so we're not yet > + * completely convinced. */ > + } > + else > + { > + best = NULL; > + } > + > + if (best && best != e->selected) > + TRACE(D_EVENTS, > + "Picked new route for prefix %N: router-id %lR metric %d", > + e->n.addr, best->router_id, best->metric); > + > + e->selected = best; > + > /* Activate triggered updates */ > if (!(e->valid & BABEL_ENTRY_VALID) || > (e->router_id != rt_router_id)) > @@ -2530,6 +2504,27 @@ babel_rt_notify(struct proto *P, struct channel *c > UNUSED, const net_addr *net, > if (!e || e->valid != BABEL_ENTRY_VALID) > return; > > + if (e->selected) { > + TRACE(D_EVENTS, "Lost all feasible routes for prefix %N", e->n.addr); > + /* We had a feasible route, but now it's gone. We must send a seqno > + * request (Section 3.8.2.1). As allowed by RFC8966 we choose to > always do > + * so even if we don't have any more unfeasible routes and we use the > + * simple unconditional multicast strategy. > + */ > + if (e->valid && (e->selected->router_id == e->router_id)) > + babel_add_seqno_request( > + p, e, e->selected->router_id, e->selected->seqno + 1, 0, NULL); > + } > + > + > + e->valid = BABEL_ENTRY_STALE; > + e->metric = BABEL_INFINITY; > + e->selected = NULL; > + > + /* Install an unreachable route for prefix hold time as per RFC8966 > section > + * 3.5.4. */ > + babel_rte_update_unreachable(p, e, 1); > + > babel_entry_invalidate(e); > babel_trigger_update(p); > } > @@ -2626,6 +2621,7 @@ babel_start(struct proto *P) > p->source_slab = sl_new(P->pool, sizeof(struct babel_source)); > p->msg_slab = sl_new(P->pool, sizeof(struct babel_msg_node)); > p->seqno_slab = sl_new(P->pool, sizeof(struct babel_seqno_request)); > + idm_init(&p->src_ids, P->pool, 8); > > p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 }; > > diff --git a/proto/babel/babel.h b/proto/babel/babel.h > index 146179cda..0699a2974 100644 > --- a/proto/babel/babel.h > +++ b/proto/babel/babel.h > @@ -25,6 +25,7 @@ > #include "lib/socket.h" > #include "lib/string.h" > #include "lib/timer.h" > +#include "lib/idm.h" > > #define BABEL_MAGIC 42 > #define BABEL_VERSION 2 > @@ -193,6 +194,7 @@ struct babel_proto { > slab *source_slab; > slab *msg_slab; > slab *seqno_slab; > + struct idm src_ids; > > struct tbf log_pkt_tbf; /* TBF for packet messages */ > }; > @@ -235,6 +237,7 @@ struct babel_iface { > struct babel_neighbor { > node n; > struct babel_iface *ifa; > + struct rte_src *src; > > ip_addr addr; > u16 rxcost; /* Sent in last IHU */ --Daniel
