diff options
-rw-r--r-- | usr.sbin/bgpd/control.c | 9 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 42 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/timer.c | 4 |
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) { |