From 48dd28ce97211b23476935d83f9bd4551383a1cb Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Mon, 28 Jul 2025 14:08:26 +0200 Subject: [PATCH] WIP checker --- nest/protocol.h | 3 + nest/rt-table.c | 183 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 136 insertions(+), 50 deletions(-) diff --git a/nest/protocol.h b/nest/protocol.h index f5d8a7571..5d60a38ab 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -490,6 +490,7 @@ extern struct ea_class ea_name, ea_protocol_name, ea_protocol_type, #define D_IFACES 8 /* [core] Interface events */ #define D_EVENTS 16 /* Protocol events */ #define D_PACKETS 32 /* Packets sent/received */ +#define D_ROUTES_DETAILED 64 /* Routes and filters but very detailed */ #ifndef PARSER #define TRACE(flags, msg, args...) \ @@ -624,6 +625,8 @@ struct channel { struct bmap imported_map; /* Which nets were touched by our import */ struct bmap export_accepted_map; /* Keeps track which routes were really exported */ struct bmap export_rejected_map; /* Keeps track which routes were rejected by export filter */ + event export_consistency_event; /* Clears the export_log and checks the consistency + of export_rejected_map and export_accepted_map */ struct limit rx_limit; /* Receive limit (for in_keep & RIK_REJECTED) */ struct limit in_limit; /* Input limit */ diff --git a/nest/rt-table.c b/nest/rt-table.c index 6383f2fe0..a71b0e27b 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -976,9 +976,9 @@ rte_mergable(const rte *pri, const rte *sec) } static void -rte_trace(const char *name, const rte *e, int dir, const char *msg) +rte_trace(const char *name, const rte *e, const char *dir, const char *msg) { - log(L_TRACE "%s %c %s %N ptr %p (%u) src %luL %uG %uS id %u %s", + log(L_TRACE "%s %s %s %N ptr %p (%u) src %luL %uG %uS id %u %s", name, dir, msg, e->net, e, NET_TO_INDEX(e->net)->index, e->src->private_id, e->src->global_id, e->stale_cycle, e->id, rta_dest_name(rte_dest(e))); @@ -998,14 +998,14 @@ static inline void channel_rte_trace_out(uint flag, struct channel *c, const rte *e, const char *msg) { if ((c->debug & flag) || (c->proto->debug & flag)) - rte_trace(c->out_req.name, e, '<', msg); + rte_trace(c->out_req.name, e, "<", msg); } static inline void rt_rte_trace_in(uint flag, struct rt_import_request *req, const rte *e, const char *msg) { if (req->trace_routes & flag) - rte_trace(req->name, e, '>', msg); + rte_trace(req->name, e, ">", msg); } #if 0 @@ -1014,10 +1014,98 @@ static inline void rt_rte_trace_out(uint flag, struct rt_export_request *req, const rte *e, const char *msg) { if (req->trace_routes & flag) - rte_trace(req->name, e, '<', msg); + rte_trace(req->name, e, "<", msg); } #endif +#if 0 +#define RT_NOTIFY_DEBUG(fmt...) log(L_TRACE "rt_notify_accepted: " fmt, ##fmt) +#else +#define RT_NOTIFY_DEBUG(...) +#endif + +struct channel_export_log { + struct channel_export_log *next; + uint cur; + uint last; + struct channel_export_log_item { + u32 rt_id; /* Route id */ + u32 net_id; /* Network in-table id */ + enum { + CELI_F_ACCEPT = 2, /* Set = accepted_map, clear = rejected_map */ + CELI_F_SET = 4, /* Set = bmap_set, clear = bmap_clear */ + CELI_F_TEST = 8, /* Set = bmap_test -> CELI_F_SET shows result */ + } flags; + } item[0]; +}; + +static inline void +channel_rte_mark_trace(struct channel *c, const rte *e, const char *reason, const char *msg) +{ + if ((c->debug & D_ROUTES_DETAILED) || (c->proto->debug & D_ROUTES_DETAILED)) + rte_trace(c->out_req.name, e, reason, msg); +} + +static inline void +channel_rte_mark_rejected(struct channel *c, const rte *e, const char *msg) +{ + bmap_set(&c->export_rejected_map, e->id); + channel_rte_mark_trace(c, e, "export_accepted_map, e->id)); +} + +static inline void +channel_rte_mark_accepted(struct channel *c, const rte *e, const char *msg) +{ + bmap_set(&c->export_accepted_map, e->id); + channel_rte_mark_trace(c, e, "export_rejected_map, e->id)); +} + +static inline void +channel_rte_clear_rejected(struct channel *c, const rte *e, const char *msg) +{ + bmap_clear(&c->export_rejected_map, e->id); + channel_rte_mark_trace(c, e, "export_accepted_map, e->id)); +} + +static inline void +channel_rte_clear_accepted(struct channel *c, const rte *e, const char *msg) +{ + bmap_clear(&c->export_accepted_map, e->id); + channel_rte_mark_trace(c, e, "export_rejected_map, e->id)); +} + +static inline bool +channel_rte_check_rejected(struct channel *c, const rte *e, const char *msg) +{ + bool out = bmap_test(&c->export_rejected_map, e->id); + if (out) + { + channel_rte_mark_trace(c, e, "export_accepted_map, e->id)); + } + else + channel_rte_mark_trace(c, e, "export_accepted_map, e->id); + if (out) + { + channel_rte_mark_trace(c, e, "export_rejected_map, e->id)); + } + else + channel_rte_mark_trace(c, e, "export_stats; /* Do nothing if we have already rejected the route */ - if (silent && bmap_test(&c->export_rejected_map, rt->id)) + if (silent && channel_rte_check_rejected(c, rt, "silent filter")) goto reject_noset; int v = p->preexport ? p->preexport(c, rt) : 0; @@ -1108,12 +1196,12 @@ export_filter(struct channel *c, rte *rt, int silent) accept: /* We have accepted the route */ - bmap_clear(&c->export_rejected_map, rt->id); + channel_rte_clear_rejected(c, rt, "filter"); return rt; reject: /* We have rejected the route by filter */ - bmap_set(&c->export_rejected_map, rt->id); + channel_rte_mark_rejected(c, rt, "filter"); reject_noset: /* Discard temporary rte */ @@ -1145,10 +1233,10 @@ do_rt_notify(struct channel *c, const net_addr *net, rte *new, const rte *old) stats->withdraws_accepted++; if (old) - bmap_clear(&c->export_accepted_map, old->id); + channel_rte_clear_accepted(c, old, "old"); if (new) - bmap_set(&c->export_accepted_map, new->id); + channel_rte_mark_accepted(c, new, "new"); if (new && old) channel_rte_trace_out(D_ROUTES, c, new, "replaced"); @@ -1164,20 +1252,28 @@ static void rt_notify_basic(struct channel *c, const rte *new, const rte *old) { const rte *trte = new ?: old; + bool orej = 0, oacc = 0; /* Have we exported the old route? */ if (old) { /* If the old route exists, it is either in rejected or in accepted map. */ - int rejected = bmap_test(&c->export_rejected_map, old->id); - int accepted = bmap_test(&c->export_accepted_map, old->id); - ASSERT_DIE(!rejected || !accepted); - - if (!accepted) + orej = channel_rte_check_rejected(c, old, "old-basic"); + oacc = channel_rte_check_accepted(c, old, "old-basic"); + ASSERT_DIE(!orej || !oacc); + + /* Is this a same-route refeed? Unmark to let it be marked again. */ + if (old == new) + if (orej) + channel_rte_clear_rejected(c, old, "refeed"); + else if (oacc) + channel_rte_clear_accepted(c, old, "refeed"); + + if (!oacc) { /* Drop the old rejected bit from the map, the old route id * gets released after exports. */ - bmap_clear(&c->export_rejected_map, old->id); + channel_rte_clear_rejected(c, old, "old-basic"); /* Treat old rejected as never seen. */ old = NULL; @@ -1206,12 +1302,6 @@ rt_notify_basic(struct channel *c, const rte *new, const rte *old) do_rt_notify(c, np ? np->net : old->net, np, old); } -#if 0 -#define RT_NOTIFY_DEBUG(fmt...) log(L_TRACE "rt_notify_accepted: " fmt, ##fmt) -#else -#define RT_NOTIFY_DEBUG(...) -#endif - static void rt_notify_accepted(struct channel *c, const struct rt_export_feed *feed) { @@ -1226,7 +1316,7 @@ rt_notify_accepted(struct channel *c, const struct rt_export_feed *feed) rte *r = &feed->block[i]; /* Previously exported */ - if (!old_best && bmap_test(&c->export_accepted_map, r->id)) + if (!old_best && channel_rte_check_accepted(c, r, "accepted")) { RT_NOTIFY_DEBUG("route %u id %u previously exported, is old best", i, r->id); old_best = r; @@ -1246,20 +1336,14 @@ rt_notify_accepted(struct channel *c, const struct rt_export_feed *feed) /* Unflag obsolete routes */ else if (r->flags & REF_OBSOLETE) - { - RT_NOTIFY_DEBUG("route %u id %u is obsolete", i, r->id); - bmap_clear(&c->export_rejected_map, r->id); - } + channel_rte_clear_rejected(c, r, "obsolete"); /* Mark invalid as rejected */ else if (!rte_is_valid(r)) - { - RT_NOTIFY_DEBUG("route %u id %u is invalid", i, r->id); - bmap_set(&c->export_rejected_map, r->id); - } + channel_rte_mark_rejected(c, r, "invalid"); /* Already rejected */ - else if (!feeding && bmap_test(&c->export_rejected_map, r->id)) + else if (!feeding && channel_rte_check_rejected(c, r, "accepted")) RT_NOTIFY_DEBUG("route %u id %u has been rejected before", i, r->id); /* No new best route yet and this is a valid candidate */ @@ -1341,7 +1425,7 @@ rt_export_merged(struct channel *c, const struct rt_export_feed *feed, linpool * return NULL; /* Already rejected, no need to re-run the filter */ - if (!feeding && bmap_test(&c->export_rejected_map, best0->id)) + if (!feeding && channel_rte_check_rejected(c, best0, "merged-best0")) return NULL; best = export_filter(c, best0, silent); @@ -1367,7 +1451,7 @@ rt_export_merged(struct channel *c, const struct rt_export_feed *feed, linpool * continue; /* Already rejected by filters */ - if (!feeding && bmap_test(&c->export_rejected_map, r->id)) + if (!feeding && channel_rte_check_rejected(c, r, "merged")) continue; /* Running export filter on new or accepted route */ @@ -1408,7 +1492,7 @@ rt_notify_merged(struct channel *c, const struct rt_export_feed *f) const rte *old_best = NULL; /* Find old best route */ for (uint i = 0; i < f->count_routes; i++) - if (bmap_test(&c->export_accepted_map, f->block[i].id)) + if (channel_rte_check_accepted(c, &f->block[i], "merged")) { old_best = &f->block[i]; break; @@ -1484,6 +1568,7 @@ channel_notify_basic(void *_channel) rte *new = &u->feed->block[i]; rte *old = NULL; + /* First check old routes */ for (uint o = oldpos; o < u->feed->count_routes; o++) if ((c->ra_mode == RA_ANY) && (new->src == u->feed->block[o].src)) { @@ -1497,8 +1582,8 @@ channel_notify_basic(void *_channel) if (old && (u->feed->block[o].id == old->id)) u->feed->block[o].src = NULL; else if ( - bmap_test(&c->export_accepted_map, u->feed->block[o].id) || - bmap_test(&c->export_rejected_map, u->feed->block[o].id) + channel_rte_check_accepted(c, &u->feed->block[o], "old-basic-ff") || + channel_rte_check_rejected(c, &u->feed->block[o], "old-basic-ff") ) { /* But we expect that there was only one route previously exported */ @@ -1507,8 +1592,8 @@ channel_notify_basic(void *_channel) } /* Check new flags */ - int nacc = bmap_test(&c->export_accepted_map, new->id); - int nrej = bmap_test(&c->export_rejected_map, new->id); + int nacc = channel_rte_check_accepted(c, new, "new-basic"); + int nrej = channel_rte_check_rejected(c, new, "new-basic"); if (old) ASSERT_DIE(!nacc && !nrej); @@ -1533,8 +1618,8 @@ channel_notify_basic(void *_channel) /* Send withdraws */ for (uint o = oldpos; o < u->feed->count_routes; o++) if (u->feed->block[o].src && ( - bmap_test(&c->export_accepted_map, u->feed->block[o].id) || - bmap_test(&c->export_rejected_map, u->feed->block[o].id) + channel_rte_check_accepted(c, &u->feed->block[o], "old-basic-fw") || + channel_rte_check_rejected(c, &u->feed->block[o], "old-basic-fw") )) { if (c->ra_mode == RA_OPTIMAL) @@ -1593,17 +1678,15 @@ channel_notify_basic(void *_channel) channel_rte_trace_out(D_ROUTES, c, new, "already exported"); if (new->id != old->id) - if (bmap_test(&c->export_accepted_map, old->id)) + if (channel_rte_check_accepted(c, old, "same")) { - bmap_set(&c->export_accepted_map, new->id); - bmap_clear(&c->export_accepted_map, old->id); - - ASSERT_DIE(!bmap_test(&c->export_rejected_map, old->id)); + channel_rte_mark_accepted(c, new, "same"); + channel_rte_clear_accepted(c, new, "same"); } - else if (bmap_test(&c->export_rejected_map, old->id)) + else if (channel_rte_check_rejected(c, old, "same")) { - bmap_set(&c->export_rejected_map, new->id); - bmap_clear(&c->export_rejected_map, old->id); + channel_rte_mark_rejected(c, new, "same"); + channel_rte_clear_rejected(c, new, "same"); } else bug("Withdrawn route never seen before"); @@ -5416,7 +5499,7 @@ krt_export_net(struct channel *c, const net_addr *a, linpool *lp) if (!feed || !feed->count_routes) return NULL; - if (!bmap_test(&c->export_accepted_map, feed->block[0].id)) + if (!channel_rte_check_accepted(c, &feed->block[0], "krt_export")) return NULL; return rt_export_merged(c, feed, lp, 1); -- 2.47.2