summaryrefslogtreecommitdiff
path: root/nest/rt-table.c
diff options
context:
space:
mode:
Diffstat (limited to 'nest/rt-table.c')
-rw-r--r--nest/rt-table.c51
1 files changed, 31 insertions, 20 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 0b6351e9..280551aa 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -376,18 +376,22 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent)
struct proto *p = c->proto;
const struct filter *filter = c->out_filter;
struct export_stats *stats = &c->export_stats;
- int v;
- v = p->preexport ? p->preexport(c, rt) : 0;
+ /* Do nothing if we have already rejected the route */
+ if (silent && bmap_test(&c->export_reject_map, rt->id))
+ goto reject_noset;
+
+ int v = p->preexport ? p->preexport(c, rt) : 0;
if (v < 0)
{
if (silent)
- goto reject;
+ goto reject_noset;
stats->updates_rejected++;
if (v == RIC_REJECT)
rte_trace_out(D_FILTERS, c, rt, "rejected by protocol");
- goto reject;
+ goto reject_noset;
+
}
if (v > 0)
{
@@ -410,9 +414,16 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent)
}
accept:
+ /* We have accepted the route */
+ bmap_clear(&c->export_reject_map, rt->id);
return rt;
reject:
+ /* We have rejected the route by filter */
+ bmap_set(&c->export_reject_map, rt->id);
+
+reject_noset:
+ /* Invalidate the route */
/* Discard temporary rte */
return NULL;
}
@@ -565,8 +576,14 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
{
/* Feed or old_best changed -> find first accepted by filters */
for (struct rte_storage *r = net->routes; r && rte_is_valid(&r->rte); r = r->next)
+ {
+ /* Already rejected before */
+ if (!refeed && bmap_test(&c->export_reject_map, r->rte.id))
+ continue;
+
if (new_best = export_filter(c, ((nb0 = r->rte), &nb0), 0))
break;
+ }
}
else
{
@@ -677,7 +694,6 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
/**
* rte_announce - announce a routing table change
* @tab: table the route has been added to
- * @type: type of route announcement (RA_UNDEF or RA_ANY)
* @net: network in question
* @new: the new or changed route
* @old: the previous route replaced by the new one
@@ -693,13 +709,6 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
* and @new_best and @old_best describes best routes. Other routes are not
* affected, but in sorted table the order of other routes might change.
*
- * Second, There is a bulk change of multiple routes in @net, with shared best
- * route selection. In such case separate route changes are described using
- * @type of %RA_ANY, with @new and @old specifying the changed route, while
- * @new_best and @old_best are NULL. After that, another notification is done
- * where @new_best and @old_best are filled (may be the same), but @new and @old
- * are NULL.
- *
* The function announces the change to all associated channels. For each
* channel, an appropriate preprocessing is done according to channel &ra_mode.
* For example, %RA_OPTIMAL channels receive just changes of best routes.
@@ -714,7 +723,7 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
* done outside of scope of rte_announce().
*/
static void
-rte_announce(rtable *tab, uint type, 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)
{
if (!new || !rte_is_valid(&new->rte))
@@ -751,9 +760,6 @@ rte_announce(rtable *tab, uint type, net *net, struct rte_storage *new, struct r
if (c->export_state == ES_DOWN)
continue;
- if (type && (type != c->ra_mode))
- continue;
-
rte n0;
switch (c->ra_mode)
{
@@ -775,6 +781,11 @@ rte_announce(rtable *tab, uint type, net *net, struct rte_storage *new, struct r
rt_notify_merged(c, net, RTE_OR_NULL(new), RTE_OR_NULL(old), RTE_OR_NULL(new_best), RTE_OR_NULL(old_best), 0);
break;
}
+
+ /* Drop the old stored rejection if applicable.
+ * new->id == old->id happens when updating hostentries. */
+ if (old && (!new || (new->rte.id != old->rte.id)))
+ bmap_clear(&c->export_reject_map, old->rte.id);
}
}
@@ -1083,7 +1094,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
}
/* Propagate the route change */
- rte_announce(table, RA_UNDEF, net, new_stored, old_stored,
+ rte_announce(table, net, new_stored, old_stored,
net->routes, old_best_stored);
if (!net->routes &&
@@ -1208,11 +1219,11 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
/* Independent call to rte_announce(), used from next hop
recalculation, outside of rte_update(). new must be non-NULL */
static inline void
-rte_announce_i(rtable *tab, uint type, net *net, struct rte_storage *new, struct rte_storage *old,
+rte_announce_i(rtable *tab, net *net, struct rte_storage *new, struct rte_storage *old,
struct rte_storage *new_best, struct rte_storage *old_best)
{
rte_update_lock();
- rte_announce(tab, type, net, new, old, new_best, old_best);
+ rte_announce(tab, net, new, old, new_best, old_best);
rte_update_unlock();
}
@@ -1938,7 +1949,7 @@ rt_next_hop_update_net(rtable *tab, net *n)
_Bool nb = (new == updates[i].new), ob = (old_best == updates[i].old);
const char *best_indicator[2][2] = { { "updated", "updated [-best]" }, { "updated [+best]", "updated [best]" } };
rte_trace_in(D_ROUTES, new->rte.sender, &updates[i].new->rte, best_indicator[nb][ob]);
- rte_announce_i(tab, RA_UNDEF, n, updates[i].new, updates[i].old, new, old_best);
+ rte_announce_i(tab, n, updates[i].new, updates[i].old, new, old_best);
}
for (int i=0; i<count; i++)