[netflow-tools] Patch to allow explicit specification of SO_SNDBUF and SO_RCVBUF

Jesse Kempf kempfj2 at cs.rpi.edu
Wed Oct 24 05:37:04 EST 2007


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 *);
 


More information about the netflow-tools mailing list