[ospfd] Additional NSM neighbour state change stats/information

2006-07-25 Paul Jakma <paul.jakma@sun.com>

	* ospf_neigbor.h: (struct ospf_neighbor) Add some additional
	  neighbour state statistics fields, timestamps for progressive
	  and regressive state changes, and pointer to event string
	  for the latter state change.
	* ospf_nsm.c: (nsm_notice_state_change) Update new state changs
	  history as required.
	* ospf_vty.c: (show_ip_ospf_neighbor_detail_sub) Print out above
	  new per-neighbour state change stats.
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
index 1564bdb..2c23774 100644
--- a/ospfd/ChangeLog
+++ b/ospfd/ChangeLog
@@ -1,3 +1,14 @@
+2006-07-25 Paul Jakma <paul.jakma@sun.com>
+
+	* ospf_neigbor.h: (struct ospf_neighbor) Add some additional
+	  neighbour state statistics fields, timestamps for progressive
+	  and regressive state changes, and pointer to event string
+	  for the latter state change.
+	* ospf_nsm.c: (nsm_notice_state_change) Update new state changs
+	  history as required.
+	* ospf_vty.c: (show_ip_ospf_neighbor_detail_sub) Print out above
+	  new per-neighbour state change stats.
+
 2006-07-10 Paul Jakma <paul.jakma@sun.com>
 
 	* ospf_nsm.c: (nsm_change_state) call nsm_clear_adj for all
diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h
index 9b7ff36..25f1352 100644
--- a/ospfd/ospf_neighbor.h
+++ b/ospfd/ospf_neighbor.h
@@ -80,11 +80,14 @@
   struct thread *t_ls_upd;
   struct thread *t_hello_reply;
 
-  /* Statistics Field */
-  u_int32_t state_change;
-  struct timeval ts_last_change;
-  const char *last_event_str;
+  /* NBMA configured neighbour */
   struct ospf_nbr_nbma *nbr_nbma;
+
+  /* Statistics */
+  struct timeval ts_last_progress;  /* last advance of NSM            */
+  struct timeval ts_last_regress;   /* last regressive NSM change     */
+  const char *last_regress_str;     /* Event which last regressed NSM */
+  u_int32_t state_change;           /* NSM state change counter       */
 };
 
 /* Macros. */
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index ff0a52d..8329a4f 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -615,8 +615,14 @@
                 LOOKUP (ospf_nsm_state_msg, next_state),
                 ospf_nsm_event_str [event]);
 
-  nbr->ts_last_change = recent_time;
-  nbr->last_event_str = ospf_nsm_event_str [event];
+  /* Advance in NSM */
+  if (next_state > nbr->state)
+    nbr->ts_last_progress = recent_time;
+  else /* regression in NSM */
+    {
+      nbr->ts_last_regress = recent_time;
+      nbr->last_regress_str = ospf_nsm_event_str [event];
+    }
 
 #ifdef HAVE_SNMP
   /* Terminal state or regression */ 
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 44049d8..912f1d0 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -3155,12 +3155,21 @@
 	   nbr->priority, LOOKUP (ospf_nsm_state_msg, nbr->state));
   /* Show state changes. */
   vty_out (vty, " %d state changes%s", nbr->state_change, VTY_NEWLINE);
-  if (nbr->ts_last_change.tv_sec || nbr->ts_last_change.tv_usec)
+  if (nbr->ts_last_progress.tv_sec || nbr->ts_last_progress.tv_usec)
     {
-      struct timeval res = tv_sub (recent_time, nbr->ts_last_change);
-      vty_out (vty, "    Last state change %s ago, due to %s%s",
+      struct timeval res = tv_sub (recent_time, nbr->ts_last_progress);
+      vty_out (vty, "    Most recent state change statistics:%s",
+               VTY_NEWLINE);
+      vty_out (vty, "      Progressive change %s ago%s",
                ospf_timeval_dump (&res, timebuf, sizeof(timebuf)),
-               (nbr->last_event_str ? nbr->last_event_str : "??"),
+               VTY_NEWLINE);
+    }
+  if (nbr->ts_last_regress.tv_sec || nbr->ts_last_regress.tv_usec)
+    {
+      struct timeval res = tv_sub (recent_time, nbr->ts_last_regress);
+      vty_out (vty, "      Regressive change %s ago, due to %s%s",
+               ospf_timeval_dump (&res, timebuf, sizeof(timebuf)),
+               (nbr->last_regress_str ? nbr->last_regress_str : "??"),
                VTY_NEWLINE);
     }
   /* Show Designated Rotuer ID. */