diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2011-12-22 13:20:29 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2011-12-22 13:20:29 +0100 |
commit | be4cd99a3688cef19f66e1c8b8e0506ffc1e13fc (patch) | |
tree | 2ac6aed8d703b4150976493ddcc179b395a795c8 /nest/rt-table.c | |
parent | cf7f0645316f5df0984467cf7001f5466254eaf3 (diff) |
Implements deterministic MED handling.
Thanks to Alexander V. Chernikov for many suggestions.
Diffstat (limited to 'nest/rt-table.c')
-rw-r--r-- | nest/rt-table.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c index e20d2f6d..377687de 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -498,6 +498,9 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte rte_announce(table, RA_ANY, net, new, old, tmpa); + if (src->rte_recalculate && src->rte_recalculate(table, net, new, old, old_best)) + goto do_recalculate; + if (new && rte_better(new, old_best)) { /* The first case - the new route is cleary optimal, we link it @@ -516,6 +519,7 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte that route at the first position and announce it. New optimal route might be NULL if there is no more routes */ + do_recalculate: /* Add the new route to the list */ if (new) { @@ -1015,27 +1019,36 @@ rt_next_hop_update_net(rtable *tab, net *n) if (!old_best) return 0; - new_best = NULL; - for (k = &n->routes; e = *k; k = &e->next) - { - if (rta_next_hop_outdated(e->attrs)) - { - new = rt_next_hop_update_rte(tab, e); - *k = new; + if (rta_next_hop_outdated(e->attrs)) + { + new = rt_next_hop_update_rte(tab, e); + *k = new; - rte_announce_i(tab, RA_ANY, n, new, e); - rte_trace_in(D_ROUTES, new->sender, new, "updated"); + rte_announce_i(tab, RA_ANY, n, new, e); + rte_trace_in(D_ROUTES, new->sender, new, "updated"); - if (e != old_best) - rte_free_quick(e); - else /* Freeing of the old best rte is postponed */ - free_old_best = 1; + /* Call a pre-comparison hook */ + /* Not really an efficient way to compute this */ + if (e->attrs->proto->rte_recalculate) + e->attrs->proto->rte_recalculate(tab, n, new, e, NULL); - e = new; - count++; - } + if (e != old_best) + rte_free_quick(e); + else /* Freeing of the old best rte is postponed */ + free_old_best = 1; + e = new; + count++; + } + + if (!count) + return 0; + + /* Find the new best route */ + new_best = NULL; + for (k = &n->routes; e = *k; k = &e->next) + { if (!new_best || rte_better(e, *new_best)) new_best = k; } |