From b58ebc4ef18f9e4a77e466a218f61eeaadb8ecb4 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Wed, 27 Sep 2023 16:47:25 +0200 Subject: [PATCH] Babel: Properly handle route refeed --- proto/babel/babel.c | 53 ++++++++++++++++++++++++++++++++++++++++----- proto/babel/babel.h | 1 + 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 27ec4784..b49c6b3b 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -2361,6 +2361,15 @@ babel_preexport(struct channel *C, struct rte *new) return 0; } +static void +babel_entry_invalidate(struct babel_entry *e) +{ + e->valid = BABEL_ENTRY_STALE; + e->metric = BABEL_INFINITY; + e->updated = current_time(); +} + + /* * babel_rt_notify - core tells us about new route (possibly our own), * so store it into our data structures. @@ -2402,7 +2411,7 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net, e = babel_get_entry(p, net); /* Activate triggered updates */ - if ((e->valid != BABEL_ENTRY_VALID) || + if (!(e->valid & BABEL_ENTRY_VALID) || (e->router_id != rt_router_id)) { babel_trigger_update(p); @@ -2422,14 +2431,46 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net, if (!e || e->valid != BABEL_ENTRY_VALID) return; - e->valid = BABEL_ENTRY_STALE; - e->metric = BABEL_INFINITY; - + babel_entry_invalidate(e); babel_trigger_update(p); - e->updated = current_time(); } } +static void +babel_feed_begin(struct channel *C, int initial) +{ + if (initial) + return; + + struct babel_proto *p = (struct babel_proto *) C->proto; + struct fib *rtable = (C->net_type == NET_IP4) ? &p->ip4_rtable : &p->ip6_rtable; + + FIB_WALK(rtable, struct babel_entry, e) + if (e->valid == BABEL_ENTRY_VALID) + e->valid = BABEL_ENTRY_REFEEDING; + FIB_WALK_END; +} + +static void +babel_feed_end(struct channel *C) +{ + struct babel_proto *p = (struct babel_proto *) C->proto; + struct fib *rtable = (C->net_type == NET_IP4) ? &p->ip4_rtable : &p->ip6_rtable; + int changed = 0; + + FIB_WALK(rtable, struct babel_entry, e) + if (e->valid == BABEL_ENTRY_REFEEDING) + { + babel_entry_invalidate(e); + changed++; + } + FIB_WALK_END; + + if (changed) + babel_trigger_update(p); +} + + static int babel_rte_better(const rte *new, const rte *old) { @@ -2482,6 +2523,8 @@ babel_init(struct proto_config *CF) P->iface_sub.if_notify = babel_if_notify; P->rt_notify = babel_rt_notify; P->preexport = babel_preexport; + P->feed_begin = babel_feed_begin; + P->feed_end = babel_feed_end; P->sources.class = &babel_rte_owner_class; diff --git a/proto/babel/babel.h b/proto/babel/babel.h index 562abac2..2aa1ed6b 100644 --- a/proto/babel/babel.h +++ b/proto/babel/babel.h @@ -299,6 +299,7 @@ struct babel_entry { #define BABEL_ENTRY_DUMMY 0 /* No outgoing route */ #define BABEL_ENTRY_VALID 1 /* Valid outgoing route */ #define BABEL_ENTRY_STALE 2 /* Stale outgoing route, waiting for GC */ +#define BABEL_ENTRY_REFEEDING 3 /* Route valid until feed ends */ /*