diff options
author | David Lamparter <equinox@diac24.net> | 2010-02-04 03:00:46 +0100 |
---|---|---|
committer | David Lamparter <equinox@diac24.net> | 2010-02-04 03:30:17 +0100 |
commit | f4b356490dc03d3758b50da11b1548254fb56138 (patch) | |
tree | ead2e56720973f2f1c7eebe0ae032f2c826bc328 /bgpd | |
parent | 7d5fe54553c735a12e3fc40c3d9f0e59c79a33c6 (diff) | |
parent | 2442cdc3064f87860972ce6397fbaab52e200a00 (diff) | |
download | quagga-f4b356490dc03d3758b50da11b1548254fb56138.tar.bz2 quagga-f4b356490dc03d3758b50da11b1548254fb56138.tar.xz |
Merge branch 'patches/sh_bgp-write-cork' into dn42
Conflicts:
lib/sockunion.c
Diffstat (limited to 'bgpd')
-rw-r--r-- | bgpd/bgp_fsm.c | 2 | ||||
-rw-r--r-- | bgpd/bgp_network.c | 1 | ||||
-rw-r--r-- | bgpd/bgp_packet.c | 80 | ||||
-rw-r--r-- | bgpd/bgpd.c | 3 |
4 files changed, 38 insertions, 48 deletions
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 487ebddb..e18fc8cd 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -704,7 +704,7 @@ bgp_start (struct peer *peer) peer->fd); return -1; } - BGP_READ_ON (peer->t_read, bgp_read, peer->fd); + BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); break; } diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index be01bbd6..83b1142e 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 b29bc1f0..1e2f95e3 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -107,8 +107,7 @@ bgp_connect_check (struct peer *peer) socklen_t slen; int ret; - /* Anyway I have to reset read and write thread. */ - BGP_READ_OFF (peer->t_read); + /* Anyway I have to reset write thread. */ BGP_WRITE_OFF (peer->t_write); /* Check file descriptor. */ @@ -597,7 +596,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); @@ -610,46 +608,37 @@ bgp_write (struct thread *thread) return 0; } - /* Nonblocking write until TCP output buffer is full. */ - while (1) + s = bgp_write_packet (peer); + if (!s) + return 0; /* nothing to send */ + + sockopt_cork (peer->fd, 1); + + /* Nonblocking write until TCP output buffer is full. */ + do { int writenum; - int val; - - 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; + /* write failed either retry needed or error */ + if (ERRNO_IO_RETRY(errno)) + break; 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; + break; } /* Retrieve BGP packet type. */ @@ -690,13 +679,14 @@ bgp_write (struct thread *thread) /* OK we send packet so delete it. */ bgp_packet_delete (peer); - - if (++count >= BGP_WRITE_PACKET_MAX) - break; } + while (++count < BGP_WRITE_PACKET_MAX && + (s = bgp_write_packet (peer)) != NULL); if (bgp_write_proceed (peer)) BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + else + sockopt_cork (peer->fd, 0); return 0; } @@ -705,7 +695,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; @@ -715,7 +705,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) { @@ -2237,12 +2230,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", @@ -2319,22 +2313,14 @@ bgp_read (struct thread *thread) peer = THREAD_ARG (thread); peer->t_read = NULL; - /* For non-blocking IO check. */ - if (peer->status == Connect) - { - bgp_connect_check (peer); - goto done; - } - else + if (peer->fd < 0) { - if (peer->fd < 0) - { - zlog_err ("bgp_read peer's fd is negative value %d", peer->fd); - return -1; - } - BGP_READ_ON (peer->t_read, bgp_read, peer->fd); + zlog_err ("bgp_read peer's fd is negative value %d", peer->fd); + return -1; } + BGP_READ_ON (peer->t_read, bgp_read, peer->fd); + /* Read packet header to determine type of the packet */ if (peer->packet_size == 0) peer->packet_size = BGP_HEADER_SIZE; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 882fe37c..a03025f6 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2257,6 +2257,9 @@ peer_change_action (struct peer *peer, afi_t afi, safi_t safi, if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) return; + if (peer->status != Established) + return; + if (type == peer_change_reset) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); |