ospf6d: add p2p interface support

Signed-off-by: Dinesh G Dutt <ddutt at cumulusnetworks.com>
Signed-off-by: Ayan Banerjee <ayabaner at gmail.com>
Reviewed-by: Scott Feldman <sfeldma at cumulusnetworks.com>
Reviewed-by: James Li <jli at cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index b35aa1a..31db9a4 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -1785,6 +1785,7 @@
   struct ospf6_dbdesc *dbdesc;
   u_char *p;
   struct ospf6_lsa *lsa;
+  struct in6_addr *dst;
 
   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
   on->thread_send_dbdesc = (struct thread *) NULL;
@@ -1848,8 +1849,14 @@
   oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
   oh->length = htons (p - sendbuf);
 
-  ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
-              on->ospf6_if, oh);
+
+  if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
+    dst = &allspfrouters6;
+  else
+    dst = &on->linklocal_addr;
+
+  ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
+
   return 0;
 }
 
@@ -1952,8 +1959,13 @@
   oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
   oh->length = htons (p - sendbuf);
 
-  ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+  if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
+    ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
               on->ospf6_if, oh);
+  else
+    ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+		on->ospf6_if, oh);
+
   return 0;
 }
 
@@ -1964,7 +1976,7 @@
   struct ospf6_header *oh;
   struct ospf6_lsupdate *lsupdate;
   u_char *p;
-  int num;
+  int lsa_cnt;
   struct ospf6_lsa *lsa;
 
   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
@@ -1981,22 +1993,13 @@
       return 0;
     }
 
-  /* if we have nothing to send, return */
-  if (on->lsupdate_list->count == 0 &&
-      on->retrans_list->count == 0)
-    {
-      if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
-        zlog_debug ("Quit to send (nothing to send)");
-      return 0;
-    }
-
   memset (sendbuf, 0, iobuflen);
   oh = (struct ospf6_header *) sendbuf;
   lsupdate = (struct ospf6_lsupdate *)
     ((caddr_t) oh + sizeof (struct ospf6_header));
 
   p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
-  num = 0;
+  lsa_cnt = 0;
 
   /* lsupdate_list lists those LSA which doesn't need to be
      retransmitted. remove those from the list */
@@ -2005,58 +2008,85 @@
     {
       /* MTU check */
       if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
-          > ospf6_packet_max(on->ospf6_if))
-        {
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	   > ospf6_packet_max(on->ospf6_if))
+	{
+	  ospf6_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
       p += OSPF6_LSA_SIZE (lsa->header);
-      num++;
+      lsa_cnt++;
 
       assert (lsa->lock == 2);
       ospf6_lsdb_remove (lsa, on->lsupdate_list);
     }
 
+  if (lsa_cnt)
+    {
+      oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+      oh->length = htons (p - sendbuf);
+      lsupdate->lsa_number = htonl (lsa_cnt);
+
+      if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
+	  (on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
+	  (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
+	ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
+		    on->ospf6_if, oh);
+      else
+	ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+		    on->ospf6_if, oh);
+    }
+
+  /* The addresses used for retransmissions are different from those sent the
+     first time and so we need to separate them here.
+  */
+  memset (sendbuf, 0, iobuflen);
+  oh = (struct ospf6_header *) sendbuf;
+  lsupdate = (struct ospf6_lsupdate *)
+    ((caddr_t) oh + sizeof (struct ospf6_header));
+  p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
+  lsa_cnt = 0;
+
   for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     {
       /* MTU check */
       if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
-          > ospf6_packet_max(on->ospf6_if))
-        {
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	   > ospf6_packet_max(on->ospf6_if))
+	{
+	  ospf6_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
       p += OSPF6_LSA_SIZE (lsa->header);
-      num++;
+      lsa_cnt++;
     }
 
-  lsupdate->lsa_number = htonl (num);
-
-  oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
-  oh->length = htons (p - sendbuf);
-
-  ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
-              on->ospf6_if, oh);
-
-  if (on->lsupdate_list->count != 0 ||
-      on->retrans_list->count != 0)
+  if (lsa_cnt)
     {
-      if (on->lsupdate_list->count != 0)
-        on->thread_send_lsupdate =
-          thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
+      oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+      oh->length = htons (p - sendbuf);
+      lsupdate->lsa_number = htonl (lsa_cnt);
+
+      if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
+	ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
+		    on->ospf6_if, oh);
       else
-        on->thread_send_lsupdate =
-          thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
-                            on->ospf6_if->rxmt_interval);
+	ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+		    on->ospf6_if, oh);
     }
 
+  if (on->lsupdate_list->count != 0)
+    on->thread_send_lsupdate =
+      thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
+  else if (on->retrans_list->count != 0)
+    on->thread_send_lsupdate =
+      thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
+			on->ospf6_if->rxmt_interval);
   return 0;
 }
 
@@ -2067,7 +2097,7 @@
   struct ospf6_header *oh;
   struct ospf6_lsupdate *lsupdate;
   u_char *p;
-  int num;
+  int lsa_cnt;
   struct ospf6_lsa *lsa;
 
   oi = (struct ospf6_interface *) THREAD_ARG (thread);
@@ -2088,41 +2118,46 @@
   memset (sendbuf, 0, iobuflen);
   oh = (struct ospf6_header *) sendbuf;
   lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
-                                       sizeof (struct ospf6_header));
+				       sizeof (struct ospf6_header));
 
   p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
-  num = 0;
+  lsa_cnt = 0;
 
   for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     {
       /* MTU check */
       if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
-          > ospf6_packet_max(oi))
-        {
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	   > ospf6_packet_max(oi))
+	{
+	  ospf6_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
       p += OSPF6_LSA_SIZE (lsa->header);
-      num++;
+      lsa_cnt++;
 
       assert (lsa->lock == 2);
       ospf6_lsdb_remove (lsa, oi->lsupdate_list);
     }
 
-  lsupdate->lsa_number = htonl (num);
+  if (lsa_cnt)
+    {
+      lsupdate->lsa_number = htonl (lsa_cnt);
 
-  oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
-  oh->length = htons (p - sendbuf);
+      oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+      oh->length = htons (p - sendbuf);
 
-  if (oi->state == OSPF6_INTERFACE_DR ||
-      oi->state == OSPF6_INTERFACE_BDR)
-    ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
-  else
-    ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+      if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
+	  (oi->state == OSPF6_INTERFACE_DR) ||
+	  (oi->state == OSPF6_INTERFACE_BDR))
+	ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
+      else
+	ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+
+    }
 
   if (oi->lsupdate_list->count > 0)
     {
@@ -2140,6 +2175,7 @@
   struct ospf6_header *oh;
   u_char *p;
   struct ospf6_lsa *lsa;
+  int lsa_cnt = 0;
 
   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
   on->thread_send_lsack = (struct thread *) NULL;
@@ -2166,16 +2202,16 @@
     {
       /* MTU check */
       if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
-        {
-          /* if we run out of packet size/space here,
-             better to try again soon. */
-          THREAD_OFF (on->thread_send_lsack);
-          on->thread_send_lsack =
-            thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
+	{
+	  /* if we run out of packet size/space here,
+	     better to try again soon. */
+	  THREAD_OFF (on->thread_send_lsack);
+	  on->thread_send_lsack =
+	    thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
 
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	  ospf6_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
       memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
@@ -2183,13 +2219,24 @@
 
       assert (lsa->lock == 2);
       ospf6_lsdb_remove (lsa, on->lsack_list);
+      lsa_cnt++;
     }
 
-  oh->type = OSPF6_MESSAGE_TYPE_LSACK;
-  oh->length = htons (p - sendbuf);
+  if (lsa_cnt)
+    {
+      oh->type = OSPF6_MESSAGE_TYPE_LSACK;
+      oh->length = htons (p - sendbuf);
 
-  ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
-              on->ospf6_if, oh);
+      ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+		  on->ospf6_if, oh);
+    }
+
+  if (on->thread_send_lsack == NULL && on->lsack_list->count > 0)
+    {
+      on->thread_send_lsack =
+        thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
+    }
+
   return 0;
 }
 
@@ -2200,6 +2247,7 @@
   struct ospf6_header *oh;
   u_char *p;
   struct ospf6_lsa *lsa;
+  int lsa_cnt = 0;
 
   oi = (struct ospf6_interface *) THREAD_ARG (thread);
   oi->thread_send_lsack = (struct thread *) NULL;
@@ -2226,16 +2274,16 @@
     {
       /* MTU check */
       if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
-        {
-          /* if we run out of packet size/space here,
-             better to try again soon. */
-          THREAD_OFF (oi->thread_send_lsack);
-          oi->thread_send_lsack =
-            thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
+	{
+	  /* if we run out of packet size/space here,
+	     better to try again soon. */
+	  THREAD_OFF (oi->thread_send_lsack);
+	  oi->thread_send_lsack =
+	    thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
 
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	  ospf6_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
       memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
@@ -2243,16 +2291,21 @@
 
       assert (lsa->lock == 2);
       ospf6_lsdb_remove (lsa, oi->lsack_list);
+      lsa_cnt++;
     }
 
-  oh->type = OSPF6_MESSAGE_TYPE_LSACK;
-  oh->length = htons (p - sendbuf);
+  if (lsa_cnt)
+    {
+      oh->type = OSPF6_MESSAGE_TYPE_LSACK;
+      oh->length = htons (p - sendbuf);
 
-  if (oi->state == OSPF6_INTERFACE_DR ||
-      oi->state == OSPF6_INTERFACE_BDR)
-    ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
-  else
-    ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+      if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
+	  (oi->state == OSPF6_INTERFACE_DR) ||
+	  (oi->state == OSPF6_INTERFACE_BDR))
+	ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
+      else
+	ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+    }
 
   if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
     {