]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements route statistics and fixes some minor bugs.
authorOndrej Zajicek <santiago@crfreenet.org>
Wed, 3 Jun 2009 23:22:56 +0000 (01:22 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Wed, 3 Jun 2009 23:22:56 +0000 (01:22 +0200)
doc/bird.sgml
nest/proto.c
nest/protocol.h
nest/rt-table.c

index 5027c3e4b1cdf60d7676ba3bba511ce9093ad1b0..c504dbb896c93ed6277332d98d89f12d761b357c 100644 (file)
@@ -1450,7 +1450,7 @@ of routes from the primary table to the secondary one, import filters control th
 direction.
 
 <p>The Pipe protocol may work in the opaque mode or in the transparent
-mode. In the opaque mode, thee Pipe protocol retransmits optimal route
+mode. In the opaque mode, the Pipe protocol retransmits optimal route
 from one table to the other table in a similar way like other
 protocols send and receive routes. Retransmitted route will have the
 source set to the Pipe protocol, which may limit access to protocol
index 0ad7229cdc01600cdafaf2775bc92e6717baa4d9..ef0587b2b12c250fa3618146e74f9dca27e459df 100644 (file)
@@ -512,6 +512,9 @@ static void
 proto_fell_down(struct proto *p)
 {
   DBG("Protocol %s down\n", p->name);
+  ASSERT(p->stats.imp_routes == 0);
+
+  bzero(&p->stats, sizeof(struct proto_stats));
   rt_unlock_table(p->table);
   proto_rethink_goal(p);
 }
@@ -693,9 +696,30 @@ proto_do_show(struct proto *p, int verbose)
          buf);
   if (verbose)
     {
-      cli_msg(-1006, "\tPreference: %d", p->preference);
-      cli_msg(-1006, "\tInput filter: %s", filter_name(p->in_filter));
-      cli_msg(-1006, "\tOutput filter: %s", filter_name(p->out_filter));
+      cli_msg(-1006, "  Preference:     %d", p->preference);
+      cli_msg(-1006, "  Input filter:   %s", filter_name(p->in_filter));
+      cli_msg(-1006, "  Output filter:  %s", filter_name(p->out_filter));
+
+      if (p->proto_state != PS_DOWN)
+       {
+         cli_msg(-1006, "  Routes:         %u imported, %u exported, %u preferred", 
+                 p->stats.imp_routes, p->stats.exp_routes, p->stats.pref_routes);
+         cli_msg(-1006, "  Route change stats:     received   rejected   filtered    ignored   accepted");
+         cli_msg(-1006, "    Import updates:     %10u %10u %10u %10u %10u",
+                 p->stats.imp_updates_received, p->stats.imp_updates_invalid,
+                 p->stats.imp_updates_filtered, p->stats.imp_updates_ignored,
+                 p->stats.imp_updates_accepted);
+         cli_msg(-1006, "    Import withdraws:   %10u %10u        --- %10u %10u",
+                 p->stats.imp_withdraws_received, p->stats.imp_withdraws_invalid,
+                 p->stats.imp_withdraws_ignored, p->stats.imp_withdraws_accepted);
+         cli_msg(-1006, "    Export updates:     %10u %10u %10u        --- %10u",
+                 p->stats.exp_updates_received, p->stats.exp_updates_rejected,
+                 p->stats.exp_updates_filtered, p->stats.exp_updates_accepted);
+         cli_msg(-1006, "    Export withdraws:   %10u        ---        ---        --- %10u",
+                 p->stats.exp_withdraws_received, p->stats.exp_withdraws_accepted);
+       }
+
+      cli_msg(-1006, "");
     }
 }
 
index 865b2b38776bd1066d7dcd8d65b4af4184f10cd8..eee3a7469b48a627444c3729977bc723cd89b9e4 100644 (file)
@@ -87,6 +87,31 @@ struct proto_config {
   /* Protocol-specific data follow... */
 };
 
+  /* Protocol statistics */
+struct proto_stats {
+  /* Import - from protocol to core */
+  u32 imp_routes;              /* Number of routes successfully imported to the (adjacent) routing table */
+  u32 pref_routes;             /* Number of routes that are preferred, sum over all routing table */
+  u32 imp_updates_received;    /* Number of route updates received */
+  u32 imp_updates_invalid;     /* Number of route updates rejected as invalid */
+  u32 imp_updates_filtered;    /* Number of route updates rejected by filters */
+  u32 imp_updates_ignored;     /* Number of route updates rejected as already in route table */
+  u32 imp_updates_accepted;    /* Number of route updates accepted and imported */
+  u32 imp_withdraws_received;  /* Number of route withdraws received */
+  u32 imp_withdraws_invalid;   /* Number of route withdraws rejected as invalid */
+  u32 imp_withdraws_ignored;   /* Number of route withdraws rejected as already not in route table */
+  u32 imp_withdraws_accepted;  /* Number of route withdraws accepted and processed */
+
+  /* Export - from core to protocol */
+  u32 exp_routes;              /* Number of routes successfully exported to the protocol */
+  u32 exp_updates_received;    /* Number of route updates received */
+  u32 exp_updates_rejected;    /* Number of route updates rejected by protocol */
+  u32 exp_updates_filtered;    /* Number of route updates rejected by filters */
+  u32 exp_updates_accepted;    /* Number of route updates accepted and exported */ 
+  u32 exp_withdraws_received;  /* Number of route withdraws received */
+  u32 exp_withdraws_accepted;  /* Number of route withdraws accepted and processed */
+};
+
 struct proto {
   node n;                              /* Node in *_proto_list */
   node glob_node;                      /* Node in global proto_list */
@@ -109,6 +134,7 @@ struct proto {
   u32 hash_key;                                /* Random key used for hashing of neighbors */
   bird_clock_t last_state_change;      /* Time of last state transition */
   char *last_state_name_announced;     /* Last state name we've announced to the user */
+  struct proto_stats stats;            /* Current protocol statistics */
 
   /*
    *   General protocol hooks:
index d608117b46de40ce3e9faafdc0694b697667ba0c..fb2feacaf411690b7247d4dd204bc2d8a2a5f482 100644 (file)
@@ -167,16 +167,27 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
 
   if (new)
     {
+      p->stats.exp_updates_received++;
+
       char *drop_reason = NULL;
       if ((class & IADDR_SCOPE_MASK) < p->min_scope)
-       drop_reason = "out of scope";
+       {
+         p->stats.exp_updates_rejected++;
+         drop_reason = "out of scope";
+       }
       else if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
-       drop_reason = "rejected by protocol";
+       {
+         p->stats.exp_updates_rejected++;
+         drop_reason = "rejected by protocol";
+       }
       else if (ok)
        rte_trace_out(D_FILTERS, p, new, "forced accept by protocol");
       else if (p->out_filter == FILTER_REJECT ||
               p->out_filter && f_run(p->out_filter, &new, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
-       drop_reason = "filtered out";
+       {
+         p->stats.exp_updates_filtered++;
+         drop_reason = "filtered out";
+       }
       if (drop_reason)
        {
          rte_trace_out(D_FILTERS, p, new, drop_reason);
@@ -185,7 +196,10 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
          new = NULL;
        }
     }
-  if (old && p->out_filter)
+  else
+    p->stats.exp_withdraws_received++;
+
+  if (old)
     {
       if (p->out_filter == FILTER_REJECT)
        old = NULL;
@@ -193,7 +207,7 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
        {
          ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL;
          ok = p->import_control ? p->import_control(p, &old, &tmpb, rte_update_pool) : 0;
-         if (ok < 0 || (!ok && f_run(p->out_filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
+         if (ok < 0 || (!ok && p->out_filter && f_run(p->out_filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
            {
              if (old != old0)
                rte_free(old);
@@ -201,6 +215,20 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
            }
        }
     }
+
+  if (!new && !old)
+    return;
+
+  if (new)
+    p->stats.exp_updates_accepted++;
+  else
+    p->stats.exp_withdraws_accepted++;
+
+  if (new)
+    p->stats.exp_routes++;
+  if (old)
+    p->stats.exp_routes--;
+
   if (p->debug & D_ROUTES)
     {
       if (new && old)
@@ -210,8 +238,6 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
       else if (old)
        rte_trace_out(D_ROUTES, p, old, "removed");
     }
-  if (!new && !old)
-    return;
   if (!new)
     p->rt_notify(p, net, NULL, old, NULL);
   else if (tmpa)
@@ -266,6 +292,14 @@ rte_announce(rtable *tab, int type, net *net, rte *new, rte *old, ea_list *tmpa)
   struct announce_hook *a;
   int class = ipa_classify(net->n.prefix);
 
+  if (type == RA_OPTIMAL)
+    {
+      if (new)
+       new->attrs->proto->stats.pref_routes++;
+      if (old)
+       old->attrs->proto->stats.pref_routes--;
+    }
+
   WALK_LIST(a, tab->hooks)
     {
       ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
@@ -363,6 +397,7 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
          if (new && rte_same(old, new))
            {
              /* No changes, ignore the new route */
+             p->stats.imp_updates_ignored++;
              rte_trace_in(D_ROUTES, p, new, "ignored");
              rte_free_quick(new);
              old->lastmod = now;
@@ -374,6 +409,22 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte
       k = &old->next;
     }
 
+  if (!old && !new)
+    {
+      p->stats.imp_withdraws_ignored++;
+      return;
+    }
+
+  if (new)
+    p->stats.imp_updates_accepted++;
+  else
+    p->stats.imp_withdraws_accepted++;
+
+  if (new)
+    p->stats.imp_routes++;
+  if (old)
+    p->stats.imp_routes--;
+
   rte_announce(table, RA_ANY, net, new, old, tmpa);
 
   if (new && rte_better(new, old_best))        /* It's a new optimal route => announce and relink it */
@@ -514,13 +565,16 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
       if (p->table != table)
        filter = FILTER_ACCEPT;
 
+      p->stats.imp_updates_received++;
       if (!rte_validate(new))
        {
          rte_trace_in(D_FILTERS, p, new, "invalid");
+         p->stats.imp_updates_invalid++;
          goto drop;
        }
       if (filter == FILTER_REJECT)
        {
+         p->stats.imp_updates_filtered++;
          rte_trace_in(D_FILTERS, p, new, "filtered out");
          goto drop;
        }
@@ -532,6 +586,7 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
          int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
          if (fr > F_ACCEPT)
            {
+             p->stats.imp_updates_filtered++;
              rte_trace_in(D_FILTERS, p, new, "filtered out");
              goto drop;
            }
@@ -542,6 +597,9 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new
        new->attrs = rta_lookup(new->attrs);
       new->flags |= REF_COW;
     }
+  else
+    p->stats.imp_withdraws_received++;
+
   rte_recalculate(table, net, p, src, new, tmpa);
   rte_update_unlock();
   return;
@@ -1025,8 +1083,11 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
       if (p2 && p2 != p0) ok = 0;
       if (ok && d->export_mode)
        {
-         int ic = (p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0);
-         if (ic < 0)
+         int class = ipa_classify(n->n.prefix);
+         int ic;
+         if ((class & IADDR_SCOPE_MASK) < p1->min_scope)
+           ok = 0;
+         else if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
            ok = 0;
          else if (!ic && d->export_mode > 1)
            {