]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
OSPF: Statistics
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 24 Oct 2018 14:15:28 +0000 (16:15 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 24 Oct 2018 14:15:28 +0000 (16:15 +0200)
Count packet rx/tx and error conditions, per iface and globally.
Show them in 'show ospf' / 'show ospf interface'.

Also removee one level of indentation for areas in 'show ospf' command.

proto/ospf/dbdes.c
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/lsack.c
proto/ospf/lsreq.c
proto/ospf/lsupd.c
proto/ospf/ospf.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/rt.c

index f211935f36974d3057afee46e8c484b29d06b58f..59490931d1a50eefcb1664caa9d446e6a0b6a4ae 100644 (file)
@@ -218,11 +218,15 @@ ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
 void
 ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
 {
+  struct ospf_iface *ifa = n->ifa;
+
   ASSERT(n->state > NEIGHBOR_EXSTART);
 
   if (!n->ldd_buffer)
   {
     log(L_WARN "%s: No DBDES packet for retransmit", p->p.name);
+    STATS(bad_dbdes);
+
     ospf_neigh_sm(n, INM_SEQMIS);
     return;
   }
@@ -251,18 +255,18 @@ ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_ne
     /* RFC 2328 10.6 and RFC 5340 4.2.2 */
 
     if (!lsa_type)
-      DROP1("LSA of unknown type");
+      DROP1(bad_dbdes, "LSA of unknown type");
 
     if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
-      DROP1("LSA with AS scope in stub area");
+      DROP1(bad_dbdes, "LSA with AS scope in stub area");
 
     /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
     if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
-      DROP1("rt-summary-LSA in stub area");
+      DROP1(bad_dbdes, "rt-summary-LSA in stub area");
 
     /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */
     if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
-      DROP1("LSA with invalid scope");
+      DROP1(bad_dbdes, "LSA with invalid scope");
 
     en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
     if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
@@ -311,6 +315,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
   if (plen < ospf_dbdes_hdrlen(p))
   {
     LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
+    STATS2(bad_pkt, dropped);
     return;
   }
 
@@ -397,13 +402,13 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
       goto duplicate;
 
     if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))
-      DROP("MS-bit mismatch", rcv_imms);
+      DROP(bad_dbdes, "MS-bit mismatch", rcv_imms);
 
     if (rcv_imms & DBDES_I)
-      DROP("I-bit mismatch", rcv_imms);
+      DROP(bad_dbdes, "I-bit mismatch", rcv_imms);
 
     if (rcv_options != n->options)
-      DROP("options mismatch", rcv_options);
+      DROP(bad_dbdes, "options mismatch", rcv_options);
 
     n->ddr = rcv_ddseq;
     n->imms = rcv_imms;
@@ -413,7 +418,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
       /* MASTER */
 
       if (rcv_ddseq != n->dds)
-       DROP("DD sequence number mismatch", rcv_ddseq);
+       DROP(bad_dbdes, "DD sequence number mismatch", rcv_ddseq);
 
       n->dds++;
 
@@ -435,7 +440,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
       /* SLAVE */
 
       if (rcv_ddseq != (n->dds + 1))
-       DROP("DD sequence number mismatch", rcv_ddseq);
+       DROP(bad_dbdes, "DD sequence number mismatch", rcv_ddseq);
 
       n->ddr = rcv_ddseq;
       n->dds = rcv_ddseq;
@@ -457,7 +462,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
        (rcv_ddseq == n->ddr))
       goto duplicate;
 
-    DROP("too late for DD exchange", n->state);
+    DROP(bad_dbdes, "too late for DD exchange", n->state);
 
   default:
     bug("Undefined interface state");
index e706ea0f63cfdf8dec6c98d1688779d06125346d..90905cde2d8cd4c0ce88c83408120198da37ba28 100644 (file)
@@ -206,7 +206,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
     struct ospf_hello2_packet *ps = (void *) pkt;
 
     if (plen < sizeof(struct ospf_hello2_packet))
-      DROP("too short", plen);
+      DROP(bad_pkt, "too short", plen);
 
     rcv_iface_id = 0;
     rcv_helloint = ntohs(ps->helloint);
@@ -218,12 +218,12 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
     int pxlen = u32_masklen(ntohl(ps->netmask));
     if (pxlen < 0)
-      DROP("prefix garbled", ntohl(ps->netmask));
+      DROP(bad_pkt, "prefix garbled", ntohl(ps->netmask));
 
     if ((ifa->type != OSPF_IT_VLINK) &&
        (ifa->type != OSPF_IT_PTP) &&
        ((uint) pxlen != ifa->addr->prefix.pxlen))
-      DROP("prefix length mismatch", pxlen);
+      DROP(bad_hello, "prefix length mismatch", pxlen);
 
     neighbors = ps->neighbors;
     neigh_count = (plen - sizeof(struct ospf_hello2_packet)) / sizeof(u32);
@@ -233,7 +233,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
     struct ospf_hello3_packet *ps = (void *) pkt;
 
     if (plen < sizeof(struct ospf_hello3_packet))
-      DROP("too short", plen);
+      DROP(bad_pkt, "too short", plen);
 
     rcv_iface_id = ntohl(ps->iface_id);
     rcv_helloint = ntohs(ps->helloint);
@@ -248,18 +248,18 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
   }
 
   if (rcv_helloint != ifa->helloint)
-    DROP("hello interval mismatch", rcv_helloint);
+    DROP(bad_hello, "hello interval mismatch", rcv_helloint);
 
   if (rcv_deadint != ifa->deadint)
-    DROP("dead interval mismatch", rcv_deadint);
+    DROP(bad_hello, "dead interval mismatch", rcv_deadint);
 
   /* Check whether bits E, N match */
   if ((rcv_options ^ loc_options) & (OPT_E | OPT_N))
-    DROP("area type mismatch", rcv_options);
+    DROP(bad_hello, "area type mismatch", rcv_options);
 
   /* RFC 5838 2.4 - AF-bit check unless on IPv6 unicast */
   if ((loc_options & OPT_AF) && !(loc_options & OPT_V6) && !(rcv_options & OPT_AF))
-    DROP("AF-bit mismatch", rcv_options);
+    DROP(bad_hello, "AF-bit mismatch", rcv_options);
 
   /* Check consistency of existing neighbor entry */
   if (n)
@@ -295,12 +295,12 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
       struct nbma_node *nn = find_nbma_node(ifa, faddr);
 
       if (!nn && ifa->strictnbma)
-       DROP1("new neighbor denied");
+       DROP1(bad_hello, "new neighbor denied");
 
       if (nn && (ifa->type == OSPF_IT_NBMA) &&
          (((rcv_priority == 0) && nn->eligible) ||
           ((rcv_priority > 0) && !nn->eligible)))
-       DROP("eligibility mismatch", rcv_priority);
+       DROP(bad_hello, "eligibility mismatch", rcv_priority);
 
       if (nn)
        nn->found = 1;
index e3d8d61bdb0ce9f3770fd496140ec089c0df4248..7c80c22684b060c7f1d6b6f8a00a85ee85f7fbea 100644 (file)
@@ -1327,6 +1327,23 @@ ospf_if_notify(struct proto *P, uint flags, struct iface *iface)
      iface_list even when down */
 }
 
+void
+ospf_iface_stats(int c, struct ospf_iface_stats *s)
+{
+  cli_msg(c, "\trx-hello %u rx-dbdes %u rx-lsreq %u rx-lsupd %u rx-lsack %u rx-vlink %u",
+         s->rx_pkts[0], s->rx_pkts[1], s->rx_pkts[2], s->rx_pkts[3], s->rx_pkts[4], s->rx_vlink);
+  cli_msg(c, "\ttx-hello %u tx-dbdes %u tx-lsreq %u tx-lsupd %u tx-lsack %u tx-vlink %u",
+         s->tx_pkts[0], s->tx_pkts[1], s->tx_pkts[2], s->tx_pkts[3], s->tx_pkts[4], s->tx_vlink);
+  cli_msg(c, "\tdropped %u bad-pkt %u bad-ver %u bad-au-type %u bad-auth %u bad-chksum %u",
+         s->dropped, s->bad_pkt, s->bad_ver, s->bad_au_type, s->bad_auth, s->bad_check);
+  cli_msg(c, "\tbad-ttl %u bad-src %u bad-area %u bad-nbr %u bad-pkt-type %u bad-state %u",
+         s->bad_ttl, s->bad_src, s->bad_area, s->bad_nbr, s->bad_pkt_type, s->bad_state);
+  cli_msg(c, "\tbad-hello %u bad-dbdes %u bad-lsreq %u bad-lsupd %u bad-lsack %u bad-lsa %u",
+         s->bad_hello, s->bad_dbdes, s->bad_lsreq, s->bad_lsupd, s->bad_lsack, s->bad_lsa);
+  cli_msg(c, "\tsk-error %u tx-queue-full %u tx-no-key %u",
+         s->sk_error, s->tx_queue_full, s->tx_no_key);
+}
+
 void
 ospf_iface_info(struct ospf_iface *ifa)
 {
@@ -1379,4 +1396,7 @@ ospf_iface_info(struct ospf_iface *ifa)
     cli_msg(-1015, "\tBackup designated router (ID): %R", ifa->bdrid);
     cli_msg(-1015, "\tBackup designated router (IP): %I", ifa->bdrip);
   }
+
+  cli_msg(-1015, "\tStatistics:");
+  ospf_iface_stats(-1015, &ifa->stats);
 }
index 251b5e47c6ff077f2496cd91db7b9b698bc6c224..3fd7e092bc1719bfb1a3bb8a0e782b004c5b3327 100644 (file)
@@ -133,7 +133,7 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
   struct ospf_proto *p = ifa->oa->po;
   struct ospf_lsa_header lsa, *lsas;
   struct top_hash_entry *ret, *en;
-  uint i, lsa_count;
+  uint i, lsa_count, bad = 0;
   u32 lsa_type, lsa_domain;
 
   /* RFC 2328 13.7 */
@@ -145,6 +145,7 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
   if (n->state < NEIGHBOR_EXCHANGE)
   {
     OSPF_TRACE(D_PACKETS, "LSACK packet ignored - lesser state than Exchange");
+    STATS2(bad_state, dropped);
     return;
   }
 
@@ -169,6 +170,10 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
                 ret->lsa.sn, ret->lsa.age, ret->lsa.checksum);
       OSPF_TRACE(D_PACKETS, "    It has: Seq: %08x, Age: %4u, Sum: %04x",
                 lsa.sn, lsa.age, lsa.checksum);
+
+      if (!bad++)
+       STATS(bad_lsack);
+
       continue;
     }
 
index 657c024785bb634289c28dca7ed88ec8d73f5d3e..b4f5f85abf1adf0719b84ff68b6f872628ef9ebf 100644 (file)
@@ -110,6 +110,7 @@ ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa,
   if (n->state < NEIGHBOR_EXCHANGE)
   {
     OSPF_TRACE(D_PACKETS, "LSREQ packet ignored - lesser state than Exchange");
+    STATS2(bad_state, dropped);
     return;
   }
 
@@ -134,6 +135,7 @@ ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa,
     {
       LOG_LSA1("Bad LSR (Type: %04x, Id: %R, Rt: %R) in LSREQ", type, id, rt);
       LOG_LSA2("  received from nbr %R on %s - LSA is missing", n->rid, ifa->ifname);
+      STATS2(bad_lsreq, dropped);
 
       ospf_neigh_sm(n, INM_BADLSREQ);
       return;
index a98c909820fd34d8e78cedd0e8b10a1cfc295a5b..37139b963c5ca4284d3f62d7f228754bf9ea9079 100644 (file)
@@ -487,6 +487,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
   if (plen < ospf_lsupd_hdrlen(p))
   {
     LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
+    STATS2(bad_pkt, dropped);
     return;
   }
 
@@ -495,6 +496,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
   if (n->state < NEIGHBOR_EXCHANGE)
   {
     OSPF_TRACE(D_PACKETS, "LSUPD packet ignored - lesser state than Exchange");
+    STATS2(bad_state, dropped);
     return;
   }
 
@@ -510,7 +512,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
     u32 lsa_len, lsa_type, lsa_domain;
 
     if ((offset + sizeof(struct ospf_lsa_header)) > plen)
-      DROP("too short", plen);
+      DROP(bad_pkt, "too short", plen);
 
     /* LSA header in network order */
     lsa_n = ((void *) pkt) + offset;
@@ -518,10 +520,10 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
     offset += lsa_len;
 
     if (offset > plen)
-      DROP("too short", plen);
+      DROP(bad_pkt, "too short", plen);
 
     if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header)))
-      DROP("invalid LSA length", lsa_len);
+      DROP(bad_pkt, "invalid LSA length", lsa_len);
 
     /* LSA header in host order */
     lsa_ntoh_hdr(lsa_n, &lsa);
@@ -643,7 +645,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
     /* 13. (6) - received LSA is in Link state request list (but not newer) */
     if (ospf_hash_find_entry(n->lsrqh, en) != NULL)
-      DROP1("error in LSA database exchange");
+      DROP1(bad_lsupd, "error in LSA database exchange");
 
     /* 13. (7) - received LSA is same */
     if (lsa_comp(&lsa, &en->lsa) == CMP_SAME)
@@ -679,6 +681,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
   skip:
     LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in LSUPD", lsa_type, lsa.id, lsa.rt);
     LOG_LSA2("  received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc);
+    STATS(bad_lsa);
   }
 
   /* Send direct LSACKs */
index df6c452e7fe55ca1909c503f9842d0fcb62569c7..07708e4fffba59384db3d84981b547afed12cd1b 100644 (file)
@@ -256,6 +256,9 @@ ospf_start(struct proto *P)
   p->gr = ospf_top_new(p, P->pool);
   s_init_list(&(p->lsal));
 
+  memset(&(p->iface_stats), 0, sizeof(struct ospf_iface_stats));
+  p->spf_count = 0;
+
   p->flood_event = ev_new(P->pool);
   p->flood_event->hook = ospf_flood_event;
   p->flood_event->data = p;
@@ -772,11 +775,15 @@ ospf_sh(struct proto *P)
   cli_msg(-1014, "Stub router: %s", (p->stub_router ? "Yes" : "No"));
   cli_msg(-1014, "RT scheduler tick: %d", p->tick);
   cli_msg(-1014, "Number of areas: %u", p->areano);
-  cli_msg(-1014, "Number of LSAs in DB:\t%u", p->gr->hash_entries);
+  cli_msg(-1014, "Number of LSAs in DB: %u", p->gr->hash_entries);
+  cli_msg(-1014, "Number of SPF runs: %u", p->spf_count);
+
+  cli_msg(-1014, "Statistics:");
+  ospf_iface_stats(-1014, &p->iface_stats);
 
   WALK_LIST(oa, p->area_list)
   {
-    cli_msg(-1014, "\tArea: %R (%u) %s", oa->areaid, oa->areaid,
+    cli_msg(-1014, "Area: %R (%u) %s", oa->areaid, oa->areaid,
            oa->areaid == 0 ? "[BACKBONE]" : "");
     ifano = 0;
     nno = 0;
@@ -795,26 +802,26 @@ ospf_sh(struct proto *P)
       }
     }
 
-    cli_msg(-1014, "\t\tStub:\t%s", oa_is_stub(oa) ? "Yes" : "No");
-    cli_msg(-1014, "\t\tNSSA:\t%s", oa_is_nssa(oa) ? "Yes" : "No");
-    cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No");
+    cli_msg(-1014, "\tStub:\t%s", oa_is_stub(oa) ? "Yes" : "No");
+    cli_msg(-1014, "\tNSSA:\t%s", oa_is_nssa(oa) ? "Yes" : "No");
+    cli_msg(-1014, "\tTransit:\t%s", oa->trcap ? "Yes" : "No");
 
     if (oa_is_nssa(oa))
-      cli_msg(-1014, "\t\tNSSA translation:\t%s%s", oa->translate ? "Yes" : "No",
+      cli_msg(-1014, "\tNSSA translation:\t%s%s", oa->translate ? "Yes" : "No",
              oa->translate == TRANS_WAIT ? " (run down)" : "");
-    cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano);
-    cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);
-    cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno);
+    cli_msg(-1014, "\tNumber of interfaces:\t%u", ifano);
+    cli_msg(-1014, "\tNumber of neighbors:\t%u", nno);
+    cli_msg(-1014, "\tNumber of adjacent neighbors:\t%u", adjno);
 
     firstfib = 1;
     FIB_WALK(&oa->net_fib, struct area_net, anet)
     {
       if(firstfib)
       {
-       cli_msg(-1014, "\t\tArea networks:");
+       cli_msg(-1014, "\tArea networks:");
        firstfib = 0;
       }
-      cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
+      cli_msg(-1014, "\t\t%1N\t%s\t%s", anet->fn.addr,
                anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
     }
     FIB_WALK_END;
@@ -824,10 +831,10 @@ ospf_sh(struct proto *P)
     {
       if(firstfib)
       {
-       cli_msg(-1014, "\t\tArea external networks:");
+       cli_msg(-1014, "\tArea external networks:");
        firstfib = 0;
       }
-      cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
+      cli_msg(-1014, "\t\t%1N\t%s\t%s", anet->fn.addr,
                anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
     }
     FIB_WALK_END;
index 54eeb74c112a41fb3839367deae926a74d102696..8e49a7c564348c1e38c9fa09418e0cb663de7093 100644 (file)
@@ -69,6 +69,8 @@
 #define MINLSARRIVAL           (1 S_)
 #define LSINFINITY             0xffffff
 
+#define OSPF_PKT_TYPES         5       /* HELLO_P .. LSACK_P */
+
 #define OSPF_DEFAULT_TICK 1
 #define OSPF_DEFAULT_STUB_COST 1000
 #define OSPF_DEFAULT_ECMP_LIMIT 16
@@ -197,6 +199,14 @@ struct ospf_iface_patt
 #define WAIT_DMH 4
   /* Value of Wait timer - not found it in RFC * - using 4*HELLO */
 
+struct ospf_iface_stats
+{
+  uint rx_pkts[OSPF_PKT_TYPES], tx_pkts[OSPF_PKT_TYPES], rx_vlink, tx_vlink;
+  uint dropped, bad_pkt, bad_ver, bad_au_type, bad_auth, bad_check;
+  uint bad_ttl, bad_src, bad_area, bad_rid, bad_nbr, bad_pkt_type;
+  uint bad_hello, bad_dbdes, bad_lsreq, bad_lsupd, bad_lsack, bad_state;
+  uint bad_lsa, sk_error, tx_queue_full, tx_no_key;
+};
 
 
 struct ospf_proto
@@ -230,6 +240,8 @@ struct ospf_proto
   sock *vlink_sk;              /* IP socket used for vlink TX */
   u32 router_id;
   u32 last_vlink_id;           /* Interface IDs for vlinks (starts at 0x80000000) */
+  struct ospf_iface_stats iface_stats;
+  uint spf_count;              /* Number of SPF calculations */
   struct tbf log_pkt_tbf;      /* TBF for packet messages */
   struct tbf log_lsa_tbf;      /* TBF for LSA messages */
 };
@@ -311,6 +323,7 @@ struct ospf_iface
   struct top_hash_entry *net_lsa;      /* Originated network LSA */
   struct top_hash_entry *pxn_lsa;      /* Originated prefix LSA */
   struct top_hash_entry **flood_queue; /* LSAs queued for LSUPD */
+  struct ospf_iface_stats stats; /* Packet statistics */
   u8 update_link_lsa;
   u8 update_net_lsa;
   u16 flood_queue_used;                /* The current number of LSAs in flood_queue */
@@ -903,6 +916,7 @@ struct ospf_iface *ospf_iface_find(struct ospf_proto *p, struct iface *what);
 void ospf_if_notify(struct proto *P, uint flags, struct iface *iface);
 void ospf_ifa_notify2(struct proto *P, uint flags, struct ifa *a);
 void ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a);
+void ospf_iface_stats(int c, struct ospf_iface_stats *s);
 void ospf_iface_info(struct ospf_iface *ifa);
 void ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip);
 void ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip);
@@ -951,8 +965,10 @@ static inline void ospf_send_to_des(struct ospf_iface *ifa)
 }
 
 #ifndef PARSER
-#define DROP(DSC,VAL) do { err_dsc = DSC; err_val = VAL; goto drop; } while(0)
-#define DROP1(DSC) do { err_dsc = DSC; goto drop; } while(0)
+#define STATS(KEY) do { ifa->stats.KEY++; p->iface_stats.KEY++; } while(0)
+#define STATS2(KEY1, KEY2) do { STATS(KEY1); STATS(KEY2); } while(0)
+#define DROP(KEY,DSC,VAL) do { STATS(KEY); STATS(dropped); err_dsc = DSC; err_val = VAL; goto drop; } while(0)
+#define DROP1(KEY,DSC) do { STATS(KEY); STATS(dropped); err_dsc = DSC; goto drop; } while(0)
 #define SKIP(DSC) do { err_dsc = DSC; goto skip; } while(0)
 #endif
 
index 38d7a75face5181bda39b2c1a63537ed60ca6733..b0bbaae1657777ab68ca216d342242b331f33499 100644 (file)
@@ -36,6 +36,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
 static void
 ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
 {
+  struct ospf_proto *p = ifa->oa->po;
   struct password_item *pass = NULL;
   union ospf_auth *auth = (void *) (pkt + 1);
 
@@ -52,7 +53,8 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
     pass = password_find(ifa->passwords, 1);
     if (!pass)
     {
-      log(L_ERR "No suitable password found for authentication");
+      log(L_ERR "%s: No suitable password found for authentication", p->p.name);
+      STATS(tx_no_key);
       return;
     }
     strncpy(auth->password, pass->password, sizeof(auth->password));
@@ -69,7 +71,8 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
     pass = password_find(ifa->passwords, 0);
     if (!pass)
     {
-      log(L_ERR "No suitable password found for authentication");
+      log(L_ERR "%s: No suitable password found for authentication", p->p.name);
+      STATS(tx_no_key);
       return;
     }
 
@@ -129,7 +132,7 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
   u8 autype = pkt->autype;
 
   if (autype != ifa->autype)
-    DROP("authentication method mismatch", autype);
+    DROP(bad_au_type, "authentication method mismatch", autype);
 
   switch (autype)
   {
@@ -139,25 +142,25 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
   case OSPF_AUTH_SIMPLE:
     pass = password_find(ifa->passwords, 1);
     if (!pass)
-      DROP1("no password found");
+      DROP1(bad_auth, "no password found");
 
     if (!password_verify(pass, auth->password, sizeof(auth->password)))
-      DROP("wrong password", pass->id);
+      DROP(bad_auth, "wrong password", pass->id);
 
     return 1;
 
   case OSPF_AUTH_CRYPT:
     pass = password_find_by_id(ifa->passwords, auth->c32.keyid);
     if (!pass)
-      DROP("no suitable password found", auth->c32.keyid);
+      DROP(bad_auth, "no suitable password found", auth->c32.keyid);
 
     uint auth_len = mac_type_length(pass->alg);
 
     if (plen + auth->c32.len > len)
-      DROP("packet length mismatch", len);
+      DROP(bad_pkt, "packet length mismatch", len);
 
     if (auth->c32.len != auth_len)
-      DROP("wrong authentication length", auth->c32.len);
+      DROP(bad_auth, "wrong authentication length", auth->c32.len);
 
     u32 rcv_csn = ntohl(auth->c32.csn);
     if (n && (rcv_csn < n->csn))
@@ -167,6 +170,7 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
       LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
                   "lower sequence number (rcv %u, old %u)",
                   n->rid, ifa->ifname, rcv_csn, n->csn);
+      STATS2(bad_auth, dropped);
       return 0;
     }
 
@@ -182,7 +186,7 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
 
     if (!mac_verify(pass->alg, pass->password, pass->length,
                    (byte *) pkt, plen + auth_len, auth_data))
-      DROP("wrong authentication code", pass->id);
+      DROP(bad_auth, "wrong authentication code", pass->id);
 
     if (n)
       n->csn = rcv_csn;
@@ -268,17 +272,17 @@ ospf_rx_hook(sock *sk, uint len)
 
 
   if (pkt == NULL)
-    DROP("bad IP header", len);
+    DROP(bad_pkt, "bad IP header", len);
 
   if (len < sizeof(struct ospf_packet))
-    DROP("too short", len);
+    DROP(bad_pkt, "too short", len);
 
   if (pkt->version != ospf_get_version(p))
-    DROP("version mismatch", pkt->version);
+    DROP(bad_ver, "version mismatch", pkt->version);
 
   uint plen = ntohs(pkt->length);
   if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
-    DROP("invalid length", plen);
+    DROP(bad_pkt, "invalid length", plen);
 
   if (sk->flags & SKF_TRUNCATED)
   {
@@ -290,11 +294,11 @@ ospf_rx_hook(sock *sk, uint len)
     if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
       sk_set_rbsize(sk, bs);
 
-    DROP("truncated", plen);
+    DROP(sk_error, "truncated", plen);
   }
 
   if (plen > len)
-    DROP("length mismatch", plen);
+    DROP(bad_pkt, "length mismatch", plen);
 
   if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT))
   {
@@ -303,7 +307,7 @@ ospf_rx_hook(sock *sk, uint len)
     void *body = ((void *) pkt) + hlen;
 
     if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
-      DROP1("invalid checksum");
+      DROP1(bad_check, "invalid checksum");
   }
 
   /* Third, we resolve associated iface and handle vlinks. */
@@ -321,7 +325,7 @@ ospf_rx_hook(sock *sk, uint len)
 
     /* It is real iface, source should be local (in OSPFv2) */
     if (ospf_is_v2(p) && !src_local)
-      DROP1("strange source address");
+      DROP1(bad_src, "strange source address");
 
     goto found;
   }
@@ -365,7 +369,7 @@ ospf_rx_hook(sock *sk, uint len)
     if (instance_id != ifa->instance_id)
       return 1;
 
-    DROP("area mismatch", areaid);
+    DROP(bad_area, "area mismatch", areaid);
   }
 
 
@@ -378,13 +382,13 @@ found:
 
   /* TTL check must be done after instance dispatch */
   if (ifa->check_ttl && (sk->rcv_ttl < 255))
-    DROP("wrong TTL", sk->rcv_ttl);
+    DROP(bad_ttl, "wrong TTL", sk->rcv_ttl);
 
   if (rid == p->router_id)
-    DROP1("my own router ID");
+    DROP1(bad_nbr, "my own router ID");
 
   if (rid == 0)
-    DROP1("zero router ID");
+    DROP1(bad_nbr, "zero router ID");
 
   /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
   uint t = ifa->type;
@@ -398,13 +402,23 @@ found:
   {
     OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
               rid, ifa->ifname, sk->faddr);
+    STATS2(bad_nbr, dropped);
     return 1;
   }
 
+  /* Check packet type here, ospf_pkt_checkauth3() expects valid values */
+  if (pkt->type < HELLO_P || pkt->type > LSACK_P)
+    DROP(bad_pkt_type, "invalid packet type", pkt->type);
+
   /* ospf_pkt_checkauth() has its own error logging */
   if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, len))
     return 1;
 
+  STATS(rx_pkts[pkt->type - 1]);
+
+  if (ifa->type == OSPF_IT_VLINK)
+    STATS(rx_vlink);
+
   switch (pkt->type)
   {
   case HELLO_P:
@@ -426,9 +440,6 @@ found:
   case LSACK_P:
     ospf_receive_lsack(pkt, ifa, n);
     break;
-
-  default:
-    DROP("invalid packet type", pkt->type);
   };
   return 1;
 
@@ -455,6 +466,7 @@ ospf_err_hook(sock * sk, int err)
   struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
   struct ospf_proto *p = ifa->oa->po;
   log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err);
+  STATS(sk_error);
 }
 
 void
@@ -462,6 +474,9 @@ ospf_verr_hook(sock *sk, int err)
 {
   struct ospf_proto *p = (struct ospf_proto *) (sk->data);
   log(L_ERR "%s: Vlink socket error: %M", p->p.name, err);
+
+  /* Cannot use STATS() as there is no specific iface */
+  p->iface_stats.sk_error++;
 }
 
 void
@@ -469,6 +484,7 @@ ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
 {
   sock *sk = ifa->sk;
   struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
+  struct ospf_proto *p = ifa->oa->po;
   uint plen = ntohs(pkt->length);
 
   if (ospf_is_v2(ifa->oa->po))
@@ -476,7 +492,16 @@ ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
 
   int done = sk_send_to(sk, plen, dst, 0);
   if (!done)
-    log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
+  {
+    log(L_WARN "%s: TX queue full on %s", p->p.name, ifa->ifname);
+    STATS(tx_queue_full);
+    return;
+  }
+
+  STATS(tx_pkts[pkt->type - 1]);
+
+  if (ifa->type == OSPF_IT_VLINK)
+    STATS(tx_vlink);
 }
 
 void
index c0fe218af14a482868fcb7d88bd05370faa0df99..dd85ea75ef2f9b767398f37bf8440a469dcdffe3 100644 (file)
@@ -1649,6 +1649,7 @@ ospf_rt_spf(struct ospf_proto *p)
     return;
 
   OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
+  p->spf_count++;
 
   /* 16. (1) */
   ospf_rt_reset(p);