0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

Fixed invalid routes handling

The invalid routes were filtered out before they could ever get
exported, yet some of the routines need them available, e.g. for
display or import reload.

Now the invalid routes are properly exported and dropped in channel
export routines instead.
This commit is contained in:
Maria Matejka 2022-07-14 11:09:23 +02:00
parent 239edf8d31
commit 1c2851ecfa
3 changed files with 34 additions and 33 deletions

View File

@ -726,8 +726,8 @@ rte_feed_count(net *n)
{ {
uint count = 0; uint count = 0;
for (struct rte_storage *e = n->routes; e; e = e->next) for (struct rte_storage *e = n->routes; e; e = e->next)
if (rte_is_valid(RTE_OR_NULL(e))) count++;
count++;
return count; return count;
} }
@ -736,11 +736,11 @@ rte_feed_obtain(net *n, struct rte **feed, uint count)
{ {
uint i = 0; uint i = 0;
for (struct rte_storage *e = n->routes; e; e = e->next) for (struct rte_storage *e = n->routes; e; e = e->next)
if (rte_is_valid(RTE_OR_NULL(e)))
{ {
ASSERT_DIE(i < count); ASSERT_DIE(i < count);
feed[i++] = &e->rte; feed[i++] = &e->rte;
} }
ASSERT_DIE(i == count); ASSERT_DIE(i == count);
} }
@ -1059,10 +1059,15 @@ void
rt_notify_optimal(struct rt_export_request *req, const net_addr *net, struct rt_pending_export *rpe) rt_notify_optimal(struct rt_export_request *req, const net_addr *net, struct rt_pending_export *rpe)
{ {
struct channel *c = SKIP_BACK(struct channel, out_req, req); struct channel *c = SKIP_BACK(struct channel, out_req, req);
rte n0;
if (rpe->new_best != rpe->old_best) if (rpe->new_best != rpe->old_best)
rt_notify_basic(c, net, RTE_COPY(rpe->new_best, &n0), RTE_OR_NULL(rpe->old_best)); {
rte n0 = RTE_COPY_VALID(rpe->new_best);
rte *o = RTE_VALID_OR_NULL(rpe->old_best);
if (n0.src || o)
rt_notify_basic(c, net, n0.src ? &n0 : NULL, o);
}
/* Drop the old stored rejection if applicable. /* Drop the old stored rejection if applicable.
* new->id == old->id happens when updating hostentries. */ * new->id == old->id happens when updating hostentries. */
@ -1074,10 +1079,14 @@ void
rt_notify_any(struct rt_export_request *req, const net_addr *net, struct rt_pending_export *rpe) rt_notify_any(struct rt_export_request *req, const net_addr *net, struct rt_pending_export *rpe)
{ {
struct channel *c = SKIP_BACK(struct channel, out_req, req); struct channel *c = SKIP_BACK(struct channel, out_req, req);
rte n0;
if (rpe->new != rpe->old) if (rpe->new != rpe->old)
rt_notify_basic(c, net, RTE_COPY(rpe->new, &n0), RTE_OR_NULL(rpe->old)); {
rte n0 = RTE_COPY_VALID(rpe->new);
rte *o = RTE_VALID_OR_NULL(rpe->old);
if (n0.src || o)
rt_notify_basic(c, net, n0.src ? &n0 : NULL, o);
}
/* Drop the old stored rejection if applicable. /* Drop the old stored rejection if applicable.
* new->id == old->id happens when updating hostentries. */ * new->id == old->id happens when updating hostentries. */
@ -1091,10 +1100,11 @@ rt_feed_any(struct rt_export_request *req, const net_addr *net, struct rt_pendin
struct channel *c = SKIP_BACK(struct channel, out_req, req); struct channel *c = SKIP_BACK(struct channel, out_req, req);
for (uint i=0; i<count; i++) for (uint i=0; i<count; i++)
{ if (rte_is_valid(feed[i]))
rte n0 = *feed[i]; {
rt_notify_basic(c, net, &n0, NULL); rte n0 = *feed[i];
} rt_notify_basic(c, net, &n0, NULL);
}
} }
/** /**
@ -1132,26 +1142,17 @@ static void
rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage *old, rte_announce(rtable *tab, net *net, struct rte_storage *new, struct rte_storage *old,
struct rte_storage *new_best, struct rte_storage *old_best) struct rte_storage *new_best, struct rte_storage *old_best)
{ {
if (!rte_is_valid(RTE_OR_NULL(new))) int new_best_valid = rte_is_valid(RTE_OR_NULL(new_best));
new = NULL; int old_best_valid = rte_is_valid(RTE_OR_NULL(old_best));
if (!rte_is_valid(RTE_OR_NULL(old)))
old = NULL;
if (!rte_is_valid(RTE_OR_NULL(new_best)))
new_best = NULL;
if (!rte_is_valid(RTE_OR_NULL(old_best)))
old_best = NULL;
if (!new && !old && !new_best && !old_best) if (!new && !old && !new_best && !old_best)
return; return;
if (new_best != old_best) if (new_best_valid || old_best_valid)
{ {
if (new_best) if (new_best_valid)
new_best->rte.sender->stats.pref++; new_best->rte.sender->stats.pref++;
if (old_best) if (old_best_valid)
old_best->rte.sender->stats.pref--; old_best->rte.sender->stats.pref--;
if (tab->hostcache) if (tab->hostcache)

View File

@ -167,8 +167,10 @@ struct rte_storage {
struct rte rte; /* Route data */ struct rte rte; /* Route data */
}; };
#define RTE_COPY(r, l) ((r) ? (((*(l)) = (r)->rte), (l)) : NULL) #define RTE_COPY(r) ((r) ? (r)->rte : (rte) {})
#define RTE_OR_NULL(r) ((r) ? &((r)->rte) : NULL) #define RTE_COPY_VALID(r) (((r) && (rte_is_valid(&(r)->rte))) ? (r)->rte : (rte) {})
#define RTE_OR_NULL(r) ((r) ? &((r)->rte) : NULL)
#define RTE_VALID_OR_NULL(r) (((r) && (rte_is_valid(&(r)->rte))) ? &((r)->rte) : NULL)
/* Table-channel connections */ /* Table-channel connections */

View File

@ -2557,12 +2557,10 @@ bgp_rte_modify_stale(struct rt_export_request *req, const net_addr *n, struct rt
{ {
rte *r = feed[i]; rte *r = feed[i];
/* Not our route */ if (
if (r->sender != irh) !rte_is_valid(r) || /* Not a valid route */
continue; (r->sender != irh) || /* Not our route */
(r->stale_cycle == irh->stale_set)) /* A new route, do not mark as stale */
/* A new route, do not mark as stale */
if (r->stale_cycle == irh->stale_set)
continue; continue;
eattr *ea = ea_find(r->attrs, BGP_EA_ID(BA_COMMUNITY)); eattr *ea = ea_find(r->attrs, BGP_EA_ID(BA_COMMUNITY));