ospf6d: add SPF logs, statistics, and display of SPF parameters

Signed-off-by: Pradosh Mohapatra <pmohapat at cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma at cumulusnetworks.com>
[DL: adapted to rebase / readded randomly lost line]
[DL: killed timeval_subtract]
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/ospf6d/ospf6_spf.h b/ospf6d/ospf6_spf.h
index 6c40424..b3481dc 100644
--- a/ospf6d/ospf6_spf.h
+++ b/ospf6d/ospf6_spf.h
@@ -79,11 +79,77 @@
 #define VERTEX_IS_TYPE(t, v) \
   ((v)->type == OSPF6_VERTEX_TYPE_ ## t ? 1 : 0)
 
+/* What triggered the SPF? */
+#define OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED         (1 << 0)
+#define OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED       (1 << 1)
+#define OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED        (1 << 2)
+#define OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED      (1 << 3)
+#define OSPF6_SPF_FLAGS_LINK_LSA_ADDED           (1 << 4)
+#define OSPF6_SPF_FLAGS_LINK_LSA_REMOVED         (1 << 5)
+#define OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED    (1 << 6)
+#define OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED   (1 << 7)
+
+static inline void
+ospf6_set_spf_reason (struct ospf6* ospf, unsigned int reason)
+{
+  ospf->spf_reason |= reason;
+}
+
+static inline void
+ospf6_reset_spf_reason (struct ospf6 *ospf)
+{
+  ospf->spf_reason = 0;
+}
+
+static inline unsigned int
+ospf6_lsadd_to_spf_reason (struct ospf6_lsa *lsa)
+{
+  unsigned int reason = 0;
+
+  switch (ntohs (lsa->header->type))
+    {
+    case OSPF6_LSTYPE_ROUTER:
+      reason = OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED;
+      break;
+    case OSPF6_LSTYPE_NETWORK:
+      reason = OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED;
+      break;
+    case OSPF6_LSTYPE_LINK:
+      reason = OSPF6_SPF_FLAGS_LINK_LSA_ADDED;
+      break;
+    default:
+      break;
+    }
+  return (reason);
+}
+
+static inline unsigned int
+ospf6_lsremove_to_spf_reason (struct ospf6_lsa *lsa)
+{
+  unsigned int reason = 0;
+
+  switch (ntohs (lsa->header->type))
+    {
+    case OSPF6_LSTYPE_ROUTER:
+      reason = OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED;
+      break;
+    case OSPF6_LSTYPE_NETWORK:
+      reason = OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED;
+      break;
+    case OSPF6_LSTYPE_LINK:
+      reason = OSPF6_SPF_FLAGS_LINK_LSA_REMOVED;
+      break;
+    default:
+      break;
+    }
+  return (reason);
+}
+
 extern void ospf6_spf_table_finish (struct ospf6_route_table *result_table);
 extern void ospf6_spf_calculation (u_int32_t router_id,
                                    struct ospf6_route_table *result_table,
                                    struct ospf6_area *oa);
-extern void ospf6_spf_schedule (struct ospf6 *ospf);
+extern void ospf6_spf_schedule (struct ospf6 *ospf, unsigned int reason);
 
 extern void ospf6_spf_display_subtree (struct vty *vty, const char *prefix,
                                        int rest, struct ospf6_vertex *v);
@@ -92,6 +158,7 @@
 extern int config_write_ospf6_debug_spf (struct vty *vty);
 extern void install_element_ospf6_debug_spf (void);
 extern void ospf6_spf_init (void);
+extern void ospf6_spf_reason_string (unsigned int reason, char *buf, int size);
 
 #endif /* OSPF6_SPF_H */