]> git.puffer.fish Git - mirror/frr.git/commitdiff
2005-02-23 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
authorajs <ajs>
Wed, 23 Feb 2005 15:43:01 +0000 (15:43 +0000)
committerajs <ajs>
Wed, 23 Feb 2005 15:43:01 +0000 (15:43 +0000)
* ospfd.h: Add new field struct stream *ibuf to struct ospf.
* ospfd.c: (ospf_new) Check return code from ospf_sock_init.
  Allocate ibuf using stream_new(OSPF_MAX_PACKET_SIZE+1).
  (ospf_finish) Call stream_free(ospf->ibuf.
* ospf_packet.c: (ospf_read) Call stream_reset(ospf->ibuf) and then
  pass it to ospf_recv_packet for use in receiving the packet
  (instead of allocating a new stream for each packet received).
  Eliminate all calls to stream_free(ibuf).
  (ospf_recv_packet) The struct stream *ibuf is now passed in as
  an argument.  No need to use recvfrom to peek at the packet
  header (to see how big it is), just use ospf->ibuf which is
  always large enough (this eliminates a system call to recvfrom).
  Therefore, no need to allocate a stream just for this packet,
  and no need to free it when done.

ospfd/ChangeLog
ospfd/ospf_packet.c
ospfd/ospfd.c
ospfd/ospfd.h

index ee30e55c855b34529fcfa7c58892aaf464415d05..668999f93832fc401852a0a2eaf94ff566da87bc 100644 (file)
@@ -1,3 +1,20 @@
+2005-02-23 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
+
+       * ospfd.h: Add new field struct stream *ibuf to struct ospf.
+       * ospfd.c: (ospf_new) Check return code from ospf_sock_init.
+         Allocate ibuf using stream_new(OSPF_MAX_PACKET_SIZE+1).
+         (ospf_finish) Call stream_free(ospf->ibuf.
+       * ospf_packet.c: (ospf_read) Call stream_reset(ospf->ibuf) and then
+         pass it to ospf_recv_packet for use in receiving the packet
+         (instead of allocating a new stream for each packet received).
+         Eliminate all calls to stream_free(ibuf).
+         (ospf_recv_packet) The struct stream *ibuf is now passed in as
+         an argument.  No need to use recvfrom to peek at the packet
+         header (to see how big it is), just use ospf->ibuf which is
+         always large enough (this eliminates a system call to recvfrom).
+         Therefore, no need to allocate a stream just for this packet,
+         and no need to free it when done.
+
 2005-02-23 Vincenzo Eramo <eramo at infocom.ing.uniroma1.it>
 
        * ospf_lsa.h: New flag to the LSA structure for the SPF calculation.
index 6b7a796dfee3e0ee73824bc26ffff1f2b4775e25..87913361cf3443342ce7b09451e048aef0791648 100644 (file)
@@ -2033,12 +2033,11 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
 }
 \f
 static struct stream *
-ospf_recv_packet (int fd, struct interface **ifp)
+ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
 {
   int ret;
-  struct ip iph;
+  struct ip *iph;
   u_int16_t ip_len;
-  struct stream *ibuf;
   unsigned int ifindex = 0;
   struct iovec iov;
   /* Header and data both require alignment. */
@@ -2051,30 +2050,26 @@ ospf_recv_packet (int fd, struct interface **ifp)
   msgh.msg_control = (caddr_t) buff;
   msgh.msg_controllen = sizeof (buff);
   
-  /* XXX Is there an upper limit on the size of these packets?  If there is,
-     it would be more efficient to read the whole packet in one shot without
-     peeking (this would cut down from 2 system calls to 1).  And this would
-     make the error-handling logic a bit more robust. */
-  ret = recvfrom (fd, (void *)&iph, sizeof (iph), MSG_PEEK, NULL, 0);
-  
-  if (ret != sizeof (iph))
+  ret = stream_recvmsg (ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE+1);
+  if (ret < 0)
     {
-      if (ret > 0)
-        {
-         zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
-                   "(ip header size is %u)",
-                   ret, (u_int)sizeof(iph));
-         recvfrom (fd, (void *)&iph, ret, 0, NULL, 0);
-        }
-      else
-       zlog_warn("ospf_recv_packet: recvfrom returned %d: %s",
-                 ret, safe_strerror(errno));
+      zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
+      return NULL;
+    }
+  if (ret < sizeof(iph))
+    {
+      zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
+               "(ip header size is %u)",
+               ret, (u_int)sizeof(iph));
       return NULL;
     }
   
-  sockopt_iphdrincl_swab_systoh (&iph);
+  /* Note that there should not be alignment problems with this assignment
+     because this is at the beginning of the stream data buffer. */
+  iph = (struct ip *) STREAM_DATA(ibuf);
+  sockopt_iphdrincl_swab_systoh (iph);
   
-  ip_len = iph.ip_len;
+  ip_len = iph->ip_len;
   
 #if !defined(GNU_LINUX) && (OpenBSD < 200311)
   /*
@@ -2091,25 +2086,17 @@ ospf_recv_packet (int fd, struct interface **ifp)
    *
    * For more details, see <netinet/ip_input.c>.
    */
-  ip_len = ip_len + (iph.ip_hl << 2);
+  ip_len = ip_len + (iph->ip_hl << 2);
 #endif
   
-  if ( (ibuf = stream_new (ip_len)) == NULL)
-    return NULL;
-  iov.iov_base = STREAM_DATA (ibuf);
-  iov.iov_len = ip_len;
-  
-  ret = stream_recvmsg (ibuf, fd, &msgh, 0, ip_len);
-  
   ifindex = getsockopt_ifindex (AF_INET, &msgh);
   
   *ifp = if_lookup_by_index (ifindex);
 
   if (ret != ip_len)
     {
-      zlog_warn ("ospf_recv_packet short read. "
-                "ip_len %d bytes read %d", ip_len, ret);
-      stream_free (ibuf);
+      zlog_warn ("ospf_recv_packet read length mismatch: ip_len is %d, "
+                        "but recvmsg returned %d", ip_len, ret);
       return NULL;
     }
   
@@ -2360,12 +2347,14 @@ ospf_read (struct thread *thread)
   ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
 
   /* read OSPF packet. */
-  ibuf = ospf_recv_packet (ospf->fd, &ifp);
-  if (ibuf == NULL)
+  stream_reset(ospf->ibuf);
+  if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
     return -1;
   
+  /* Note that there should not be alignment problems with this assignment
+     because this is at the beginning of the stream data buffer. */
   iph = (struct ip *) STREAM_DATA (ibuf);
-  sockopt_iphdrincl_swab_systoh (iph);
+  /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */
 
   if (ifp == NULL)
     /* Handle cases where the platform does not support retrieving the ifindex,
@@ -2374,10 +2363,7 @@ ospf_read (struct thread *thread)
     ifp = if_lookup_address (iph->ip_src);
   
   if (ifp == NULL)
-    {
-      stream_free (ibuf);
-      return 0;
-    }
+    return 0;
 
   /* IP Header dump. */
     if (IS_DEBUG_OSPF_PACKET(0, RECV))
@@ -2391,7 +2377,6 @@ ospf_read (struct thread *thread)
           zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
                      inet_ntoa (iph->ip_src));
         }
-      stream_free (ibuf);
       return 0;
     }
 
@@ -2418,7 +2403,6 @@ ospf_read (struct thread *thread)
           zlog_warn ("Packet from [%s] received on link %s"
                      " but no ospf_interface",
                      inet_ntoa (iph->ip_src), ifp->name);
-          stream_free (ibuf);
           return 0;
         }
     }
@@ -2430,7 +2414,6 @@ ospf_read (struct thread *thread)
     {
       zlog_warn ("Packet from [%s] received on wrong link %s",
                  inet_ntoa (iph->ip_src), ifp->name); 
-      stream_free (ibuf);
       return 0;
     }
   else if (oi->state == ISM_Down)
@@ -2441,7 +2424,6 @@ ospf_read (struct thread *thread)
                 inet_ntop(AF_INET, &iph->ip_src, buf[0], sizeof(buf[0])),
                 inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
                 ifp->name, if_flag_dump(ifp->flags));
-      stream_free (ibuf);
       /* Fix multicast memberships? */
       if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
        SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
@@ -2463,7 +2445,6 @@ ospf_read (struct thread *thread)
       zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)",
                  inet_ntoa (iph->ip_src), IF_NAME (oi),
                  LOOKUP (ospf_ism_state_msg, oi->state));
-      stream_free (ibuf);
       /* Try to fix multicast membership. */
       SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
       ospf_if_set_multicast(oi);
@@ -2500,7 +2481,6 @@ ospf_read (struct thread *thread)
                      ospf_packet_type_str[ospfh->type],
                      inet_ntoa (iph->ip_src));
         }
-      stream_free (ibuf);
       return ret;
     }
 
@@ -2534,7 +2514,6 @@ ospf_read (struct thread *thread)
       break;
     }
 
-  stream_free (ibuf);
   return 0;
 }
 
index 931ae49c59bae85ae65919b2dd9f9b92dfdf72ee..a77fb4b16d71a6169f5a6bb652b9afa73c639bd5 100644 (file)
@@ -204,9 +204,19 @@ ospf_new ()
                                           new, new->lsa_refresh_interval);
   new->lsa_refresher_started = time (NULL);
 
-  new->fd = ospf_sock_init ();
-  if (new->fd >= 0)
-    new->t_read = thread_add_read (master, ospf_read, new, new->fd);
+  if ((new->fd = ospf_sock_init()) < 0)
+    {
+      zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
+              "a socket");
+      exit(1);
+    }
+  if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
+    {
+      zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
+              OSPF_MAX_PACKET_SIZE+1);
+      exit(1);
+    }
+  new->t_read = thread_add_read (master, ospf_read, new, new->fd);
   new->oi_write_q = list_new ();
   
   return new;
@@ -360,6 +370,7 @@ ospf_finish (struct ospf *ospf)
   OSPF_TIMER_OFF (ospf->t_write);
 
   close (ospf->fd);
+  stream_free(ospf->ibuf);
    
 #ifdef HAVE_OPAQUE_LSA
   LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
index 0f778e0d5fc88a727d76527ca8233df9b7f4ef22..2a6c23e971b3fddbce8d95702cc5292fd1f6a146 100644 (file)
@@ -248,6 +248,7 @@ struct ospf
   struct thread *t_write;
   struct thread *t_read;
   int fd;
+  struct stream *ibuf;
   struct list *oi_write_q;
   
   /* Distribute lists out of other route sources. */