]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospfd: Prioritise hellos for sending by queueing to head of output buffer
authorPaul Jakma <paul@quagga.net>
Fri, 8 Jan 2010 17:11:15 +0000 (17:11 +0000)
committerPaul Jakma <paul@quagga.net>
Wed, 8 Dec 2010 17:11:19 +0000 (17:11 +0000)
* It's possible for the packet output buffer to be filled up with a long
  series of non-Hello packets in between Hellos packets, such that the
  router's neighbours don't receive the Hello packet in time, even though
  the hello-timer ran at about the right time. Fix this by prioritising
  Hello packets, letting them skip the queue and go ahead of any packets
  already on the queue.

  This problem can occur when there are lots of LSAs and slow links.

* ospf_packet.h: (ospf_hello_send_sub) not used outside of ospf_packet.c
* ospf_packet.c: (ospf_fifo_push_head) add packet to head of fifo (so its
  no longer really a fifo, but hey)
  (ospf_packet_add_top) add packet to top of the packet output queue.
  (ospf_hello_send_sub) Put Hello's at the top of the packet output queue.
  make it take in_addr_t parameter, so that this
  ospf_hello_send can re-use this code too.
  (ospf_hello_send) consolidate code by using ospf_hello_send_sub
  (ospf_poll_send,ospf_hello_reply_timer) adjust for ospf_hello_send_sub.

ospfd/ospf_packet.c
ospfd/ospf_packet.h

index 80641b49e075268b69cac899813e3c3d5b94a48f..8b7c63a93afd94973215d4de45aeb73995396527 100644 (file)
@@ -125,6 +125,20 @@ ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
   fifo->count++;
 }
 
+/* Add new packet to head of fifo. */
+static void
+ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op)
+{
+  op->next = fifo->head;
+  
+  if (fifo->tail == NULL)
+    fifo->tail = op;
+  
+  fifo->head = op;
+  
+  fifo->count++;
+}
+
 /* Delete first packet from fifo. */
 struct ospf_packet *
 ospf_fifo_pop (struct ospf_fifo *fifo)
@@ -199,6 +213,27 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
   /* ospf_fifo_debug (oi->obuf); */
 }
 
+static void
+ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op)
+{
+  if (!oi->obuf)
+    {
+      zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
+              "destination %s) called with NULL obuf, ignoring "
+              "(please report this bug)!\n",
+              IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
+              ospf_packet_type_str[stream_getc_from(op->s, 1)],
+              inet_ntoa (op->dst));
+      return;
+    }
+
+  /* Add packet to head of queue. */
+  ospf_fifo_push_head (oi->obuf, op);
+
+  /* Debug of packet fifo*/
+  /* ospf_fifo_debug (oi->obuf); */
+}
+
 void
 ospf_packet_delete (struct ospf_interface *oi)
 {
@@ -2967,8 +3002,8 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
   return length;
 }
 
-void
-ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
+static void
+ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr)
 {
   struct ospf_packet *op;
   u_int16_t length = OSPF_HEADER_SIZE;
@@ -2987,10 +3022,12 @@ ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
   /* Set packet length. */
   op->length = length;
 
-  op->dst.s_addr = addr->s_addr;
+  op->dst.s_addr = addr;
 
-  /* Add packet to the interface output queue. */
-  ospf_packet_add (oi, op);
+  /* Add packet to the top of the interface output queue, so that they
+   * can't get delayed by things like long queues of LS Update packets
+   */
+  ospf_packet_add_top (oi, op);
 
   /* Hook thread to write packet. */
   OSPF_ISM_WRITE_ON (oi->ospf);
@@ -3021,7 +3058,7 @@ ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
       && oi->state != ISM_DR && oi->state != ISM_Backup)
     return;
 
-  ospf_hello_send_sub (oi, &nbr_nbma->addr);
+  ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr);
 }
 
 int
@@ -3060,7 +3097,7 @@ ospf_hello_reply_timer (struct thread *thread)
     zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
          IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
 
-  ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
+  ospf_hello_send_sub (nbr->oi, nbr->address.u.prefix4.s_addr);
 
   return 0;
 }
@@ -3069,27 +3106,10 @@ ospf_hello_reply_timer (struct thread *thread)
 void
 ospf_hello_send (struct ospf_interface *oi)
 {
-  struct ospf_packet *op;
-  u_int16_t length = OSPF_HEADER_SIZE;
-
   /* If this is passive interface, do not send OSPF Hello. */
   if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
     return;
 
-  op = ospf_packet_new (oi->ifp->mtu);
-
-  /* Prepare OSPF common header. */
-  ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
-
-  /* Prepare OSPF Hello body. */
-  length += ospf_make_hello (oi, op->s);
-
-  /* Fill OSPF header. */
-  ospf_fill_header (oi, op->s, length);
-
-  /* Set packet length. */
-  op->length = length;
-
   if (oi->type == OSPF_IFTYPE_NBMA)
     {
       struct ospf_neighbor *nbr;
@@ -3119,34 +3139,16 @@ ospf_hello_send (struct ospf_interface *oi)
                if (nbr->priority == 0 && oi->state == ISM_DROther)
                  continue;
                /* if oi->state == Waiting, send hello to all neighbors */
-               {
-                 struct ospf_packet *op_dup;
-
-                 op_dup = ospf_packet_dup(op);
-                 op_dup->dst = nbr->address.u.prefix4;
-
-                 /* Add packet to the interface output queue. */
-                 ospf_packet_add (oi, op_dup);
-
-                 OSPF_ISM_WRITE_ON (oi->ospf);
-               }
-
+               ospf_hello_send_sub (oi, nbr->address.u.prefix4.s_addr);
              }
-      ospf_packet_free (op);
     }
   else
     {
       /* Decide destination address. */
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
-       op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
-      else 
-       op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
-
-      /* Add packet to the interface output queue. */
-      ospf_packet_add (oi, op);
-
-      /* Hook thread to write packet. */
-      OSPF_ISM_WRITE_ON (oi->ospf);
+        ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr);
+      else
+        ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS));
     }
 }
 
index 7b3d686612049fd924dfbb5e4e3f247950f5d6c8..9a472081a6718c165140749ec620b380d4b39ee0 100644 (file)
@@ -162,6 +162,5 @@ extern int ospf_ls_upd_timer (struct thread *);
 extern int ospf_ls_ack_timer (struct thread *);
 extern int ospf_poll_timer (struct thread *);
 extern int ospf_hello_reply_timer (struct thread *);
-extern void ospf_hello_send_sub (struct ospf_interface *, struct in_addr *);
 
 #endif /* _ZEBRA_OSPF_PACKET_H */