Index | Thread | Search

From:
David Hill <dhill@mindcry.org>
Subject:
tcpbench - fix ipv6/udp (diff)
To:
tech@openbsd.org
Date:
Sat, 30 Aug 2025 00:53:25 +0000

Download raw body.

Thread
Hello -

When using tcpbench with IPv6 and UDP, it showed poor performance. 
Using -vvv, I saw it writing 1472 bytes.   With -B 1452 (1500 - 40 - 8) 
(mtu - ipv6 header - udp header) I get proper performance.

I saw in the code a TODO, so thought I'd take a stab at it.

# tcpbench -su
Elapsed:        1010 Mbps:      37.695 Peak Mbps:      37.695 Rx PPS: 
3200
Elapsed:        2020 Mbps:       1.961 Peak Mbps:      37.695 Rx PPS: 
  166
Elapsed:        3030 Mbps:       0.000 Peak Mbps:      37.695 Rx PPS: 
    0
Elapsed:        4040 Mbps:       0.000 Peak Mbps:      37.695 Rx PPS: 
    0
Elapsed:        5050 Mbps:       0.000 Peak Mbps:      37.695 Rx PPS: 
    0
Elapsed:        6060 Mbps:       0.000 Peak Mbps:      37.695 Rx PPS: 
    0
Elapsed:        7070 Mbps:       0.000 Peak Mbps:      37.695 Rx PPS: 
    0
Elapsed:        8080 Mbps:       0.000 Peak Mbps:      37.695 Rx PPS: 
    0
Elapsed:        9090 Mbps:       0.000 Peak Mbps:      37.695 Rx PPS:

server after:
# tcpbench -su
Elapsed:        1000 Mbps:      50.425 Peak Mbps:      50.425 Rx PPS: 
4341
Elapsed:        2000 Mbps:      33.768 Peak Mbps:      50.425 Rx PPS: 
2907
Elapsed:        3014 Mbps:      39.813 Peak Mbps:      50.425 Rx PPS: 
3427
Elapsed:        4024 Mbps:      48.064 Peak Mbps:      50.425 Rx PPS: 
4137
Elapsed:        5024 Mbps:      33.861 Peak Mbps:      50.425 Rx PPS: 
2915

Index: usr.bin/tcpbench/tcpbench.c
===================================================================
RCS file: /cvs/src/usr.bin/tcpbench/tcpbench.c,v
diff -u -p -r1.73 tcpbench.c
--- usr.bin/tcpbench/tcpbench.c	30 Dec 2024 21:19:29 -0000	1.73
+++ usr.bin/tcpbench/tcpbench.c	30 Aug 2025 00:52:08 -0000
@@ -61,7 +61,6 @@
  #define DEFAULT_PORT "12345"
  #define DEFAULT_STATS_INTERVAL 1000 /* ms */
  #define DEFAULT_BUF (256 * 1024)
-#define DEFAULT_UDP_PKT (1500 - 28) /* TODO don't hardcode this */
  #define TCP_MODE !ptb->uflag
  #define UDP_MODE ptb->uflag
  #define MAX_FD 1024
@@ -117,6 +116,7 @@ static void	print_tcp_header(void);
  static void	list_kvars(void);
  static void	check_kvar(const char *);
  static char **	check_prepare_kvars(char *);
+static void	dummybuf_prepare(struct statctx *);
  static void	stats_prepare(struct statctx *);
  static void	summary_display(void);
  static void	tcp_stats_display(unsigned long long, long double, float,
@@ -352,8 +352,44 @@ check_prepare_kvars(char *list)
  }

  static void
+dummybuf_prepare(struct statctx *sc)
+{
+	/*
+	 * Rationale,
+	 * If TCP, use a big buffer with big reads/writes.
+	 * If UDP, use a big buffer in server and a buffer the size of a
+	 * ethernet packet.
+	 */
+	if (ptb->dummybuf_len == 0 && (ptb->sflag || TCP_MODE))
+		ptb->dummybuf_len = DEFAULT_BUF;
+		
+	if (ptb->dummybuf_len == 0) {
+		struct sockaddr_storage ss;
+		socklen_t len = sizeof(ss);
+
+		if (getsockname(sc->fd, (struct sockaddr *)&ss, &len) == -1)
+			err(1, "getsockname");
+
+		switch (ss.ss_family) {
+		case AF_INET:
+			ptb->dummybuf_len = 1500-28;
+		case AF_INET6:
+		default:
+			ptb->dummybuf_len = 1500-48;
+			break;
+		}
+	}
+
+	if ((ptb->dummybuf = malloc(ptb->dummybuf_len)) == NULL)
+		err(1, "malloc");
+	arc4random_buf(ptb->dummybuf, ptb->dummybuf_len);
+}
+
+static void
  stats_prepare(struct statctx *sc)
  {
+	dummybuf_prepare(sc);
+
  	sc->buf = ptb->dummybuf;
  	sc->buflen = ptb->dummybuf_len;

@@ -1276,19 +1312,6 @@ main(int argc, char **argv)
  	if (pledge("stdio id dns inet unix", NULL) == -1)
  		err(1, "pledge");

-	/*
-	 * Rationale,
-	 * If TCP, use a big buffer with big reads/writes.
-	 * If UDP, use a big buffer in server and a buffer the size of a
-	 * ethernet packet.
-	 */
-	if (!ptb->dummybuf_len) {
-		if (ptb->sflag || TCP_MODE)
-			ptb->dummybuf_len = DEFAULT_BUF;
-		else
-			ptb->dummybuf_len = DEFAULT_UDP_PKT;
-	}
-
  	bzero(&hints, sizeof(hints));
  	hints.ai_family = family;
  	if (UDP_MODE) {
@@ -1375,9 +1398,6 @@ main(int argc, char **argv)

  	/* Init world */
  	TAILQ_INIT(&sc_queue);
-	if ((ptb->dummybuf = malloc(ptb->dummybuf_len)) == NULL)
-		err(1, "malloc");
-	arc4random_buf(ptb->dummybuf, ptb->dummybuf_len);

  	timerclear(&mainstats.t_first);
  	mainstats.floor_mbps = INFINITY;