2004-07-14 Paul Jakma <paul@dishone.st>

        * ospf_packet.c: (ospf_ls_upd_send_queue_event) Partial fix for
          problem reported by Peter Frost amongst others, where function
          will spin indefinitely if update list contains LSAs greater than
          MTU-headers or other condition leading to update list never being
          cleared. Problem of what to do with these LSAs remains.
          (ospf_make_ls_upd) add comment about large LSA problem,
          indentation cleanup.
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
index f35e1af..5702732 100644
--- a/ospfd/ChangeLog
+++ b/ospfd/ChangeLog
@@ -1,3 +1,13 @@
+2004-07-14 Paul Jakma <paul@dishone.st>
+
+	* ospf_packet.c: (ospf_ls_upd_send_queue_event) Partial fix for 
+	  problem reported by Peter Frost amongst others, where function
+	  will spin indefinitely if update list contains LSAs greater than
+	  MTU-headers or other condition leading to update list never being
+          cleared. Problem of what to do with these LSAs remains.
+          (ospf_make_ls_upd) add comment about large LSA problem,
+	  indentation cleanup.
+
 2004-07-01  Greg Troxel  <gdt@fnord.ir.bbn.com>
 
 	* Makefile.am (lib_LTLIBRARIES): make libospf shared
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 5692db6..990fe6a 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -2702,8 +2702,8 @@
   int count = 0;
 
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info("ospf_make_ls_upd: Start");
-  
+    zlog_info ("ospf_make_ls_upd: Start");
+
   pp = stream_get_putp (s);
   ospf_output_forward (s, 4);
 
@@ -2713,16 +2713,20 @@
       u_int16_t ls_age;
 
       if (IS_DEBUG_OSPF_EVENT)
-	zlog_info("ospf_make_ls_upd: List Iteration");
+        zlog_info ("ospf_make_ls_upd: List Iteration");
 
       lsa = getdata (node);
       assert (lsa);
       assert (lsa->data);
 
       /* Check packet size. */
+      /* XXX: LSA can be > packet-headers, eg router-lsas for machines
+       * with hundreds of interfaces, received as several
+       * fragmented packets.
+       */
       if (length + delta + ntohs (lsa->data->length) > OSPF_PACKET_MAX (oi))
-	break;
-      
+        break;
+
       /* Keep pointer to LS age. */
       lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_putp (s));
 
@@ -2749,7 +2753,7 @@
   stream_set_putp (s, s->endp);
 
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info("ospf_make_ls_upd: Stop");
+    zlog_info ("ospf_make_ls_upd: Stop");
   return length;
 }
 
@@ -3100,8 +3104,9 @@
   /* Prepare OSPF common header. */
   ospf_make_header (OSPF_MSG_LS_UPD, oi, op->s);
 
-  /* Prepare OSPF Link State Update body. */
-  /* Includes Type-7 translation. */
+  /* Prepare OSPF Link State Update body.
+   * Includes Type-7 translation. 
+   */
   length += ospf_make_ls_upd (oi, update, op->s);
 
   /* Fill OSPF header. */
@@ -3126,6 +3131,9 @@
   struct ospf_interface *oi = THREAD_ARG(thread);
   struct route_node *rn;
   struct route_node *rnext;
+  struct list *update;
+  struct listnode *tn, *nn;
+  unsigned int again = 0;
   
   oi->t_ls_upd_event = NULL;
 
@@ -3134,23 +3142,43 @@
 
   for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext)
     {
-      
+      update = (struct list *)rn->info;
       rnext = route_next (rn);
       
       if (rn->info == NULL)
         continue;
 
-      while (!list_isempty ((list)rn->info))
-        ospf_ls_upd_queue_send (oi, rn->info, rn->p.u.prefix4);
-
-      list_delete (rn->info);
-      rn->info = NULL;
+      for (tn = update->head; tn; tn = nn)
+        {
+          nn = tn->next;
+          ospf_ls_upd_queue_send (oi, update, rn->p.u.prefix4);
+        }
       
-      route_unlock_node (rn);
+      /* list might not be empty.
+       * TODO: work out what to do about oversized LSAs.
+       */
+      if (listcount(update) == 0)
+        {
+          list_delete (rn->info);
+          rn->info = NULL;
+          route_unlock_node (rn);
+        }
+      else
+        again++;
+    }
+
+  if (again != 0)
+    {
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("ospf_ls_upd_send_queue: update lists not cleared,"
+                   " %d nodes to try again, raising new event", again);
+      oi->t_ls_upd_event = 
+        thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
     }
 
   if (IS_DEBUG_OSPF_EVENT)
     zlog_info ("ospf_ls_upd_send_queue stop");
+  
   return 0;
 }