0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Fixed secondary route export

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

View File

@ -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

View File

@ -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), \

View File

@ -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;

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);
}
#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