]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fixed new route comparison
authorMaria Matejka <mq@ucw.cz>
Mon, 27 Jun 2022 10:32:15 +0000 (12:32 +0200)
committerMaria Matejka <mq@ucw.cz>
Mon, 27 Jun 2022 10:32:47 +0000 (12:32 +0200)
nest/proto.c
nest/rt-table.c
nest/rt.h

index 3792fde4e8523d9b63a0a49b5e2a9a84d702e32c..0daf59f40191f725614b2e2594ccda068720decd 100644 (file)
@@ -177,7 +177,7 @@ proto_find_channel_by_name(struct proto *p, const char *n)
   return NULL;
 }
 
-rte * channel_preimport(struct rt_import_request *req, rte *new, rte *old);
+int channel_preimport(struct rt_import_request *req, rte *new, rte *old);
 
 void rt_notify_optimal(struct rt_export_request *req, const net_addr *net, struct rt_pending_export *rpe);
 void rt_notify_any(struct rt_export_request *req, const net_addr *net, struct rt_pending_export *rpe);
index ed0132ca9feee7255d4f639896992c67bf313854..41b6337eab9da8cb64e610c530cec8a589c4b124 100644 (file)
@@ -1282,6 +1282,14 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
   rte *old_best = old_best_stored ? &old_best_stored->rte : NULL;
   rte *old = NULL;
 
+  /* If the new route is identical to the old one, we find the attributes in
+   * cache and clone these with no performance drop. OTOH, if we were to lookup
+   * the attributes, such a route definitely hasn't been anywhere yet,
+   * therefore it's definitely worth the time. */
+  struct rte_storage *new_stored = NULL;
+  if (new)
+    new = &(new_stored = rte_store(new, net, table))->rte;
+
   /* Find and remove original route from the same protocol */
   struct rte_storage **before_old = rte_find(net, src);
 
@@ -1304,7 +1312,7 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
                c->table->name, net->n.addr, old->src->proto->name, old->src->private_id, old->src->global_id);
        }
 
-         if (new && rte_same(old, new))
+         if (new && rte_same(old, &new_stored->rte))
            {
              /* No changes, ignore the new route and refresh the old one */
 
@@ -1315,6 +1323,10 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
                  stats->updates_ignored++;
                  rt_rte_trace_in(D_ROUTES, req, new, "ignored");
                }
+
+             /* We need to free the already stored route here before returning */
+             rte_free(new_stored);
+             return;
          }
 
        *before_old = (*before_old)->next;
@@ -1327,8 +1339,13 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
       return;
     }
 
-  if (req->preimport)
-    new = req->preimport(req, new, old);
+  /* If rejected by import limit, we need to pretend there is no route */
+  if (req->preimport && (req->preimport(req, new, old) == 0))
+  {
+    rte_free(new_stored);
+    new_stored = NULL;
+    new = NULL;
+  }
 
   int new_ok = rte_is_ok(new);
   int old_ok = rte_is_ok(old);
@@ -1343,8 +1360,6 @@ rte_recalculate(struct rt_import_hook *c, net *net, rte *new, struct rte_src *sr
   if (old_ok || new_ok)
     table->last_rt_change = current_time();
 
-  struct rte_storage *new_stored = new ? rte_store(new, net, table) : NULL;
-
   if (table->config->sorted)
     {
       /* If routes are sorted, just insert new route to appropriate position */
@@ -1500,14 +1515,14 @@ rte_update_unlock(void)
     lp_flush(rte_update_pool);
 }
 
-rte *
+int
 channel_preimport(struct rt_import_request *req, rte *new, rte *old)
 {
   struct channel *c = SKIP_BACK(struct channel, in_req, req);
 
   if (new && !old)
     if (CHANNEL_LIMIT_PUSH(c, RX))
-      return NULL;
+      return 0;
 
   if (!new && old)
     CHANNEL_LIMIT_POP(c, RX);
@@ -1520,15 +1535,15 @@ channel_preimport(struct rt_import_request *req, rte *new, rte *old)
       if (c->in_keep & RIK_REJECTED)
       {
        new->flags |= REF_FILTERED;
-       return new;
+       return 1;
       }
       else
-       return NULL;
+       return 0;
 
   if (!new_in && old_in)
     CHANNEL_LIMIT_POP(c, IN);
 
-  return new;
+  return 1;
 }
 
 void
index c959d3586069a30f6c2e68c3ba926a442b377a28..70e0283fff9dbf84c747592ce5172eabc8490bc5 100644 (file)
--- a/nest/rt.h
+++ b/nest/rt.h
@@ -181,7 +181,7 @@ struct rt_import_request {
   void (*log_state_change)(struct rt_import_request *req, u8 state);
   /* Preimport is called when the @new route is just-to-be inserted, replacing @old.
    * Return a route (may be different or modified in-place) to continue or NULL to withdraw. */
-  struct rte *(*preimport)(struct rt_import_request *req, struct rte *new, struct rte *old);
+  int (*preimport)(struct rt_import_request *req, struct rte *new, struct rte *old);
   struct rte *(*rte_modify)(struct rte *, struct linpool *);
 };