]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fixed hostentry update for sorted tables mq-hostentry-sorted-fix
authorMaria Matejka <mq@ucw.cz>
Wed, 20 May 2020 14:46:45 +0000 (16:46 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 20 May 2020 15:08:59 +0000 (17:08 +0200)
Best route recalculation after nexthop update completely ignored the
table's sortedness.

nest/rt-table.c

index ae5a844497a7860655512232fa469fe1b68cf522..93521457c2ef003f44ba3d60e7dda391c75eb30e 100644 (file)
@@ -2075,6 +2075,34 @@ rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
   return e;
 }
 
+static struct rte *
+rte_recalc_sort(struct rte *chain)
+{
+  ASSERT(chain);
+
+  /* Single route -> nothing to do */
+  if (!chain->next)
+    return chain;
+
+  /* Simple insert sort (TODO: something faster for long chains) */
+  struct rte *best = chain, *next = chain->next, *cur;
+  chain->next = NULL;
+
+  while (cur = next)
+  {
+    next = cur->next;
+    for (struct rte **k = &best; *k; k = &((*k)->next))
+      if (rte_better(cur, *k))
+      {
+       cur->next = *k;
+       *k = cur;
+       break;
+      }
+  }
+
+  return best;
+}
+
 static inline int
 rt_next_hop_update_net(rtable *tab, net *n)
 {
@@ -2113,20 +2141,25 @@ rt_next_hop_update_net(rtable *tab, net *n)
     return 0;
 
   /* Find the new best route */
-  new_best = NULL;
-  for (k = &n->routes; e = *k; k = &e->next)
+  if (tab->config->sorted)
+    new = n->routes = rte_recalc_sort(n->routes);
+  else
     {
-      if (!new_best || rte_better(e, *new_best))
-       new_best = k;
-    }
+      new_best = NULL;
+      for (k = &n->routes; e = *k; k = &e->next)
+      {
+       if (!new_best || rte_better(e, *new_best))
+         new_best = k;
+      }
 
-  /* Relink the new best route to the first position */
-  new = *new_best;
-  if (new != n->routes)
-    {
-      *new_best = new->next;
-      new->next = n->routes;
-      n->routes = new;
+      /* Relink the new best route to the first position */
+      new = *new_best;
+      if (new != n->routes)
+      {
+       *new_best = new->next;
+       new->next = n->routes;
+       n->routes = new;
+      }
     }
 
   /* Announce the new best route */