{
struct rt_import_hook *hook = req->hook;
ASSERT_DIE(hook);
- ASSERT_DIE(hook->stale_set == hook->stale_valid);
RT_LOCKED(hook->table, tab)
{
/* If the pruning routine is too slow */
- if ((hook->stale_pruned < hook->stale_valid) && (hook->stale_pruned + 128 < hook->stale_valid)
- || (hook->stale_pruned > hook->stale_valid) && (hook->stale_pruned > hook->stale_valid + 128))
+ if (((hook->stale_set - hook->stale_pruned) & 0xff) >= 240)
{
- log(L_WARN "Route refresh flood in table %s", hook->table->name);
+ log(L_WARN "Route refresh flood in table %s (stale_set=%u, stale_pruned=%u)", hook->table->name, hook->stale_set, hook->stale_pruned);
+
+ /* Forcibly set all old routes' stale cycle to zero. */
FIB_WALK(&tab->fib, net, n)
{
for (struct rte_storage *e = n->routes; e; e = e->next)
e->rte.stale_cycle = 0;
}
FIB_WALK_END;
+
+ /* Smash the route refresh counter and zero everything. */
tab->rr_counter -= hook->stale_set - hook->stale_pruned;
- hook->stale_set = 1;
- hook->stale_valid = 0;
- hook->stale_pruned = 0;
- }
- /* Setting a new value of the stale modifier */
- else if (!++hook->stale_set)
- {
- /* Let's reserve the stale_cycle zero value for always-invalid routes */
- hook->stale_set = 1;
- hook->stale_valid = 0;
+ hook->stale_set = hook->stale_valid = hook->stale_pruning = hook->stale_pruned = 0;
}
+ /* Now we can safely increase the stale_set modifier */
+ hook->stale_set++;
+
/* The table must know that we're route-refreshing */
tab->rr_counter++;
RT_LOCKED(hook->table, tab)
{
- hook->stale_valid++;
- ASSERT_DIE(hook->stale_set == hook->stale_valid);
+ /* Now valid routes are only those one with the latest stale_set value */
+ uint cnt = hook->stale_set - hook->stale_valid;
+ hook->stale_valid = hook->stale_set;
/* Here we can't kick the timer as we aren't in the table service loop */
rt_schedule_prune(tab);
if (req->trace_routes & D_STATES)
- log(L_TRACE "%s: route refresh end [%u]", req->name, hook->stale_valid);
+ if (cnt > 1)
+ log(L_TRACE "%s: route refresh end (x%u) [%u]", req->name, cnt, hook->stale_valid);
+ else
+ log(L_TRACE "%s: route refresh end [%u]", req->name, hook->stale_valid);
}
}
{
case BGP_GRS_NONE:
c->gr_active = BGP_GRS_ACTIVE;
- rt_refresh_begin(&c->c.in_req);
- break;
+ /* fall through */
case BGP_GRS_ACTIVE:
- rt_refresh_end(&c->c.in_req);
rt_refresh_begin(&c->c.in_req);
break;
if (c->load_state == BFS_LOADING)
{ log(L_WARN "%s: BEGIN-OF-RR received before END-OF-RIB, ignoring", p->p.name); return; }
- if (c->load_state == BFS_REFRESHING)
- rt_refresh_end(&c->c.in_req);
-
c->load_state = BFS_REFRESHING;
rt_refresh_begin(&c->c.in_req);
}