0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-08 12:18:42 +00:00

Fixed secondary route export

This commit is contained in:
Maria Matejka 2024-06-28 21:38:54 +02:00
parent b03625698b
commit e45feec8f2
4 changed files with 50 additions and 16 deletions

View File

@ -108,8 +108,6 @@ void
channel_request_full_refeed(struct channel *c) channel_request_full_refeed(struct channel *c)
{ {
rt_export_refeed(&c->out_req, NULL); rt_export_refeed(&c->out_req, NULL);
bmap_reset(&c->export_accepted_map, 16);
bmap_reset(&c->export_rejected_map, 16);
} }
static void static void

View File

@ -331,9 +331,21 @@ static inline bool
rt_net_is_feeding_request(struct rt_export_request *req, const net_addr *n) rt_net_is_feeding_request(struct rt_export_request *req, const net_addr *n)
{ {
struct netindex *ni = NET_TO_INDEX(n); struct netindex *ni = NET_TO_INDEX(n);
return switch (rt_export_get_state(req))
!bmap_test(&req->feed_map, ni->index) {
&& rt_net_is_feeding_feeder(&req->feeder, n); 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), \ #define rt_net_is_feeding(h, n) _Generic((h), \

View File

@ -103,9 +103,7 @@ rt_export_get(struct rt_export_request *r)
else if (feed = rt_export_next_feed(&r->feeder)) else if (feed = rt_export_next_feed(&r->feeder))
{ {
/* Feeding more */ /* Feeding more */
bmap_set(&r->feed_map, feed->ni->index);
rtex_trace(r, D_ROUTES, "Feeding %N", feed->ni->addr); rtex_trace(r, D_ROUTES, "Feeding %N", feed->ni->addr);
EXPORT_FOUND(RT_EXPORT_FEED); EXPORT_FOUND(RT_EXPORT_FEED);
} }
else if (rt_export_get_state(r) == TES_DOWN) 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); 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)); ASSERT_DIE(feed && (feed != &rt_feed_index_out_of_range));
EXPORT_FOUND(RT_EXPORT_FEED); 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++) for (uint i = 0; i < u->feed->count_exports; i++)
bmap_set(&r->seq_map, u->feed->exports[i]); bmap_set(&r->seq_map, u->feed->exports[i]);
bmap_set(&r->feed_map, u->feed->ni->index);
if (!u->update) if (!u->update)
break; break;

View File

@ -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); 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 static void
rt_notify_accepted(struct channel *c, const struct rt_export_feed *feed) 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 feeding = rt_net_is_feeding(&c->out_req, feed->ni->addr);
bool idempotent = 0; 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++) for (uint i = 0; i < feed->count_routes; i++)
{ {
rte *r = &feed->block[i]; rte *r = &feed->block[i];
@ -1095,45 +1103,62 @@ rt_notify_accepted(struct channel *c, const struct rt_export_feed *feed)
/* Previously exported */ /* Previously exported */
if (!old_best && bmap_test(&c->export_accepted_map, r->id)) 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; 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 */ /* 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; new_best = r;
idempotent = 1;
} }
} }
/* Unflag obsolete routes */ /* 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); bmap_clear(&c->export_rejected_map, r->id);
}
/* Mark invalid as rejected */ /* Mark invalid as rejected */
else if (!rte_is_valid(r)) 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); bmap_set(&c->export_rejected_map, r->id);
}
/* Already rejected */ /* Already rejected */
else if (!feeding && bmap_test(&c->export_rejected_map, r->id)) 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 */ /* No new best route yet and this is a valid candidate */
else if (!new_best) else if (!new_best)
{ {
/* This branch should not be executed if this route is old 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 */ /* Have no new best route yet, try this route not seen before */
new_best = export_filter(c, r, 0); 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 */ /* Nothing to export */
if (!idempotent && (new_best || old_best)) if (!idempotent && (new_best || old_best))
do_rt_notify(c, feed->ni->addr, new_best, old_best); do_rt_notify(c, feed->ni->addr, new_best, old_best);
else else
DBG("rt_notify_accepted: nothing to export\n"); RT_NOTIFY_DEBUG("nothing to export for %N", feed->ni->addr);
} }
void void