]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Nest: Update statistics and rx-limit for Adj-RIB-In
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 11 Dec 2018 12:52:30 +0000 (13:52 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 12 Dec 2018 13:46:24 +0000 (14:46 +0100)
nest/route.h
nest/rt-table.c

index 7a683f9e32c569a7ef5ac0c7860e6c5ff930d87a..93afae57e87190037380b1b12543cff1678cd01f 100644 (file)
@@ -151,6 +151,7 @@ typedef struct rtable {
   uint addr_type;                      /* Type of address data stored in table (NET_*) */
   int pipe_busy;                       /* Pipe loop detection */
   int use_count;                       /* Number of protocols using this table */
+  u32 rt_count;                                /* Number of routes in the table */
   struct hostcache *hostcache;
   struct rtable_config *config;                /* Configuration of this table */
   struct config *deleted;              /* Table doesn't exist in current configuration,
index 5beb1be9f0c11b52642dcb05742292224090bf47..ae4bb74d1b536c20daabaadc2cc047192add65d8 100644 (file)
@@ -1044,6 +1044,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
              return;
            }
          *k = old->next;
+         table->rt_count--;
          break;
        }
       k = &old->next;
@@ -1063,7 +1064,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
   int old_ok = rte_is_ok(old);
 
   struct channel_limit *l = &c->rx_limit;
-  if (l->action && !old && new)
+  if (l->action && !old && new && !c->in_table)
     {
       u32 all_routes = stats->imp_routes + stats->filt_routes;
 
@@ -1146,6 +1147,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
 
          new->next = *k;
          *k = new;
+         table->rt_count++;
        }
     }
   else
@@ -1163,6 +1165,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
 
          new->next = net->routes;
          net->routes = new;
+         table->rt_count++;
        }
       else if (old == old_best)
        {
@@ -1178,6 +1181,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
            {
              new->next = net->routes;
              net->routes = new;
+             table->rt_count++;
            }
 
          /* Find a new optimal route (if there is any) */
@@ -1205,6 +1209,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
          ASSERT(net->routes != NULL);
          new->next = net->routes->next;
          net->routes->next = new;
+         table->rt_count++;
        }
       /* The fourth (empty) case - suboptimal route was removed, nothing to do */
     }
@@ -2292,12 +2297,13 @@ rt_feed_channel_abort(struct channel *c)
 int
 rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
 {
+  struct rtable *tab = c->in_table;
   rte *old, **pos;
   net *net;
 
   if (new)
   {
-    net = net_get(c->in_table, n);
+    net = net_get(tab, n);
 
     if (!new->pref)
       new->pref = c->preference;
@@ -2307,10 +2313,10 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr
   }
   else
   {
-    net = net_find(c->in_table, n);
+    net = net_find(tab, n);
 
     if (!net)
-      return 0;
+      goto drop_withdraw;
   }
 
   /* Find the old rte */
@@ -2318,17 +2324,36 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr
     if (old->attrs->src == src)
     {
       if (new && rte_same(old, new))
-       return 0;
+       goto drop_update;
 
       /* Remove the old rte */
       *pos = old->next;
       rte_free_quick(old);
+      tab->rt_count--;
 
       break;
     }
 
   if (!new)
-    return !!old;
+  {
+    if (!old)
+      goto drop_withdraw;
+
+    return 1;
+  }
+
+  struct channel_limit *l = &c->rx_limit;
+  if (l->action && !old)
+  {
+    if (tab->rt_count >= l->limit)
+      channel_notify_limit(c, l, PLD_RX, tab->rt_count);
+
+    if (l->state == PLS_BLOCKED)
+    {
+      rte_trace_in(D_FILTERS, c->proto, new, "ignored [limit]");
+      goto drop_update;
+    }
+  }
 
   /* Insert the new rte */
   rte *e = rte_do_cow(new);
@@ -2338,8 +2363,19 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr
   e->lastmod = current_time();
   e->next = *pos;
   *pos = e;
-
+  tab->rt_count++;
   return 1;
+
+drop_update:
+  c->stats.imp_updates_received++;
+  c->stats.imp_updates_ignored++;
+  rte_free(new);
+  return 0;
+
+drop_withdraw:
+  c->stats.imp_withdraws_received++;
+  c->stats.imp_withdraws_ignored++;
+  return 0;
 }
 
 int
@@ -2400,6 +2436,7 @@ rt_prune_sync(rtable *t, int all)
       {
        *ee = e->next;
        rte_free_quick(e);
+       t->rt_count--;
       }
       else
        ee = &e->next;