]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: leave peer socket in non-blocking mode (mostly)
authorStephen Hemminger <shemminger@vyatta.com>
Thu, 5 Aug 2010 17:26:23 +0000 (10:26 -0700)
committerPaul Jakma <paul@quagga.net>
Mon, 21 Mar 2011 17:30:52 +0000 (17:30 +0000)
* bgpd: Rather than toggling socket in/out of non-block mode, just leave it
  in nonblocking mode.

  One exception is in bgp_notify which only happens just before close.

bgpd/bgp_network.c
bgpd/bgp_packet.c

index 9e3427d2a4ee821da36be2b42a7bef2301fdc0eb..4c79aa6385564089a94c53ef8a4bcca799073b6f 100644 (file)
@@ -150,6 +150,7 @@ bgp_accept (struct thread *thread)
       zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno));
       return -1;
     }
+  set_nonblocking (bgp_sock);
 
   if (BGP_DEBUG (events, EVENTS))
     zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
index 9102add73547b3aee110b64bae6b885ee0fed8de..5620e0c4f58c8c6c8ffaf9cd3f9b5307897e6918 100644 (file)
@@ -598,7 +598,6 @@ bgp_write (struct thread *thread)
   struct stream *s; 
   int num;
   unsigned int count = 0;
-  int write_errno;
 
   /* Yes first of all get peer pointer. */
   peer = THREAD_ARG (thread);
@@ -620,36 +619,24 @@ bgp_write (struct thread *thread)
       s = bgp_write_packet (peer);
       if (! s)
        return 0;
-      
-      /* XXX: FIXME, the socket should be NONBLOCK from the start
-       * status shouldnt need to be toggled on each write
-       */
-      val = fcntl (peer->fd, F_GETFL, 0);
-      fcntl (peer->fd, F_SETFL, val|O_NONBLOCK);
 
       /* Number of bytes to be sent.  */
       writenum = stream_get_endp (s) - stream_get_getp (s);
 
       /* Call write() system call.  */
       num = write (peer->fd, STREAM_PNT (s), writenum);
-      write_errno = errno;
-      fcntl (peer->fd, F_SETFL, val);
-      if (num <= 0)
+      if (num < 0)
        {
-         /* Partial write. */
-         if (write_errno == EWOULDBLOCK || write_errno == EAGAIN)
-             break;
-
-         BGP_EVENT_ADD (peer, TCP_fatal_error);
+         /* need to try again */
+         if (!ERRNO_IO_RETRY(errno))
+           BGP_EVENT_ADD (peer, TCP_fatal_error);
          return 0;
        }
+
       if (num != writenum)
        {
+         /* Partial write */
          stream_forward_getp (s, num);
-
-         if (write_errno == EAGAIN)
-           break;
-
          continue;
        }
 
@@ -706,7 +693,7 @@ bgp_write (struct thread *thread)
 static int
 bgp_write_notify (struct peer *peer)
 {
-  int ret;
+  int ret, val;
   u_char type;
   struct stream *s; 
 
@@ -716,7 +703,10 @@ bgp_write_notify (struct peer *peer)
     return 0;
   assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
 
-  /* I'm not sure fd is writable. */
+  /* Put socket in blocking mode. */
+  val = fcntl (peer->fd, F_GETFL, 0);
+  fcntl (peer->fd, F_SETFL, val & ~O_NONBLOCK);
+
   ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s));
   if (ret <= 0)
     {
@@ -2263,12 +2253,13 @@ bgp_read_packet (struct peer *peer)
     return 0;
 
   /* Read packet from fd. */
-  nbytes = stream_read_unblock (peer->ibuf, peer->fd, readsize);
+  nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
 
   /* If read byte is smaller than zero then error occured. */
   if (nbytes < 0) 
     {
-      if (errno == EAGAIN)
+      /* Transient error should retry */
+      if (nbytes == -2)
        return -1;
 
       plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",