From bf84daca8c83a28e2227c73a36cb41e49189148a Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Wed, 27 Sep 2023 16:29:44 +0200 Subject: [PATCH] RIP: Properly handle route refeed --- proto/rip/rip.c | 60 ++++++++++++++++++++++++++++++++++++++++++------- proto/rip/rip.h | 1 + 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/proto/rip/rip.c b/proto/rip/rip.c index dded05c71..9e6eed121 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -328,6 +328,17 @@ rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from) rip_announce_rte(p, en); } +static void +rip_withdraw_entry(struct rip_proto *p, struct rip_entry *en) +{ + en->valid = RIP_ENTRY_STALE; + en->metric = p->infinity; + en->tag = 0; + en->from = NULL; + en->iface = NULL; + en->next_hop = IPA_NONE; +} + /* * rip_rt_notify - core tells us about new route, so store * it into our data structures. @@ -392,17 +403,11 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, s /* Withdraw */ en = fib_find(&p->rtable, net); - if (!en || en->valid != RIP_ENTRY_VALID) + if (!en || !(en->valid & RIP_ENTRY_VALID)) return; old_metric = en->metric; - - en->valid = RIP_ENTRY_STALE; - en->metric = p->infinity; - en->tag = 0; - en->from = NULL; - en->iface = NULL; - en->next_hop = IPA_NONE; + rip_withdraw_entry(p, en); } /* Activate triggered updates */ @@ -413,6 +418,43 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, s } } +void +rip_feed_begin(struct channel *C, int initial) +{ + if (initial) + return; + + struct rip_proto *p = (struct rip_proto *) C->proto; + + FIB_WALK(&p->rtable, struct rip_entry, en) + { + if (en->valid == RIP_ENTRY_VALID) + en->valid = RIP_ENTRY_REFEEDING; + } + FIB_WALK_END; +} + +void +rip_feed_end(struct channel *C) +{ + struct rip_proto *p = (struct rip_proto *) C->proto; + int changed = 0; + + FIB_WALK(&p->rtable, struct rip_entry, en) + { + if (en->valid == RIP_ENTRY_REFEEDING) + { + rip_withdraw_entry(p, en); + changed++; + } + } + FIB_WALK_END; + + if (changed) + rip_trigger_update(p); +} + + void rip_flush_table(struct rip_proto *p, struct rip_neighbor *n) { @@ -1159,6 +1201,8 @@ rip_init(struct proto_config *CF) P->iface_sub.neigh_notify = rip_neigh_notify; P->reload_routes = rip_reload_routes; P->sources.class = &rip_rte_owner_class; + P->feed_begin = rip_feed_begin; + P->feed_end = rip_feed_end; return P; } diff --git a/proto/rip/rip.h b/proto/rip/rip.h index a01f8d3b4..6d70df465 100644 --- a/proto/rip/rip.h +++ b/proto/rip/rip.h @@ -194,6 +194,7 @@ struct rip_rte #define RIP_ENTRY_DUMMY 0 /* Only used to store list of incoming routes */ #define RIP_ENTRY_VALID 1 /* Valid outgoing route */ #define RIP_ENTRY_STALE 2 /* Stale outgoing route, waiting for GC */ +#define RIP_ENTRY_REFEEDING 3 /* Route valid until feed ends */ static inline int rip_is_v2(struct rip_proto *p) { return p->rip2; } -- 2.47.2