]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Babel: Properly handle route refeed
authorMaria Matejka <mq@ucw.cz>
Wed, 27 Sep 2023 14:47:25 +0000 (16:47 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 27 Sep 2023 15:40:40 +0000 (17:40 +0200)
proto/babel/babel.c
proto/babel/babel.h

index 27ec478471b6136c2b1b55e9503aef57a6fd4c19..b49c6b3b732567d1574479f53f852b5118b4faec 100644 (file)
@@ -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;
 
index 562abac2cfb5a6e59f67e9c2b5e4c896ba17eb1e..2aa1ed6b38961753deaaee667f0c1c3d63154b80 100644 (file)
@@ -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 */
 
 
 /*