From: Maria Matejka Date: Tue, 29 Jul 2025 09:13:14 +0000 (+0200) Subject: fixup! WIP checker X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2F281-mq-checker;p=thirdparty%2Fbird.git fixup! WIP checker --- diff --git a/nest/protocol.h b/nest/protocol.h index 5d60a38ab..3199f9fa4 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -627,6 +627,7 @@ struct channel { 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 channel_export_log *export_log;/* Keeps track what happened since last export_consistency_event */ 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 a71b0e27b..fa54dfe7e 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1025,57 +1025,124 @@ rt_rte_trace_out(uint flag, struct rt_export_request *req, const rte *e, const c #endif struct channel_export_log { - struct channel_export_log *next; + struct channel_export_log *prev; uint cur; - uint last; + uint total; 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 */ + const char *msg; /* Message */ + enum channel_export_log_flags { + CELI_F_ACCEPT = 1, /* Set = accepted_map, clear = rejected_map */ + CELI_F_SET = 2, /* Set = bmap_set, clear = bmap_clear */ + CELI_F_TEST = 4, /* Set = bmap_test -> CELI_F_SET shows result */ } flags; } item[0]; }; +static const char *channel_export_log_flags_str[] = { + "debug & D_ROUTES_DETAILED) || (c->proto->debug & D_ROUTES_DETAILED)) - rte_trace(c->out_req.name, e, reason, msg); + rte_trace(c->out_req.name, e, channel_export_log_flags_str[flags], msg); + + struct channel_export_log *cel = c->export_log; + if (!cel || (cel->cur == cel->total)) + { + cel = alloc_page(); + cel->prev = c->export_log; + cel->cur = 0; + cel->total = (page_size - sizeof *cel) / sizeof cel->item[0]; + ASSERT_DIE(cel->total > 0); + ASSERT_DIE((void *) cel + page_size > (void *)(&cel->item[cel->total - 1])); + ASSERT_DIE((void *) cel + page_size <= (void *)(&cel->item[cel->total])); + + c->export_log = cel; + } + + cel->item[cel->cur++] = (struct channel_export_log_item) { + .rt_id = e->id, + .net_id = NET_TO_INDEX(e->net)->index, + .msg = msg, + .flags = flags, + }; +} + +static inline void +channel_rte_assert_dump(struct channel *c) +{ + uint count = 0; + for (struct channel_export_log *cel = c->export_log; cel; cel = cel->prev) + count++; + + struct channel_export_log **celb = mb_allocz(c->proto->pool, count * sizeof *celb); + + uint pos = count-1; + for (struct channel_export_log *cel = c->export_log; cel; cel = cel->prev) + celb[pos--] = cel; + + for (uint pos = 0; pos < count; pos++) + for (uint i = 0; i < celb[pos]->cur; i++) + log(L_BUG "%s: net %u rte %u %s %s", + c->out_req.name, celb[pos]->item[i].net_id, celb[pos]->item[i].rt_id, + channel_export_log_flags_str[celb[pos]->item[i].flags], celb[pos]->item[i].msg); +} + +static inline void +channel_rte_assert_rejected(struct channel *c, const rte *e, bool expected) +{ + if (bmap_test(&c->export_rejected_map, e->id) == expected) + return; + + channel_rte_assert_dump(c); + bug("Expected route %d should %sbe in the rejected map", e->id, expected ? "" : "not "); +} + +static inline void +channel_rte_assert_accepted(struct channel *c, const rte *e, bool expected) +{ + if (bmap_test(&c->export_accepted_map, e->id) == expected) + return; + + channel_rte_assert_dump(c); + bug("Expected route %d should %sbe in the accepted map", e->id, expected ? "" : "not "); } 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)); + channel_rte_mark_trace(c, e, CELI_F_SET, msg); + channel_rte_assert_accepted(c, e, false); } 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)); + channel_rte_mark_trace(c, e, CELI_F_SET | CELI_F_ACCEPT, msg); + channel_rte_assert_rejected(c, e, false); } 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)); + channel_rte_mark_trace(c, e, 0, msg); + channel_rte_assert_accepted(c, e, false); } 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)); + channel_rte_mark_trace(c, e, CELI_F_ACCEPT, msg); + channel_rte_assert_rejected(c, e, false); } static inline bool @@ -1084,25 +1151,34 @@ 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)); + channel_rte_mark_trace(c, e, CELI_F_TEST | CELI_F_SET, msg); + channel_rte_assert_accepted(c, e, false); } 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)); + channel_rte_mark_trace(c, e, CELI_F_TEST | CELI_F_SET | CELI_F_ACCEPT, msg); + channel_rte_assert_rejected(c, e, false); } else - channel_rte_mark_trace(c, e, "preexport ? p->preexport(c, rt) : 0; if (v < 0) { @@ -1196,7 +1283,8 @@ export_filter(struct channel *c, rte *rt, int silent) accept: /* We have accepted the route */ - channel_rte_clear_rejected(c, rt, "filter"); + if (!channel_rte_check_accepted(c, rt, "filter")) + channel_rte_clear_rejected(c, rt, "filter"); return rt; reject: @@ -1232,9 +1320,6 @@ do_rt_notify(struct channel *c, const net_addr *net, rte *new, const rte *old) else stats->withdraws_accepted++; - if (old) - channel_rte_clear_accepted(c, old, "old"); - if (new) channel_rte_mark_accepted(c, new, "new"); @@ -1262,24 +1347,12 @@ rt_notify_basic(struct channel *c, const rte *new, const rte *old) 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"); + /* Remove the flags, they are no longer needed */ + channel_rte_clear_both(c, old, "old-basic"); + /* Treat old rejected as never seen. */ if (!oacc) - { - /* Drop the old rejected bit from the map, the old route id - * gets released after exports. */ - channel_rte_clear_rejected(c, old, "old-basic"); - - /* Treat old rejected as never seen. */ old = NULL; - } - - /* Accepted bit is dropped in do_rt_notify() */ } /* Run the filters for the new route */ @@ -1336,14 +1409,14 @@ rt_notify_accepted(struct channel *c, const struct rt_export_feed *feed) /* Unflag obsolete routes */ else if (r->flags & REF_OBSOLETE) - channel_rte_clear_rejected(c, r, "obsolete"); + channel_rte_clear_both(c, r, "obsolete-sec"); /* Mark invalid as rejected */ else if (!rte_is_valid(r)) - channel_rte_mark_rejected(c, r, "invalid"); + channel_rte_mark_rejected(c, r, "invalid-sec"); /* Already rejected */ - else if (!feeding && channel_rte_check_rejected(c, r, "accepted")) + else if (!feeding && channel_rte_check_rejected(c, r, "sec")) 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 */ @@ -1492,11 +1565,15 @@ 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 (channel_rte_check_accepted(c, &f->block[i], "merged")) - { - old_best = &f->block[i]; - break; - } + if (!old_best) + old_best = &f->block[i]; + else + bug("Two old_best routes in the same dump"); + if (f->block[i].flags & REF_OBSOLETE) + channel_rte_clear_both(c, &f->block[i], "obsolete-merged"); + } /* Prepare new merged route */ rte *new_merged = f->count_routes ? rt_export_merged(c, f, tmp_linpool, 0) : NULL; @@ -1617,13 +1694,12 @@ channel_notify_basic(void *_channel) /* Send withdraws */ for (uint o = oldpos; o < u->feed->count_routes; o++) - if (u->feed->block[o].src && ( - 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 (u->feed->block[o].src && channel_rte_check_accepted(c, &u->feed->block[o], "old-basic-fw")) { if (c->ra_mode == RA_OPTIMAL) ASSERT_DIE(notify_count == 0); + else + ASSERT_DIE(u->feed->block[o].flags & REF_OBSOLETE); rt_notify_basic(c, NULL, &u->feed->block[o]); notify_count++;