]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Removed unnecessary recursion from rt_export_get()
authorMaria Matejka <mq@ucw.cz>
Wed, 12 Jun 2024 09:33:26 +0000 (11:33 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 12 Jun 2024 12:48:33 +0000 (14:48 +0200)
nest/rt-export.c

index c36a5aa1f914d17242abcef9eb8dc61e4e2a87df..f421a63b80eabe5986165f193ccaaf9346f1e7d9 100644 (file)
@@ -49,123 +49,127 @@ rt_export_get(struct rt_export_request *r)
     .feed = feed, \
   }; \
   return (r->cur = reu); \
-} while (0) \
+} while (0)
 
-#define NOT_THIS_UPDATE        do { \
+#define NOT_THIS_UPDATE        \
   lfjour_release(&r->r); \
-  return rt_export_get(r); \
-} while (0) \
+  continue;
 
-  enum rt_export_state es = rt_export_get_state(r);
-  switch (es)
+  while (1)
   {
-    case TES_DOWN:
-      rtex_trace(r, (D_ROUTES|D_STATES), "Export is down");
-      return NULL;
-
-    case TES_STOP:
-      rtex_trace(r, (D_ROUTES|D_STATES), "Received stop event");
-      struct rt_export_union *reu = tmp_alloc(sizeof *reu);
-      *reu = (struct rt_export_union) {
-       .kind = RT_EXPORT_STOP,
-       .req = r,
-      };
-      return (r->cur = reu);
-
-    case TES_PARTIAL:
-    case TES_FEEDING:
-    case TES_READY:
-      break;
+    enum rt_export_state es = rt_export_get_state(r);
+    switch (es)
+    {
+      case TES_DOWN:
+       rtex_trace(r, (D_ROUTES|D_STATES), "Export is down");
+       return NULL;
+
+      case TES_STOP:
+       rtex_trace(r, (D_ROUTES|D_STATES), "Received stop event");
+       struct rt_export_union *reu = tmp_alloc(sizeof *reu);
+       *reu = (struct rt_export_union) {
+         .kind = RT_EXPORT_STOP,
+         .req = r,
+       };
+       return (r->cur = reu);
+
+      case TES_PARTIAL:
+      case TES_FEEDING:
+      case TES_READY:
+       break;
 
-    case TES_MAX:
-      bug("invalid export state");
-  }
+      case TES_MAX:
+       bug("invalid export state");
+    }
 
-  /* Process sequence number reset event */
-  if (lfjour_reset_seqno(&r->r))
-    bmap_reset(&r->seq_map, 4);
+    /* Process sequence number reset event */
+    if (lfjour_reset_seqno(&r->r))
+      bmap_reset(&r->seq_map, 4);
 
-  /* Get a new update */
-  SKIP_BACK_DECLARE(struct rt_export_item, update, li, lfjour_get(&r->r));
-  SKIP_BACK_DECLARE(struct rt_exporter, e, journal, lfjour_of_recipient(&r->r));
-  struct rt_export_feed *feed = NULL;
+    /* Get a new update */
+    SKIP_BACK_DECLARE(struct rt_export_item, update, li, lfjour_get(&r->r));
+    SKIP_BACK_DECLARE(struct rt_exporter, e, journal, lfjour_of_recipient(&r->r));
+    struct rt_export_feed *feed = NULL;
 
-  /* No update, try feed */
-  if (!update)
-    if (es == TES_READY)
+    /* No update, try feed */
+    if (!update)
     {
-      /* Fed up of feeding */
-      rtex_trace(r, D_ROUTES, "Export drained");
-      return NULL;
+      if (es == TES_READY)
+      {
+       /* Fed up of feeding */
+       rtex_trace(r, D_ROUTES, "Export drained");
+       return NULL;
+      }
+      else if (feed = rt_export_next_feed(&r->feeder))
+      {
+       /* Feeding more */
+       bmap_set(&r->feed_map, feed->ni->index);
+       rtex_trace(r, D_ROUTES, "Feeding %N", feed->ni->addr);
+
+       EXPORT_FOUND(RT_EXPORT_FEED);
+      }
+      else if (rt_export_get_state(r) == TES_DOWN)
+      {
+       /* Torn down inbetween */
+       rtex_trace(r, D_STATES, "Export ended itself");
+       return NULL;
+      }
+      else
+      {
+       /* No more food */
+       rt_export_change_state(r, BIT32_ALL(TES_FEEDING, TES_PARTIAL), TES_READY);
+       rtex_trace(r, D_STATES, "Fed up");
+       CALL(r->fed, r);
+       return NULL;
+      }
     }
-    else if (feed = rt_export_next_feed(&r->feeder))
-    {
-      /* Feeding more */
-      bmap_set(&r->feed_map, feed->ni->index);
-      rtex_trace(r, D_ROUTES, "Feeding %N", feed->ni->addr);
 
-      EXPORT_FOUND(RT_EXPORT_FEED);
-    }
-    else if (rt_export_get_state(r) == TES_DOWN)
+    /* There actually is an update */
+    if (bmap_test(&r->seq_map, update->seq))
     {
-      /* Torn down inbetween */
-      rtex_trace(r, D_STATES, "Export ended itself");
-      return NULL;
+      /* But this update has been already processed, let's try another one */
+      rtex_trace(r, D_ROUTES, "Skipping an already processed update %lu", update->seq);
+      NOT_THIS_UPDATE;
     }
-    else
-    {
-      /* No more food */
-      rt_export_change_state(r, BIT32_ALL(TES_FEEDING, TES_PARTIAL), TES_READY);
-      rtex_trace(r, D_STATES, "Fed up");
-      CALL(r->fed, r);
-      return NULL;
-    }
-
-  /* There actually is an update */
-  if (bmap_test(&r->seq_map, update->seq))
-  {
-    /* But this update has been already processed, let's try another one */
-    rtex_trace(r, D_ROUTES, "Skipping an already processed update %lu", update->seq);
-    NOT_THIS_UPDATE;
-  }
 
-  /* Is this update allowed by prefilter? */
-  const net_addr *n = (update->new ?: update->old)->net;
-  struct netindex *ni = NET_TO_INDEX(n);
+    /* Is this update allowed by prefilter? */
+    const net_addr *n = (update->new ?: update->old)->net;
+    struct netindex *ni = NET_TO_INDEX(n);
 
-  if (!rt_prefilter_net(&r->feeder.prefilter, n))
-  {
-    rtex_trace(r, D_ROUTES, "Not exporting %N due to prefilter", n);
-    NOT_THIS_UPDATE;
-  }
-
-  if ((es != TES_READY) && rt_net_is_feeding(r, n))
-  {
-    /* But this net shall get a feed first! */
-    rtex_trace(r, D_ROUTES, "Expediting %N feed due to pending update %lu", n, update->seq);
-    if (r->feeder.domain.rtable)
+    if (!rt_prefilter_net(&r->feeder.prefilter, n))
     {
-      LOCK_DOMAIN(rtable, r->feeder.domain);
-      feed = e->feed_net(e, NULL, ni->index, update);
-      UNLOCK_DOMAIN(rtable, r->feeder.domain);
+      rtex_trace(r, D_ROUTES, "Not exporting %N due to prefilter", n);
+      NOT_THIS_UPDATE;
     }
-    else
+
+    if ((es != TES_READY) && rt_net_is_feeding(r, n))
     {
-      RCU_ANCHOR(u);
-      feed = e->feed_net(e, u, ni->index, update);
+      /* But this net shall get a feed first! */
+      rtex_trace(r, D_ROUTES, "Expediting %N feed due to pending update %lu", n, update->seq);
+      if (r->feeder.domain.rtable)
+      {
+       LOCK_DOMAIN(rtable, r->feeder.domain);
+       feed = e->feed_net(e, NULL, ni->index, update);
+       UNLOCK_DOMAIN(rtable, r->feeder.domain);
+      }
+      else
+      {
+       RCU_ANCHOR(u);
+       feed = e->feed_net(e, u, ni->index, update);
+      }
+
+      bmap_set(&r->feed_map, ni->index);
+      ASSERT_DIE(feed && (feed != &rt_feed_index_out_of_range));
+
+      EXPORT_FOUND(RT_EXPORT_FEED);
     }
 
-    bmap_set(&r->feed_map, ni->index);
-    ASSERT_DIE(feed && (feed != &rt_feed_index_out_of_range));
+    /* OK, now this actually is an update, thank you for your patience */
+    rtex_trace(r, D_ROUTES, "Updating %N, seq %lu", n, update->seq);
 
-    EXPORT_FOUND(RT_EXPORT_FEED);
+    EXPORT_FOUND(RT_EXPORT_UPDATE);
   }
 
-  /* OK, now this actually is an update, thank you for your patience */
-  rtex_trace(r, D_ROUTES, "Updating %N, seq %lu", n, update->seq);
-
-  EXPORT_FOUND(RT_EXPORT_UPDATE);
-
 #undef NOT_THIS_UPDATE
 #undef EXPORT_FOUND
 }