summaryrefslogtreecommitdiff
path: root/nest/rt-table.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2011-12-22 13:20:29 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2011-12-22 13:20:29 +0100
commitbe4cd99a3688cef19f66e1c8b8e0506ffc1e13fc (patch)
tree2ac6aed8d703b4150976493ddcc179b395a795c8 /nest/rt-table.c
parentcf7f0645316f5df0984467cf7001f5466254eaf3 (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.c45
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;
}