diff --git a/nest/proto.c b/nest/proto.c index 81d1e924..2bb0766e 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -108,8 +108,6 @@ void channel_request_full_refeed(struct channel *c) { rt_export_refeed(&c->out_req, NULL); - bmap_reset(&c->export_accepted_map, 16); - bmap_reset(&c->export_rejected_map, 16); } static void diff --git a/nest/route.h b/nest/route.h index 3b56ccb6..72089929 100644 --- a/nest/route.h +++ b/nest/route.h @@ -331,9 +331,21 @@ static inline bool rt_net_is_feeding_request(struct rt_export_request *req, const net_addr *n) { struct netindex *ni = NET_TO_INDEX(n); - return - !bmap_test(&req->feed_map, ni->index) - && rt_net_is_feeding_feeder(&req->feeder, n); + switch (rt_export_get_state(req)) + { + case TES_PARTIAL: + case TES_FEEDING: + break; + + default: + return 0; + } + + /* Already fed */ + if (bmap_test(&req->feed_map, ni->index)) + return 0; + + return rt_net_is_feeding_feeder(&req->feeder, n); } #define rt_net_is_feeding(h, n) _Generic((h), \ diff --git a/nest/rt-export.c b/nest/rt-export.c index e7cfeab8..a1d17a39 100644 --- a/nest/rt-export.c +++ b/nest/rt-export.c @@ -103,9 +103,7 @@ rt_export_get(struct rt_export_request *r) else if (feed = rt_export_next_feed(&r->feeder)) { /* Feeding more */ - bmap_set(&r->feed_map, feed->ni->index); rtex_trace(r, D_ROUTES, "Feeding %N", feed->ni->addr); - EXPORT_FOUND(RT_EXPORT_FEED); } else if (rt_export_get_state(r) == TES_DOWN) @@ -158,7 +156,6 @@ rt_export_get(struct rt_export_request *r) feed = e->feed_net(e, u, ni->index, NULL, NULL, update); } - bmap_set(&r->feed_map, ni->index); ASSERT_DIE(feed && (feed != &rt_feed_index_out_of_range)); EXPORT_FOUND(RT_EXPORT_FEED); @@ -193,6 +190,8 @@ rt_export_release(const struct rt_export_union *u) for (uint i = 0; i < u->feed->count_exports; i++) bmap_set(&r->seq_map, u->feed->exports[i]); + bmap_set(&r->feed_map, u->feed->ni->index); + if (!u->update) break; diff --git a/nest/rt-table.c b/nest/rt-table.c index eaabb939..a76a12ec 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1081,13 +1081,21 @@ 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) { - rte *old_best, *new_best; + rte *old_best = NULL, *new_best = NULL; bool feeding = rt_net_is_feeding(&c->out_req, feed->ni->addr); bool idempotent = 0; + RT_NOTIFY_DEBUG("%s feed for %N with %u routes", feeding ? "refeed" : "regular", feed->ni->addr, feed->count_routes); + for (uint i = 0; i < feed->count_routes; i++) { rte *r = &feed->block[i]; @@ -1095,45 +1103,62 @@ rt_notify_accepted(struct channel *c, const struct rt_export_feed *feed) /* Previously exported */ if (!old_best && bmap_test(&c->export_accepted_map, r->id)) { + RT_NOTIFY_DEBUG("route %u id %u previously exported, is old best", i, r->id); old_best = r; + /* Is being withdrawn */ + if (r->flags & REF_OBSOLETE) + RT_NOTIFY_DEBUG("route %u id %u is also obsolete", i, r->id); + /* Is still the best and need not be refed anyway */ - if (!new_best && !feeding) + else if (!new_best && !feeding) { - idempotent = 1; + RT_NOTIFY_DEBUG("route %u id %u is also new best (idempotent)", i, r->id); new_best = r; + idempotent = 1; } } /* Unflag obsolete routes */ - if (r->flags & REF_OBSOLETE) + 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); + } /* 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); + } /* Already rejected */ else if (!feeding && bmap_test(&c->export_rejected_map, r->id)) - ; + 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 */ else if (!new_best) { /* This branch should not be executed if this route is old best */ - ASSERT_DIE(r != old_best); + ASSERT_DIE(feeding || (r != old_best)); /* Have no new best route yet, try this route not seen before */ new_best = export_filter(c, r, 0); - DBG("rt_notify_accepted: checking route id %u: %s\n", r->id, new_best ? "ok" : "no"); + RT_NOTIFY_DEBUG("route %u id %u is a new_best candidate %s", i, r->id, + new_best ? "and is accepted" : "but got rejected"); } + + /* Just a debug message for the last case */ + else + RT_NOTIFY_DEBUG("route %u id %u is suboptimal, not checking", i, r->id); } /* Nothing to export */ if (!idempotent && (new_best || old_best)) do_rt_notify(c, feed->ni->addr, new_best, old_best); else - DBG("rt_notify_accepted: nothing to export\n"); + RT_NOTIFY_DEBUG("nothing to export for %N", feed->ni->addr); } void