summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2010-08-05 10:26:23 -0700
committerPaul Jakma <paul@quagga.net>2011-03-21 17:30:52 +0000
commit35398589cf1293956dfefb5096aa5284c72a696f (patch)
treea0d844e42273fd0ee217652a6fd33552661f8b6f
parent2c9fd7e07283b8904ef20030c9dadb032e999b12 (diff)
bgpd: leave peer socket in non-blocking mode (mostly)
* 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.
-rw-r--r--bgpd/bgp_network.c1
-rw-r--r--bgpd/bgp_packet.c37
2 files changed, 15 insertions, 23 deletions
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 9e3427d2..4c79aa63 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -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));
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 9102add7..5620e0c4 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -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",