]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Statistics
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Fri, 30 Nov 2018 21:10:14 +0000 (22:10 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Fri, 30 Nov 2018 21:10:14 +0000 (22:10 +0100)
Count message rx/tx, enqueued buckets/prefixes and recoverable
error conditions. Show them in 'show protocol all'

proto/bgp/attrs.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/packets.c

index 0f41f818399557a36d23cf3308cd7d9a428a26b5..e53b09d81b780d034a54f52f170490d32f3cf07e 100644 (file)
@@ -1094,8 +1094,10 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
     ADVANCE(pos, len, alen);
   }
 
+#define FAIL(KEY) ({ STATS(KEY); goto fail; })
+
   if (s->err_withdraw)
-    goto withdraw;
+    FAIL(bad_attribute);
 
   /* If there is no reachability NLRI, we are finished */
   if (!s->ip_reach_len && !s->mp_reach_len)
@@ -1104,10 +1106,10 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
 
   /* Handle missing mandatory attributes; RFC 7606 3 (d) */
   if (!BIT32_TEST(s->attrs_seen, BA_ORIGIN))
-  { REPORT(NO_MANDATORY, "ORIGIN"); goto withdraw; }
+  { REPORT(NO_MANDATORY, "ORIGIN"); FAIL(no_mandatory); }
 
   if (!BIT32_TEST(s->attrs_seen, BA_AS_PATH))
-  { REPORT(NO_MANDATORY, "AS_PATH"); goto withdraw; }
+  { REPORT(NO_MANDATORY, "AS_PATH"); FAIL(no_mandatory); }
 
   /* When receiving attributes from non-AS4-aware BGP speaker, we have to
      reconstruct AS_PATH and AGGREGATOR attributes; RFC 6793 4.2.3 */
@@ -1116,19 +1118,19 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
 
   /* Reject routes with our ASN in AS_PATH attribute */
   if (bgp_as_path_loopy(p, attrs, p->local_as))
-    goto withdraw;
+    FAIL(loopy);
 
   /* Reject routes with our Confederation ID in AS_PATH attribute; RFC 5065 4.0 */
   if ((p->public_as != p->local_as) && bgp_as_path_loopy(p, attrs, p->public_as))
-    goto withdraw;
+    FAIL(loopy);
 
   /* Reject routes with our Router ID in ORIGINATOR_ID attribute; RFC 4456 8 */
   if (p->is_internal && bgp_originator_id_loopy(p, attrs))
-    goto withdraw;
+    FAIL(loopy);
 
   /* Reject routes with our Cluster ID in CLUSTER_LIST attribute; RFC 4456 8 */
   if (p->rr_client && bgp_cluster_list_loopy(p, attrs))
-    goto withdraw;
+    FAIL(loopy);
 
   /* If there is no local preference, define one */
   if (!BIT32_TEST(s->attrs_seen, BA_LOCAL_PREF))
@@ -1141,8 +1143,11 @@ framing_error:
   /* RFC 7606 4 - handle attribute framing errors */
   REPORT("Malformed attribute list - framing error (%u/%u) at %d",
         alen, len, (int) (pos - s->attrs));
+  FAIL(bad_alist);
+
+#undef FAIL
 
-withdraw:
+fail:
   /* RFC 7606 5.2 - handle missing NLRI during errors */
   if (!s->ip_reach_len && !s->mp_reach_len)
     bgp_parse_error(s, 1);
index 9db26050cc5b1a89ed96186540b6bf7a7f0b5f70..0e60d88d86bde1d7b70dc2d839a695ba6a8e460e 100644 (file)
@@ -1328,6 +1328,8 @@ bgp_start(struct proto *P)
   p->source_addr = p->cf->local_ip;
   p->link_addr = IPA_NONE;
 
+  memset(&(p->stats), 0, sizeof(struct bgp_stats));
+
   /* Lock all channels when in GR recovery mode */
   if (p->p.gr_recovery && p->cf->gr_mode)
   {
@@ -2104,6 +2106,15 @@ bgp_show_proto_info(struct proto *P)
            tm_remains(p->conn->keepalive_timer), p->conn->keepalive_time);
   }
 
+  struct bgp_stats *s = &p->stats;
+  cli_msg(-1006, "    Statistics:");
+  cli_msg(-1006, "      rx-open %u  rx-update %u  rx-notify %u  rx-keepalive %u  rx-refresh %u",
+         s->rx_pkts[0], s->rx_pkts[1], s->rx_pkts[2], s->rx_pkts[3], s->rx_pkts[4]);
+  cli_msg(-1006, "      tx-open %u  tx-update %u  tx-notify %u  tx-keepalive %u  tx-refresh %u",
+         s->tx_pkts[0], s->tx_pkts[1], s->tx_pkts[2], s->tx_pkts[3], s->tx_pkts[4]);
+  cli_msg(-1006, "      bad-alist %u  bad-attribute %u  bad-next-hop %u  no-mandatory %u  loopy %u",
+         s->bad_alist, s->bad_attribute, s->bad_next_hop, s->no_mandatory, s->loopy);
+
   if ((p->last_error_class != BE_NONE) &&
       (p->last_error_class != BE_MAN_DOWN))
   {
@@ -2120,6 +2131,9 @@ bgp_show_proto_info(struct proto *P)
 
       if (c->c.channel_state == CS_UP)
       {
+       cli_msg(-1006, "    Enqueued updates:   %u", c->bucket_hash.count);
+       cli_msg(-1006, "    Enqueued prefixes:  %u", c->prefix_hash.count);
+
        if (ipa_zero(c->link_addr))
          cli_msg(-1006, "    BGP Next hop:   %I", c->next_hop_addr);
        else
index 30424abb852cc52fd7cd974554a3c4ff8b34397b..3a1efc8ccbac68eff755bc606e29dbf37b246c6c 100644 (file)
@@ -55,6 +55,8 @@ struct eattr;
 #define BGP_AF_FLOW4           BGP_AF( BGP_AFI_IPV4, BGP_SAFI_FLOW )
 #define BGP_AF_FLOW6           BGP_AF( BGP_AFI_IPV6, BGP_SAFI_FLOW )
 
+#define BGP_PKT_TYPES          5       /* PKT_OPEN .. PKT_ROUTE_REFRESH */
+
 
 struct bgp_write_state;
 struct bgp_parse_state;
@@ -196,6 +198,14 @@ struct bgp_caps {
 #define WALK_AF_CAPS(caps,ac) \
   for (ac = caps->af_data; ac < &caps->af_data[caps->af_count]; ac++)
 
+struct bgp_stats {
+  uint rx_pkts[BGP_PKT_TYPES], tx_pkts[BGP_PKT_TYPES];
+  uint bad_alist, bad_attribute, bad_next_hop, no_mandatory, loopy;
+};
+
+#ifndef PARSER
+#define STATS(KEY) ({ p->stats.KEY++; })
+#endif
 
 struct bgp_socket {
   node n;                              /* Node in global bgp_sockets */
@@ -254,6 +264,7 @@ struct bgp_proto {
   struct neighbor *neigh;              /* Neighbor entry corresponding to remote ip, NULL if multihop */
   struct bgp_socket *sock;             /* Shared listening socket */
   struct bfd_request *bfd_req;         /* BFD request, if BFD is used */
+  struct bgp_stats stats;              /* Packet statistics */
   ip_addr source_addr;                 /* Local address used as an advertised next hop */
   ip_addr link_addr;                   /* Link-local version of source_addr */
   event *event;                                /* Event for respawning and shutting process */
index aa08732dc35fee8210bb8a77ed06fe23a8e88022..1376ba6736a9557d8d08d92a2a03526919f9f67a 100644 (file)
@@ -2174,6 +2174,7 @@ bgp_rx_end_mark(struct bgp_parse_state *s, u32 afi)
 static inline void
 bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_list *ea, byte *nh, uint nh_len)
 {
+  struct bgp_proto *p = s->proto;
   struct bgp_channel *c = bgp_get_channel(s->proto, afi);
   rta *a = NULL;
 
@@ -2207,7 +2208,10 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
 
     /* Handle withdraw during next hop decoding */
     if (s->err_withdraw)
+    {
+      STATS(bad_next_hop);
       a = NULL;
+    }
   }
 
   c->desc->decode_nlri(s, nlri, len, a);
@@ -2446,6 +2450,7 @@ found:
 static inline int
 bgp_send(struct bgp_conn *conn, uint type, uint len)
 {
+  struct bgp_proto *p = conn->bgp;
   sock *sk = conn->sk;
   byte *buf = sk->tbuf;
 
@@ -2453,6 +2458,7 @@ bgp_send(struct bgp_conn *conn, uint type, uint len)
   put_u16(buf+16, len);
   buf[18] = type;
 
+  STATS(tx_pkts[type - 1]);
   return sk_send(sk, len);
 }
 
@@ -2812,13 +2818,22 @@ bgp_rx_keepalive(struct bgp_conn *conn)
 static void
 bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
 {
+  struct bgp_proto *p = conn->bgp;
   byte type = pkt[18];
 
   DBG("BGP: Got packet %02x (%d bytes)\n", type, len);
 
-  if (conn->bgp->p.mrtdump & MD_MESSAGES)
+  if (p->p.mrtdump & MD_MESSAGES)
     mrt_dump_bgp_packet(conn, pkt, len);
 
+  if (type < PKT_OPEN || type > PKT_ROUTE_REFRESH)
+  {
+    bgp_error(conn, 1, 3, pkt+18, 1);
+    return;
+  }
+
+  STATS(rx_pkts[type - 1]);
+
   switch (type)
   {
   case PKT_OPEN:               return bgp_rx_open(conn, pkt, len);
@@ -2826,7 +2841,6 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
   case PKT_NOTIFICATION:       return bgp_rx_notification(conn, pkt, len);
   case PKT_KEEPALIVE:          return bgp_rx_keepalive(conn);
   case PKT_ROUTE_REFRESH:      return bgp_rx_route_refresh(conn, pkt, len);
-  default:                     bgp_error(conn, 1, 3, pkt+18, 1);
   }
 }