Jesse Kempf
2007-Oct-23 19:37 UTC
[netflow-tools] Patch to allow explicit specification of SO_SNDBUF and SO_RCVBUF
I''ve inlined the diff at the bottom of the email. In short, this patch makes it possible to specify the receive buffer size for each ``listen on'''' directive, and the send buffer size for ``logsock''''. There''s some receive buffer guessing for listening sockets already, but I figured it would be more helpful (and more precise) to let the administrator explicitly tune the values. Well, that and I just had need to take a crack at tuning these values. Cheers, -Jesse Kempf Index: flowd-bufsiz/parse.y ==================================================================--- flowd-bufsiz/parse.y (revision 173) +++ flowd-bufsiz/parse.y (revision 177) @@ -102,7 +102,7 @@ %} -%token LISTEN ON JOIN GROUP LOGFILE LOGSOCK STORE PIDFILE FLOW SOURCE +%token LISTEN ON JOIN GROUP LOGFILE LOGSOCK BUFSIZE STORE PIDFILE FLOW SOURCE %token ALL TAG ACCEPT DISCARD QUICK AGENT SRC DST PORT PROTO TOS ANY %token TCP_FLAGS EQUALS MASK INET INET6 DAYS AFTER BEFORE DATE %token IN_IFNDX OUT_IFNDX @@ -385,8 +385,22 @@ la->fd = -1; la->addr = $3.addr; la->port = $3.port; + la->bufsiz = 0; TAILQ_INSERT_TAIL(&conf->listen_addrs, la, entry); } + | LISTEN ON address_port BUFSIZE number { + struct listen_addr *la; + + if ((la = calloc(1, sizeof(*la))) == NULL) + logerrx("listen_on: calloc"); + + la->fd = -1; + la->addr = $3.addr; + la->port = $3.port; + la->bufsiz = $5; + TAILQ_INSERT_TAIL(&conf->listen_addrs, la, entry); + + } | FLOW SOURCE prefix_or_any { struct allowed_device *ad; @@ -414,6 +428,10 @@ | LOGSOCK string { conf->log_socket = $2; } + | LOGSOCK string BUFSIZE number { + conf->log_socket = $2; + conf->log_socket_bufsiz = $4; + } | PIDFILE string { conf->pid_file = $2; } @@ -902,6 +920,7 @@ { "all", ALL}, { "any", ANY}, { "before", BEFORE}, + { "bufsize", BUFSIZE}, { "date", DATE}, { "days", DAYS}, { "discard", DISCARD}, Index: flowd-bufsiz/flowd.c ==================================================================--- flowd-bufsiz/flowd.c (revision 173) +++ flowd-bufsiz/flowd.c (revision 177) @@ -1365,7 +1365,7 @@ struct listen_addr *la; TAILQ_FOREACH(la, &conf->listen_addrs, entry) { - if ((la->fd = open_listener(&la->addr, la->port, + if ((la->fd = open_listener(&la->addr, la->port, la->bufsiz, &conf->join_groups)) == -1) { logerrx("Listener setup of [%s]:%d failed", addr_ntop_buf(&la->addr), la->port); Index: flowd-bufsiz/flowd.h ==================================================================--- flowd-bufsiz/flowd.h (revision 173) +++ flowd-bufsiz/flowd.h (revision 177) @@ -55,6 +55,7 @@ struct xaddr addr; u_int16_t port; int fd; + size_t bufsiz; TAILQ_ENTRY(listen_addr) entry; }; TAILQ_HEAD(listen_addrs, listen_addr); @@ -72,6 +73,7 @@ struct flowd_config { char *log_file; char *log_socket; + size_t log_socket_bufsiz; char *pid_file; u_int32_t store_mask; u_int32_t opts; Index: flowd-bufsiz/flowd.conf.5.in ==================================================================--- flowd-bufsiz/flowd.conf.5.in (revision 173) +++ flowd-bufsiz/flowd.conf.5.in (revision 177) @@ -135,7 +135,20 @@ listen on [::]:12345 .Ed .Pp -This option is mandatory, there is no default value. + +This option accepts the modifier +.Pa bufsize +to allow the specification (in bytes) of the receive buffer for this socket. +.Pp +For example, +.Bd -literal -offset indent +listen on 0.0.0.0:12345 bufsize 9876 +.Ed +.Pp +The +.Cm listen on +directive is mandatory. There is no default value. + .It Ar logfile Specifies the file in which the received flow records are stored. The full path to the file must be specified in quotes. @@ -161,7 +174,18 @@ logsock "/var/log/flowd.sock" .Ed .Pp -There is no default value for this option and it it mandatory +This option accepts the modifier +.Pa bufsize +to allow the specification (in bytes) of the send buffer for this socket. +.Pp +For example, +.Bd -literal -offset indent +logsock "/var/log/flowd.sock" bufsize 1234 +.Ed +.Pp +There is no default value for +.Cm logfile +and it is mandatory to specify at least one of the .Cm logfile and Index: flowd-bufsiz/privsep.c ==================================================================--- flowd-bufsiz/privsep.c (revision 173) +++ flowd-bufsiz/privsep.c (revision 177) @@ -119,7 +119,7 @@ } int -open_listener(struct xaddr *addr, u_int16_t port, struct join_groups *groups) +open_listener(struct xaddr *addr, u_int16_t port, size_t bufsiz, struct join_groups *groups) { int fd, fl, i, orig; struct sockaddr_storage ss; @@ -167,10 +167,23 @@ logit(LOG_DEBUG, "Listener for [%s]:%d fd = %d", addr_ntop_buf(addr), port, fd); - /* Crank up socket receive buffer size to cope with bursts of flows */ + /* Crank up socket receive buffer size to cope with bursts of flows + * If the config doesn''t contain an explicit buffer size, we + * fall back to guessing. + */ + slen = sizeof(fl); if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &orig, &slen) == 0) { - for (i = 3; i >= 1; i--) { + if (bufsiz > 0) { + fl = bufsiz; + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, + &bufsiz, sizeof(bufsiz)) == 0) { + logit(LOG_DEBUG, "Increased socket receive " + "buffer from %d to %d", orig, fl); + } else if (i == 1) + logerr("%s: setsockopt(SO_RCVBUF)", __func__); + } else{ + for (i = 3; i >= 1; i--) { fl = (1024 * 64) << i; if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &fl, sizeof(fl)) == 0) { @@ -179,6 +192,7 @@ break; } else if (i == 1) logitm(LOG_DEBUG, "setsockopt(SO_RCVBUF)"); + } } } @@ -300,6 +314,13 @@ newconf.log_file = privsep_read_string(fd, 1); newconf.log_socket = privsep_read_string(fd, 1); + if (atomicio(read, fd, &newconf.log_socket_bufsiz, + sizeof(newconf.log_socket_bufsiz)) !+ sizeof(newconf.log_socket_bufsiz)) { + logitm(LOG_ERR, "%s: read(conf.log_socket_bufsiz)", __func__); + return (-1); + } + if ((newconf.pid_file = privsep_read_string(fd, 0)) == NULL) { logit(LOG_ERR, "%s: Couldn''t read conf.pid_file", __func__); return (-1); @@ -431,6 +452,13 @@ logit(LOG_ERR, "%s: Couldn''t write conf.log_socket", __func__); return (-1); } + if (atomicio(vwrite, fd, &conf->log_socket_bufsiz, + sizeof(conf->log_socket_bufsiz)) !+ sizeof(conf->log_socket_bufsiz)) { + logitm(LOG_ERR, "%s: write(conf.log_socket_bufsiz)", __func__); + return (-1); + } + if (privsep_write_string(fd, conf->pid_file, 0) == -1) { logit(LOG_ERR, "%s: Couldn''t write conf.pid_file", __func__); return (-1); @@ -581,7 +609,7 @@ FILE *cfg; struct passwd *pw = NULL; struct flowd_config newconf = { - NULL, NULL, NULL, 0, 0, + NULL, NULL, 0, NULL, 0, 0, TAILQ_HEAD_INITIALIZER(newconf.listen_addrs), TAILQ_HEAD_INITIALIZER(newconf.filter_list), TAILQ_HEAD_INITIALIZER(newconf.allowed_devices), @@ -786,7 +814,7 @@ static int answer_open_socket(struct flowd_config *conf, int client_fd) { - int fd; + int fd, slen, orig; struct sockaddr_un to; socklen_t tolen; @@ -816,6 +844,20 @@ return (-1); } + slen = sizeof(orig); + if (conf->log_socket_bufsiz > 0 && + getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &orig, &slen) == 0) { + + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, + &conf->log_socket_bufsiz, + sizeof(conf->log_socket_bufsiz)) == 0) { + logit(LOG_DEBUG, "Increased log_socket send " + "buffer from %d to %d", orig, + conf->log_socket_bufsiz); + } else + logerr("%s: setsockopt(SO_SNDBUF)", __func__); + } + if (send_fd(client_fd, fd) == -1) return (-1); @@ -850,7 +892,7 @@ } TAILQ_FOREACH(la, &newconf.listen_addrs, entry) { - if ((la->fd = open_listener(&la->addr, la->port, + if ((la->fd = open_listener(&la->addr, la->port, la->bufsiz, &conf->join_groups)) == -1) { logit(LOG_ERR, "Listener setup of [%s]:%d failed", addr_ntop_buf(&la->addr), la->port); Index: flowd-bufsiz/privsep.h ==================================================================--- flowd-bufsiz/privsep.h (revision 173) +++ flowd-bufsiz/privsep.h (revision 177) @@ -27,7 +27,7 @@ void privsep_init(struct flowd_config *, int *, const char *); int client_open_log(int); int client_open_socket(int); -int open_listener(struct xaddr *, u_int16_t, struct join_groups *); +int open_listener(struct xaddr *, u_int16_t, size_t, struct join_groups *); int read_config(const char *, struct flowd_config *); int client_reconfigure(int, struct flowd_config *);
Damien Miller
2007-Oct-24 01:05 UTC
[netflow-tools] Patch to allow explicit specification of SO_SNDBUF and SO_RCVBUF
On Tue, 23 Oct 2007, Jesse Kempf wrote:> > I''ve inlined the diff at the bottom of the email. > > In short, this patch makes it possible to specify the receive buffer > size for each ``listen on'''' directive, and the send buffer size for > ``logsock''''. > > There''s some receive buffer guessing for listening sockets already, > but I figured it would be more helpful (and more precise) to let the > administrator explicitly tune the values. Well, that and I just had > need to take a crack at tuning these values.Applied (with some trivial tweaks) - thanks! It would be good if you could specify a scale suffix to the bufsize number, e.g. "listen on 0.0.0.0:1234 bufsize 512k", if you are interested in doing more work :) -d