summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/control.c9
-rw-r--r--usr.sbin/bgpd/session.c42
-rw-r--r--usr.sbin/bgpd/session.h4
-rw-r--r--usr.sbin/bgpd/timer.c4
4 files changed, 42 insertions, 17 deletions
diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c
index 8ee3f50b5aa..84fa4ce92aa 100644
--- a/usr.sbin/bgpd/control.c
+++ b/usr.sbin/bgpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.70 2010/10/29 12:51:53 henning Exp $ */
+/* $OpenBSD: control.c,v 1.71 2012/04/12 17:26:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -122,7 +122,10 @@ control_accept(int listenfd, int restricted)
len = sizeof(sun);
if ((connfd = accept(listenfd,
(struct sockaddr *)&sun, &len)) == -1) {
- if (errno != EWOULDBLOCK && errno != EINTR)
+ if (errno == ENFILE || errno == EMFILE) {
+ pauseaccept = getmonotime();
+ return (0);
+ } else if (errno != EWOULDBLOCK && errno != EINTR)
log_warn("control_accept: accept");
return (0);
}
@@ -182,7 +185,7 @@ control_close(int fd)
close(c->ibuf.fd);
free(c);
-
+ pauseaccept = 0;
return (1);
}
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index c24eb9b3dc3..02d3840d84a 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.320 2012/01/06 17:33:11 sthen Exp $ */
+/* $OpenBSD: session.c,v 1.321 2012/04/12 17:26:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -107,6 +107,7 @@ struct imsgbuf *ibuf_rde_ctl;
struct imsgbuf *ibuf_main;
struct mrt_head mrthead;
+time_t pauseaccept;
void
session_sighdlr(int sig)
@@ -372,17 +373,25 @@ session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2],
* messages if the ctl sockets are getting full.
*/
pfd[PFD_PIPE_ROUTE_CTL].events = POLLIN;
- pfd[PFD_SOCK_CTL].fd = csock;
- pfd[PFD_SOCK_CTL].events = POLLIN;
- pfd[PFD_SOCK_RCTL].fd = rcsock;
- pfd[PFD_SOCK_RCTL].events = POLLIN;
+ if (pauseaccept == 0) {
+ pfd[PFD_SOCK_CTL].fd = csock;
+ pfd[PFD_SOCK_CTL].events = POLLIN;
+ pfd[PFD_SOCK_RCTL].fd = rcsock;
+ pfd[PFD_SOCK_RCTL].events = POLLIN;
+ } else {
+ pfd[PFD_SOCK_CTL].fd = -1;
+ pfd[PFD_SOCK_RCTL].fd = -1;
+ }
pfd[PFD_SOCK_PFKEY].fd = pfkeysock;
pfd[PFD_SOCK_PFKEY].events = POLLIN;
i = PFD_LISTENERS_START;
TAILQ_FOREACH(la, conf->listen_addrs, entry) {
- pfd[i].fd = la->fd;
- pfd[i].events = POLLIN;
+ if (pauseaccept == 0) {
+ pfd[i].fd = la->fd;
+ pfd[i].events = POLLIN;
+ } else
+ pfd[i].fd = -1;
i++;
}
idx_listeners = i;
@@ -469,12 +478,21 @@ session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2],
i++;
}
+ if (pauseaccept && timeout > 1)
+ timeout = 1;
if (timeout < 0)
timeout = 0;
if ((nfds = poll(pfd, i, timeout * 1000)) == -1)
if (errno != EINTR)
fatal("poll error");
+ /*
+ * If we previously saw fd exhaustion, we stop accept()
+ * for 1 second to throttle the accept() loop.
+ */
+ if (pauseaccept && getmonotime() > pauseaccept + 1)
+ pauseaccept = 0;
+
if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & POLLOUT)
if (msgbuf_write(&ibuf_main->w) < 0)
fatal("pipe write error");
@@ -869,9 +887,10 @@ start_timer_keepalive(struct peer *peer)
void
session_close_connection(struct peer *peer)
{
- if (peer->fd != -1)
+ if (peer->fd != -1) {
close(peer->fd);
-
+ pauseaccept = 0;
+ }
peer->fd = peer->wbuf.fd = -1;
}
@@ -975,7 +994,10 @@ session_accept(int listenfd)
len = sizeof(cliaddr);
if ((connfd = accept(listenfd,
(struct sockaddr *)&cliaddr, &len)) == -1) {
- if (errno == EWOULDBLOCK || errno == EINTR)
+ if (errno == ENFILE || errno == EMFILE) {
+ pauseaccept = getmonotime();
+ return;
+ } else if (errno == EWOULDBLOCK || errno == EINTR)
return;
else
log_warn("accept");
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index a8f52685625..5b300aa6148 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.112 2011/09/18 09:31:25 claudio Exp $ */
+/* $OpenBSD: session.h,v 1.113 2012/04/12 17:26:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -226,6 +226,7 @@ struct peer {
};
extern struct peer *peers;
+extern time_t pauseaccept;
struct ctl_timer {
enum Timer type;
@@ -296,6 +297,7 @@ int imsg_compose_rde(int, pid_t, void *, u_int16_t);
void session_stop(struct peer *, u_int8_t);
/* timer.c */
+time_t getmonotime(void);
struct peer_timer *timer_get(struct peer *, enum Timer);
struct peer_timer *timer_nextisdue(struct peer *);
time_t timer_nextduein(struct peer *);
diff --git a/usr.sbin/bgpd/timer.c b/usr.sbin/bgpd/timer.c
index 0aaba0886a2..1690708e7ce 100644
--- a/usr.sbin/bgpd/timer.c
+++ b/usr.sbin/bgpd/timer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: timer.c,v 1.14 2010/10/24 17:20:08 deraadt Exp $ */
+/* $OpenBSD: timer.c,v 1.15 2012/04/12 17:26:09 claudio Exp $ */
/*
* Copyright (c) 2003-2007 Henning Brauer <henning@openbsd.org>
@@ -23,8 +23,6 @@
#include "bgpd.h"
#include "session.h"
-time_t getmonotime(void);
-
time_t
getmonotime(void)
{