mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
Fixed flush condition when stale cycle valid/set indicators wrap around
This commit is contained in:
parent
3685b0f9b6
commit
40061ac3ac
@ -2721,10 +2721,63 @@ rt_prune_net(struct rtable_private *tab, struct network *n)
|
|||||||
for (struct rte_storage *e = n->routes; e; e = e->next)
|
for (struct rte_storage *e = n->routes; e; e = e->next)
|
||||||
{
|
{
|
||||||
struct rt_import_hook *s = e->rte.sender;
|
struct rt_import_hook *s = e->rte.sender;
|
||||||
if ((s->import_state == TIS_FLUSHING) ||
|
|
||||||
(e->rte.stale_cycle < s->stale_valid) ||
|
_Bool stale = (s->import_state == TIS_FLUSHING);
|
||||||
(e->rte.stale_cycle > s->stale_set))
|
|
||||||
|
if (!stale)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The range of 0..256 is split by s->stale_* like this:
|
||||||
|
*
|
||||||
|
* pruned pruning valid set
|
||||||
|
* | | | |
|
||||||
|
* 0 v v v v 256
|
||||||
|
* |...........................+++++++++++........|
|
||||||
|
*
|
||||||
|
* We want to drop everything outside the marked range, thus
|
||||||
|
* (e->rte.stale_cycle < s->stale_valid) ||
|
||||||
|
* (e->rte.stale_cycle > s->stale_set))
|
||||||
|
* looks right.
|
||||||
|
*
|
||||||
|
* But the pointers may wrap around, and in the following situation, all the routes get pruned:
|
||||||
|
*
|
||||||
|
* set pruned pruning valid
|
||||||
|
* | | | |
|
||||||
|
* 0 v v v v 256
|
||||||
|
* |++++++..................................++++++|
|
||||||
|
*
|
||||||
|
* In that case, we want
|
||||||
|
* (e->rte.stale_cycle > s->stale_valid) ||
|
||||||
|
* (e->rte.stale_cycle < s->stale_set))
|
||||||
|
*
|
||||||
|
* Full logic table:
|
||||||
|
*
|
||||||
|
* permutation | result | (S < V) + (S < SC) + (SC < V)
|
||||||
|
* -----------------+----------+---------------------------------
|
||||||
|
* SC < V <= S | prune | 0 + 0 + 1 = 1
|
||||||
|
* S < SC < V | prune | 1 + 1 + 1 = 3
|
||||||
|
* V <= S < SC | prune | 0 + 1 + 0 = 1
|
||||||
|
* SC <= S < V | keep | 1 + 0 + 1 = 2
|
||||||
|
* V <= SC <= S | keep | 0 + 0 + 0 = 0
|
||||||
|
* S < V <= SC | keep | 1 + 1 + 0 = 2
|
||||||
|
*
|
||||||
|
* Now the following code hopefully makes sense.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int sv = (s->stale_set < s->stale_valid);
|
||||||
|
int ssc = (s->stale_set < e->rte.stale_cycle);
|
||||||
|
int scv = (e->rte.stale_cycle < s->stale_valid);
|
||||||
|
stale = (sv + ssc + scv) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* By the C standard, either the importer is flushing and stale_perm is 1,
|
||||||
|
* or by the table above, stale_perm is between 0 and 3, where even values
|
||||||
|
* say "keep" and odd values say "prune". */
|
||||||
|
|
||||||
|
if (stale)
|
||||||
|
{
|
||||||
|
/* Announce withdrawal */
|
||||||
struct netindex *i = RTE_GET_NETINDEX(&e->rte);
|
struct netindex *i = RTE_GET_NETINDEX(&e->rte);
|
||||||
rte_recalculate(tab, e->rte.sender, i, n, NULL, e->rte.src);
|
rte_recalculate(tab, e->rte.sender, i, n, NULL, e->rte.src);
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user