ospf6d: fix neighbor state machine (faster lsdb sync, RFC compliance)

The OSPFv3 code doesn't do the following things right as part of an adjacency
bringup:
 - Transmit DbDesc frames appropriately to ensure faster state transition to
   Loading state
 - Transmit LsReq frames when switching to exchange state and on receipt of
   an LS update in Loading state
 - Requesting LSAs multiple times in LsReq.

It currently uses retransmit timer expiry to send the LsReq and DbDesc frames
which significantly slows down large lsdb syncs.

Signed-off-by: Dinesh G Dutt <ddutt at cumulusnetworks.com>
Reviewed-by: Scott Feldman <sfeldma at cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index beae699..e02a432 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -206,8 +206,8 @@
 void
 ospf6_install_lsa (struct ospf6_lsa *lsa)
 {
-  struct ospf6_lsa *old;
   struct timeval now;
+  struct ospf6_lsa *old;
 
   if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
       IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
@@ -290,7 +290,7 @@
               if (ospf6_lsa_compare (lsa, req) > 0)
                 {
                   if (is_debug)
-                    zlog_debug ("Requesting is newer, next neighbor");
+                    zlog_debug ("Requesting is older, next neighbor");
                   continue;
                 }
 
@@ -298,18 +298,30 @@
                  examin next neighbor */
               if (ospf6_lsa_compare (lsa, req) == 0)
                 {
-                  if (is_debug)
-                    zlog_debug ("Requesting the same, remove it, next neighbor");
+		  if (is_debug)
+		    zlog_debug ("Requesting the same, remove it, next neighbor");
+		  if (req == on->last_ls_req)
+		    {
+		      ospf6_lsa_unlock (req);
+		      on->last_ls_req = NULL;
+		    }
                   ospf6_lsdb_remove (req, on->request_list);
+		  ospf6_check_nbr_loading (on);
                   continue;
                 }
 
               /* If the new LSA is more recent, delete from request-list */
               if (ospf6_lsa_compare (lsa, req) < 0)
                 {
-                  if (is_debug)
-                    zlog_debug ("Received is newer, remove requesting");
+		  if (is_debug)
+		    zlog_debug ("Received is newer, remove requesting");
+		  if (req == on->last_ls_req)
+		    {
+		      ospf6_lsa_unlock (req);
+		      on->last_ls_req = NULL;
+		    }
                   ospf6_lsdb_remove (req, on->request_list);
+		  ospf6_check_nbr_loading (on);
                   /* fall through */
                 }
             }
@@ -796,7 +808,7 @@
     {
       /* log */
       if (is_debug)
-        zlog_debug ("Drop MaxAge LSA with direct acknowledgement.");
+	zlog_debug ("Drop MaxAge LSA with direct acknowledgement.");
 
       /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
       ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
@@ -950,8 +962,8 @@
               zlog_debug ("The LSA is in Seqnumber Wrapping");
               zlog_debug ("MaxAge & MaxSeqNum, discard");
             }
-          ospf6_lsa_delete (new);
-          return;
+	  ospf6_lsa_delete (new);
+	  return;
         }
 
       /* Otherwise, Send database copy of this LSA to this neighbor */
@@ -968,8 +980,8 @@
           if (from->thread_send_lsupdate == NULL)
             from->thread_send_lsupdate =
               thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
-          ospf6_lsa_delete (new);
-          return;
+	  ospf6_lsa_delete (new);
+	  return;
         }
       return;
     }