]> git.puffer.fish Git - mirror/frr.git/commitdiff
In the "write" direction added a command to ensure that Quagga
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:24:42 +0000 (17:24 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:24:42 +0000 (17:24 -0700)
is able to send out K (=3 by default) packets per thread-write.

Signed-off-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: JR Rivers <jrrivers@cumulusnetworks.com>
ospfd/ospf_packet.c
ospfd/ospf_vty.c
ospfd/ospfd.c
ospfd/ospfd.h

index c0c0924377b89512e7b93994f66608634cecfd08..43a237cf558b4ad558c7e406452c7af47dfc1316 100644 (file)
@@ -217,6 +217,13 @@ ospf_fifo_flush (struct ospf_fifo *fifo)
   fifo->count = 0;
 }
 
+/* Return the current fifo count */
+static int
+ospf_fifo_count (struct ospf_fifo *fifo)
+{
+       return (fifo->count);
+}
+
 /* Free ospf packet fifo. */
 void
 ospf_fifo_free (struct ospf_fifo *fifo)
@@ -647,6 +654,7 @@ ospf_write (struct thread *thread)
 #endif /* WANT_OSPF_WRITE_FRAGMENT */
   u_int16_t maxdatasize;
 #define OSPF_WRITE_IPHL_SHIFT 2
+  int pkt_count = 0;
   
   ospf->t_write = NULL;
 
@@ -668,131 +676,135 @@ ospf_write (struct thread *thread)
   maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) -
     sizeof (struct ip);
   
-  /* Get one packet from queue. */
-  op = ospf_fifo_head (oi->obuf);
-  assert (op);
-  assert (op->length >= OSPF_HEADER_SIZE);
-
-  if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
-      || op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
-      ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
-    
-  /* Rewrite the md5 signature & update the seq */
-  ospf_make_md5_digest (oi, op);
-
-  /* Retrieve OSPF packet type. */
-  stream_set_getp (op->s, 1);
-  type = stream_getc (op->s);
+  while ((pkt_count < ospf->write_multiplier) && ospf_fifo_count(oi->obuf))
+       {
+      pkt_count++;
+      /* Get one packet from queue. */
+      op = ospf_fifo_head (oi->obuf);
+      assert (op);
+      assert (op->length >= OSPF_HEADER_SIZE);
+
+      if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
+          || op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
+          ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
+
+      /* Rewrite the md5 signature & update the seq */
+      ospf_make_md5_digest (oi, op);
+
+      /* Retrieve OSPF packet type. */
+      stream_set_getp (op->s, 1);
+      type = stream_getc (op->s);
   
-  /* reset get pointer */
-  stream_set_getp (op->s, 0);
+      /* reset get pointer */
+      stream_set_getp (op->s, 0);
 
-  memset (&iph, 0, sizeof (struct ip));
-  memset (&sa_dst, 0, sizeof (sa_dst));
+      memset (&iph, 0, sizeof (struct ip));
+      memset (&sa_dst, 0, sizeof (sa_dst));
   
-  sa_dst.sin_family = AF_INET;
+      sa_dst.sin_family = AF_INET;
 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
-  sa_dst.sin_len = sizeof(sa_dst);
+      sa_dst.sin_len = sizeof(sa_dst);
 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
-  sa_dst.sin_addr = op->dst;
-  sa_dst.sin_port = htons (0);
-
-  /* Set DONTROUTE flag if dst is unicast. */
-  if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
-    if (!IN_MULTICAST (htonl (op->dst.s_addr)))
-      flags = MSG_DONTROUTE;
-
-  iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT;
-  /* it'd be very strange for header to not be 4byte-word aligned but.. */
-  if ( sizeof (struct ip) 
-        > (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) )
-    iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */
+      sa_dst.sin_addr = op->dst;
+      sa_dst.sin_port = htons (0);
+
+      /* Set DONTROUTE flag if dst is unicast. */
+      if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
+        if (!IN_MULTICAST (htonl (op->dst.s_addr)))
+          flags = MSG_DONTROUTE;
+
+      iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT;
+      /* it'd be very strange for header to not be 4byte-word aligned but.. */
+      if ( sizeof (struct ip)
+            > (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) )
+        iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */
   
-  iph.ip_v = IPVERSION;
-  iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
-  iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
+      iph.ip_v = IPVERSION;
+      iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
+      iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
 
 #if defined(__DragonFly__)
-  /*
-   * DragonFly's raw socket expects ip_len/ip_off in network byte order.
-   */
-  iph.ip_len = htons(iph.ip_len);
+      /*
+       * DragonFly's raw socket expects ip_len/ip_off in network byte order.
+       */
+      iph.ip_len = htons(iph.ip_len);
 #endif
 
 #ifdef WANT_OSPF_WRITE_FRAGMENT
-  /* XXX-MT: not thread-safe at all..
-   * XXX: this presumes this is only programme sending OSPF packets 
-   * otherwise, no guarantee ipid will be unique
-   */
-  iph.ip_id = ++ipid;
+      /* XXX-MT: not thread-safe at all..
+       * XXX: this presumes this is only programme sending OSPF packets
+       * otherwise, no guarantee ipid will be unique
+       */
+      iph.ip_id = ++ipid;
 #endif /* WANT_OSPF_WRITE_FRAGMENT */
 
-  iph.ip_off = 0;
-  if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
-    iph.ip_ttl = OSPF_VL_IP_TTL;
-  else
-    iph.ip_ttl = OSPF_IP_TTL;
-  iph.ip_p = IPPROTO_OSPFIGP;
-  iph.ip_sum = 0;
-  iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
-  iph.ip_dst.s_addr = op->dst.s_addr;
-
-  memset (&msg, 0, sizeof (msg));
-  msg.msg_name = (caddr_t) &sa_dst;
-  msg.msg_namelen = sizeof (sa_dst); 
-  msg.msg_iov = iov;
-  msg.msg_iovlen = 2;
-  iov[0].iov_base = (char*)&iph;
-  iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
-  iov[1].iov_base = STREAM_PNT (op->s);
-  iov[1].iov_len = op->length;
+      iph.ip_off = 0;
+      if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+        iph.ip_ttl = OSPF_VL_IP_TTL;
+      else
+        iph.ip_ttl = OSPF_IP_TTL;
+      iph.ip_p = IPPROTO_OSPFIGP;
+      iph.ip_sum = 0;
+      iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
+      iph.ip_dst.s_addr = op->dst.s_addr;
+
+      memset (&msg, 0, sizeof (msg));
+      msg.msg_name = (caddr_t) &sa_dst;
+      msg.msg_namelen = sizeof (sa_dst);
+      msg.msg_iov = iov;
+      msg.msg_iovlen = 2;
+      iov[0].iov_base = (char*)&iph;
+      iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
+      iov[1].iov_base = STREAM_PNT (op->s);
+      iov[1].iov_len = op->length;
   
-  /* Sadly we can not rely on kernels to fragment packets because of either
-   * IP_HDRINCL and/or multicast destination being set.
-   */
+      /* Sadly we can not rely on kernels to fragment packets because of either
+       * IP_HDRINCL and/or multicast destination being set.
+       */
 #ifdef WANT_OSPF_WRITE_FRAGMENT
-  if ( op->length > maxdatasize )
-    ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize, 
-                      oi->ifp->mtu, flags, type);
+      if ( op->length > maxdatasize )
+        ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize,
+                          oi->ifp->mtu, flags, type);
 #endif /* WANT_OSPF_WRITE_FRAGMENT */
 
-  /* send final fragment (could be first) */
-  sockopt_iphdrincl_swab_htosys (&iph);
-  ret = sendmsg (ospf->fd, &msg, flags);
-  sockopt_iphdrincl_swab_systoh (&iph);
-  if (IS_DEBUG_OSPF_EVENT)
-    zlog_debug ("ospf_write to %s, "
-              "id %d, off %d, len %d, interface %s, mtu %u:",
-              inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
-              oi->ifp->name, oi->ifp->mtu);
+      /* send final fragment (could be first) */
+      sockopt_iphdrincl_swab_htosys (&iph);
+      ret = sendmsg (ospf->fd, &msg, flags);
+      sockopt_iphdrincl_swab_systoh (&iph);
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_debug ("ospf_write to %s, "
+                  "id %d, off %d, len %d, interface %s, mtu %u:",
+                  inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
+                  oi->ifp->name, oi->ifp->mtu);
   
-  if (ret < 0)
-    zlog_warn ("*** sendmsg in ospf_write failed to %s, "
-              "id %d, off %d, len %d, interface %s, mtu %u: %s",
-              inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
-              oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
+      if (ret < 0)
+        zlog_warn ("*** sendmsg in ospf_write failed to %s, "
+                  "id %d, off %d, len %d, interface %s, mtu %u: %s",
+                  inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
+                  oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
 
-  /* Show debug sending packet. */
-  if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
-    {
-      if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
-       {
-         zlog_debug ("-----------------------------------------------------");
-         ospf_ip_header_dump (&iph);
-         stream_set_getp (op->s, 0);
-         ospf_packet_dump (op->s);
-       }
+      /* Show debug sending packet. */
+      if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
+        {
+          if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
+           {
+             zlog_debug ("-----------------------------------------------------");
+             ospf_ip_header_dump (&iph);
+             stream_set_getp (op->s, 0);
+             ospf_packet_dump (op->s);
+           }
 
-      zlog_debug ("%s sent to [%s] via [%s].",
-                LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst),
-                IF_NAME (oi));
+          zlog_debug ("%s sent to [%s] via [%s].",
+                    LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst),
+                    IF_NAME (oi));
 
-      if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
-       zlog_debug ("-----------------------------------------------------");
-    }
+          if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
+           zlog_debug ("-----------------------------------------------------");
+        }
 
-  /* Now delete packet from queue. */
-  ospf_packet_delete (oi);
+      /* Now delete packet from queue. */
+      ospf_packet_delete (oi);
+       }
 
   /* Move this interface to the tail of write_q to
         serve everyone in a round robin fashion */
index 561d8114995d1f0ae789de1ac184f51210f78dfc..b9c99b1dbdf3095b9c82cf9b4609165e1a1a8d10 100644 (file)
@@ -2531,6 +2531,37 @@ DEFUN (no_ospf_auto_cost_reference_bandwidth,
   return CMD_SUCCESS;
 }
 
+DEFUN (ospf_write_multiplier,
+       ospf_write_multiplier_cmd,
+       "write-multiplier <1-50>",
+       "Number of writes per thread callback\n")
+{
+  struct ospf *ospf = vty->index;
+  u_int32_t write_multiplier;
+
+  write_multiplier = strtol (argv[0], NULL, 10);
+  if (write_multiplier < 1 || write_multiplier > 50)
+    {
+      vty_out (vty, "write-multiplier value is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ospf->write_multiplier = write_multiplier;
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf_write_multiplier,
+       no_ospf_write_multiplier_cmd,
+       "no write-multiplier",
+       NO_STR
+       "Number of writes per thread callback\n")
+{
+  struct ospf *ospf = vty->index;
+
+  ospf->write_multiplier = OSPF_WRITE_MULTIPLIER_DEFAULT;
+  return CMD_SUCCESS;
+}
+
 const char *ospf_abr_type_descr_str[] = 
 {
   "Unknown",
@@ -2760,6 +2791,10 @@ DEFUN (show_ip_ospf,
            ospf_timer_dump (ospf->t_spf_calc, timebuf, sizeof (timebuf)),
            VTY_NEWLINE);
   
+  /* Show write multiplier values */
+  vty_out (vty, " Write Multiplier set to %d %s",
+          ospf->write_multiplier, VTY_NEWLINE);
+
   /* Show refresh parameters. */
   vty_out (vty, " Refresh timer %d secs%s",
           ospf->lsa_refresh_interval, VTY_NEWLINE);
@@ -7287,6 +7322,11 @@ ospf_config_write (struct vty *vty)
                 ospf->spf_delay, ospf->spf_holdtime,
                 ospf->spf_max_holdtime, VTY_NEWLINE);
       
+      /* Write multiplier print. */
+      if (ospf->write_multiplier != OSPF_WRITE_MULTIPLIER_DEFAULT)
+        vty_out (vty, " ospf write-multiplier %d%s",
+                 ospf->write_multiplier, VTY_NEWLINE);
+
       /* Max-metric router-lsa print */
       config_write_stub_router (vty, ospf);
       
@@ -7723,6 +7763,10 @@ ospf_vty_init (void)
   install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd);
   install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd);
 
+  /* write multiplier commands */
+  install_element (OSPF_NODE, &ospf_write_multiplier_cmd);
+  install_element (OSPF_NODE, &no_ospf_write_multiplier_cmd);
+
   /* Init interface related vty commands. */
   ospf_vty_if_init ();
 
index dd57f645b77620bcadc2d09a1799dc15ded5a41c..09f3a142471c11379ed3fbdec4e1f6938295571a 100644 (file)
@@ -233,6 +233,7 @@ ospf_new (void)
     }
   new->t_read = thread_add_read (master, ospf_read, new, new->fd);
   new->oi_write_q = list_new ();
+  new->write_multiplier = OSPF_WRITE_MULTIPLIER_DEFAULT;
   
   return new;
 }
index bf70d022753d2507ca9cb159b221b03941dc710a..3e8b52e9e323b224dc58bf9b5ce0f0c77b67e296 100644 (file)
@@ -219,6 +219,8 @@ struct ospf
   struct thread *t_deferred_shutdown;  /* deferred/stub-router shutdown timer*/
 
   struct thread *t_write;
+#define OSPF_WRITE_MULTIPLIER_DEFAULT    3
+  int write_multiplier;         /* Num of packets sent per thread invocation */
   struct thread *t_read;
   int fd;
   unsigned int maxsndbuflen;