summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2016-04-06 11:49:34 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2016-04-06 11:49:34 +0200
commit9e7b3ebdf9556d7464911dd39e862b1c003319b3 (patch)
treef1b3415e75106fd7d1ab7d17c7c47cb6e0f7583d
parente86cfd41d975122cc944db68383aef4028da9575 (diff)
IO: Replace RX priority heuristic with explicit mark
In BIRD, RX has lower priority than TX with the exception of RX from control socket. The patch replaces heuristic based on socket type with explicit mark and uses it for both control socket and BGP session waiting to be established. This should avoid an issue when during heavy load, outgoing connection could connect (TX event), send open, but then failed to receive OPEN / establish in time, not sending notifications between and therefore got hold timer expired error from the neighbor immediately after it finally established the connection.
-rw-r--r--lib/socket.h1
-rw-r--r--proto/bgp/bgp.c3
-rw-r--r--sysdep/unix/io.c4
-rw-r--r--sysdep/unix/main.c2
4 files changed, 8 insertions, 2 deletions
diff --git a/lib/socket.h b/lib/socket.h
index fbea92aa..0327e9e5 100644
--- a/lib/socket.h
+++ b/lib/socket.h
@@ -28,6 +28,7 @@ typedef struct birdsock {
struct iface *iface; /* Interface; specify this for broad/multicast sockets */
byte *rbuf, *rpos; /* NULL=allocate automatically */
+ uint fast_rx; /* RX has higher priority in event loop */
uint rbsize;
int (*rx_hook)(struct birdsock *, int size); /* NULL=receiving turned off, returns 1 to clear rx buffer */
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 11f33b14..7328cb79 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -374,6 +374,8 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
if (ipa_zero(p->source_addr))
p->source_addr = conn->sk->saddr;
+ conn->sk->fast_rx = 0;
+
p->conn = conn;
p->last_error_class = 0;
p->last_error_code = 0;
@@ -696,6 +698,7 @@ bgp_setup_sk(struct bgp_conn *conn, sock *s)
{
s->data = conn;
s->err_hook = bgp_sock_err;
+ s->fast_rx = 1;
conn->sk = s;
}
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 112ebe91..078fe73c 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -2152,7 +2152,7 @@ io_loop(void)
int steps;
steps = MAX_STEPS;
- if ((s->type >= SK_MAGIC) && (pfd[s->index].revents & (POLLIN | POLLHUP | POLLERR)) && s->rx_hook)
+ if (s->fast_rx && (pfd[s->index].revents & (POLLIN | POLLHUP | POLLERR)) && s->rx_hook)
do
{
steps--;
@@ -2197,7 +2197,7 @@ io_loop(void)
goto next2;
}
- if ((s->type < SK_MAGIC) && (pfd[s->index].revents & (POLLIN | POLLHUP | POLLERR)) && s->rx_hook)
+ if (!s->fast_rx && (pfd[s->index].revents & (POLLIN | POLLHUP | POLLERR)) && s->rx_hook)
{
count++;
io_log_event(s->rx_hook, s->data);
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 24d34f60..5d5586a0 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -450,6 +450,7 @@ cli_connect(sock *s, int size UNUSED)
s->err_hook = cli_err;
s->data = c = cli_new(s);
s->pool = c->pool; /* We need to have all the socket buffers allocated in the cli pool */
+ s->fast_rx = 1;
c->rx_pos = c->rx_buf;
c->rx_aux = NULL;
rmove(s, c->pool);
@@ -466,6 +467,7 @@ cli_init_unix(uid_t use_uid, gid_t use_gid)
s->type = SK_UNIX_PASSIVE;
s->rx_hook = cli_connect;
s->rbsize = 1024;
+ s->fast_rx = 1;
/* Return value intentionally ignored */
unlink(path_control_socket);