git: b4e9bfd51c2d - stable/13 - netmap: pkt-gen: sync with upstream

From: Vincenzo Maffione <vmaffione_at_FreeBSD.org>
Date: Tue, 09 May 2023 20:39:42 UTC
The branch stable/13 has been updated by vmaffione:

URL: https://cgit.FreeBSD.org/src/commit/?id=b4e9bfd51c2d6f66291c89c3e8f4c5809f1be447

commit b4e9bfd51c2d6f66291c89c3e8f4c5809f1be447
Author:     Vincenzo Maffione <vmaffione@FreeBSD.org>
AuthorDate: 2023-04-26 20:32:24 +0000
Commit:     Vincenzo Maffione <vmaffione@FreeBSD.org>
CommitDate: 2023-05-09 20:39:36 +0000

    netmap: pkt-gen: sync with upstream
    
    Keep in sync with the recent upstream changes:
    
    Fix compilation on 32-bit architectures
    Update IP length, UDP length/checksum when size changes
    Man page fixes
    
    Submitted by:   jlduran@gmail.com
    MFC after:      7 days
    Differential Revision:  https://reviews.freebsd.org/D39760
    
    (cherry picked from commit 8c3b8c838674239538682b914bc1d7059255f116)
---
 tools/tools/netmap/pkt-gen.8 |  7 ++--
 tools/tools/netmap/pkt-gen.c | 86 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 88 insertions(+), 5 deletions(-)

diff --git a/tools/tools/netmap/pkt-gen.8 b/tools/tools/netmap/pkt-gen.8
index c3f0330e46ba..2a80f160bb9d 100644
--- a/tools/tools/netmap/pkt-gen.8
+++ b/tools/tools/netmap/pkt-gen.8
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 21, 2020
+.Dd April 21, 2023
 .Dt PKT-GEN 8
 .Os
 .Sh NAME
@@ -150,7 +150,7 @@ mode), a single RX ring (in
 mode), or a TX/RX ring pair.
 The number of
 .Ar threads
-must be less than or equal to the number of TX (or RX) ring available
+must be less than or equal to the number of TX (or RX) rings available
 in the device specified by
 .Ar interface .
 .It Fl T Ar report_ms
@@ -288,7 +288,8 @@ length of 128 bytes.
 You must set the destination MAC address for
 packets to be received by the target host.
 .Bd -literal -offset indent
-pkt-gen -i netmap:ncxl0 -f tx -s 172.16.0.1:53 -d 172.16.1.3:53 -D 00:07:43:29:2a:e0
+pkt-gen -i netmap:ncxl0 -f tx -s 172.16.0.1:53 -d 172.16.1.3:53 \e
+-D 00:07:43:29:2a:e0
 .Ed
 .Sh SEE ALSO
 .Xr netmap 4 ,
diff --git a/tools/tools/netmap/pkt-gen.c b/tools/tools/netmap/pkt-gen.c
index 296208018fd4..621e3e215118 100644
--- a/tools/tools/netmap/pkt-gen.c
+++ b/tools/tools/netmap/pkt-gen.c
@@ -283,6 +283,7 @@ struct glob_arg {
 #define OPT_RANDOM_SRC  512
 #define OPT_RANDOM_DST  1024
 #define OPT_PPS_STATS   2048
+#define OPT_UPDATE_CSUM 4096
 	int dev_type;
 #ifndef NO_PCAP
 	pcap_t *p;
@@ -1005,6 +1006,85 @@ update_addresses(struct pkt *pkt, struct targ *t)
 	else
 		update_ip6(pkt, t);
 }
+
+static void
+update_ip_size(struct pkt *pkt, int size)
+{
+	struct ip ip;
+	struct udphdr udp;
+	uint16_t oiplen, niplen;
+	uint16_t nudplen;
+	uint16_t ip_sum = 0;
+
+	memcpy(&ip, &pkt->ipv4.ip, sizeof(ip));
+	memcpy(&udp, &pkt->ipv4.udp, sizeof(udp));
+
+	oiplen = ntohs(ip.ip_len);
+	niplen = size - sizeof(struct ether_header);
+	ip.ip_len = htons(niplen);
+	nudplen = niplen - sizeof(struct ip);
+	udp.uh_ulen = htons(nudplen);
+	ip_sum = new_udp_sum(ip_sum, oiplen, niplen);
+
+	/* update checksums */
+	if (ip_sum != 0)
+		ip.ip_sum = ~cksum_add(~ip.ip_sum, htons(ip_sum));
+
+	udp.uh_sum = 0;
+	/* Magic: taken from sbin/dhclient/packet.c */
+	udp.uh_sum = wrapsum(
+		checksum(&udp, sizeof(udp),	/* udp header */
+		checksum(pkt->ipv4.body,	/* udp payload */
+		nudplen - sizeof(udp),
+		checksum(&ip.ip_src, /* pseudo header */
+		2 * sizeof(ip.ip_src),
+		IPPROTO_UDP + (u_int32_t)ntohs(udp.uh_ulen)))));
+
+	memcpy(&pkt->ipv4.ip, &ip, sizeof(ip));
+	memcpy(&pkt->ipv4.udp, &udp, sizeof(udp));
+}
+
+static void
+update_ip6_size(struct pkt *pkt, int size)
+{
+	struct ip6_hdr ip6;
+	struct udphdr udp;
+	uint16_t niplen, nudplen;
+	uint32_t csum;
+
+	memcpy(&ip6, &pkt->ipv6.ip, sizeof(ip6));
+	memcpy(&udp, &pkt->ipv6.udp, sizeof(udp));
+
+	nudplen = niplen = size - sizeof(struct ether_header) - sizeof(ip6);
+	ip6.ip6_plen = htons(niplen);
+	udp.uh_ulen = htons(nudplen);
+
+	/* Save part of pseudo header checksum into csum */
+	udp.uh_sum = 0;
+	csum = IPPROTO_UDP << 24;
+	csum = checksum(&csum, sizeof(csum), nudplen);
+	udp.uh_sum = wrapsum(
+		checksum(&udp, sizeof(udp),	/* udp header */
+		checksum(pkt->ipv6.body,	/* udp payload */
+		nudplen - sizeof(udp),
+		checksum(&pkt->ipv6.ip.ip6_src, /* pseudo header */
+		2 * sizeof(pkt->ipv6.ip.ip6_src), csum))));
+
+	memcpy(&pkt->ipv6.ip, &ip6, sizeof(ip6));
+	memcpy(&pkt->ipv6.udp, &udp, sizeof(udp));
+}
+
+static void
+update_size(struct pkt *pkt, struct targ *t, int size)
+{
+	if (t->g->options & OPT_UPDATE_CSUM) {
+		if (t->g->af == AF_INET)
+			update_ip_size(pkt, size);
+		else
+			update_ip6_size(pkt, size);
+	}
+}
+
 /*
  * initialize one packet and prepare for the next one.
  * The copy could be done better instead of repeating it each time.
@@ -1744,6 +1824,7 @@ sender_body(void *data)
 				size = nrand48(targ->seed) %
 					(targ->g->pkt_size - targ->g->pkt_min_size) +
 					targ->g->pkt_min_size;
+				update_size(pkt, targ, size);
 			}
 			m = send_packets(txring, pkt, frame, size, targ,
 					 limit, options);
@@ -2528,6 +2609,7 @@ usage(int errcode)
 "				OPT_RANDOM_SRC  512\n"
 "				OPT_RANDOM_DST  1024\n"
 "				OPT_PPS_STATS   2048\n"
+"				OPT_UPDATE_CSUM 4096\n"
 		     "",
 		cmd);
 	exit(errcode);
@@ -3284,8 +3366,8 @@ out:
 		g.tx_period.tv_nsec = g.tx_period.tv_nsec % 1000000000;
 	}
 	if (g.td_type == TD_TYPE_SENDER)
-	    D("Sending %d packets every  %ld.%09ld s",
-			g.burst, g.tx_period.tv_sec, g.tx_period.tv_nsec);
+	    D("Sending %d packets every  %jd.%09ld s",
+			g.burst, (intmax_t)g.tx_period.tv_sec, g.tx_period.tv_nsec);
 	/* Install ^C handler. */
 	global_nthreads = g.nthreads;
 	sigemptyset(&ss);