git: 0a12444b2989 - main - pkt-gen: fix UDP checksum when IPv6 address ranges are used
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 01 Nov 2026 18:10:05 UTC
The branch main has been updated by vmaffione:
URL: https://cgit.FreeBSD.org/src/commit/?id=0a12444b2989c38a5d2e358e0f9ef01c665cc268
commit 0a12444b2989c38a5d2e358e0f9ef01c665cc268
Author: Vincenzo Maffione <vmaffione@FreeBSD.org>
AuthorDate: 2026-11-01 18:06:13 +0000
Commit: Vincenzo Maffione <vmaffione@FreeBSD.org>
CommitDate: 2026-11-01 18:06:13 +0000
pkt-gen: fix UDP checksum when IPv6 address ranges are used
update_ip6() left the UDP checksum stale for most packets. Unlike
update_ip(), it computed the incremental checksum delta only after the
source-address wrap, so every earlier "break" (port increment, address
increment, and both random paths) returned with udp_sum still 0 and no
correction applied. The trailing delta block also re-read oaddr/naddr
after they had been reassigned, so the source and destination deltas
could not both be accounted for.
Fold each delta in with new_udp_sum() before the corresponding break,
mirroring the structure update_ip() already uses, and drop the stale
trailing block. IPv4 was not affected.
Verified by driving update_addresses() directly and recomputing every
checksum from scratch over the real pseudo-header: 128 packets across
six range configurations, 12 mismatches before, 0 after. IPv4 passes
both before and after.
Submitted by: Olivier Cochard-Labbé <olivier@cochard.me>
---
tools/tools/netmap/pkt-gen.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/tools/tools/netmap/pkt-gen.c b/tools/tools/netmap/pkt-gen.c
index c17579a142b9..510f6a3db462 100644
--- a/tools/tools/netmap/pkt-gen.c
+++ b/tools/tools/netmap/pkt-gen.c
@@ -917,7 +917,7 @@ update_ip6(struct pkt *pkt, struct targ *t)
struct glob_arg *g = t->g;
struct ip6_hdr ip6;
struct udphdr udp;
- uint16_t udp_sum;
+ uint16_t udp_sum = 0;
uint16_t oaddr, naddr;
uint16_t oport, nport;
uint8_t group;
@@ -925,7 +925,6 @@ update_ip6(struct pkt *pkt, struct targ *t)
memcpy(&ip6, &pkt->ipv6.ip, sizeof(ip6));
memcpy(&udp, &pkt->ipv6.udp, sizeof(udp));
do {
- udp_sum = 0;
group = g->src_ip.ipv6.sgroup;
naddr = oaddr = ntohs(ip6.ip6_src.s6_addr16[group]);
nport = oport = ntohs(udp.uh_sport);
@@ -934,29 +933,28 @@ update_ip6(struct pkt *pkt, struct targ *t)
udp.uh_sport = nrand48(t->seed);
naddr = ntohs(ip6.ip6_src.s6_addr16[group]);
nport = ntohs(udp.uh_sport);
+ udp_sum = new_udp_sum(udp_sum, oaddr, naddr);
+ udp_sum = new_udp_sum(udp_sum, oport, nport);
break;
}
if (oport < g->src_ip.port1) {
nport = oport + 1;
udp.uh_sport = htons(nport);
+ udp_sum = new_udp_sum(udp_sum, oport, nport);
break;
}
nport = g->src_ip.port0;
udp.uh_sport = htons(nport);
+ udp_sum = new_udp_sum(udp_sum, oport, nport);
if (oaddr < ntohs(g->src_ip.ipv6.end.s6_addr16[group])) {
naddr = oaddr + 1;
ip6.ip6_src.s6_addr16[group] = htons(naddr);
+ udp_sum = new_udp_sum(udp_sum, oaddr, naddr);
break;
}
naddr = ntohs(g->src_ip.ipv6.start.s6_addr16[group]);
ip6.ip6_src.s6_addr16[group] = htons(naddr);
-
- /* update checksums if needed */
- if (oaddr != naddr)
- udp_sum = cksum_add(~oaddr, naddr);
- if (oport != nport)
- udp_sum = cksum_add(udp_sum,
- cksum_add(~oport, nport));
+ udp_sum = new_udp_sum(udp_sum, oaddr, naddr);
group = g->dst_ip.ipv6.egroup;
naddr = oaddr = ntohs(ip6.ip6_dst.s6_addr16[group]);
@@ -966,32 +964,32 @@ update_ip6(struct pkt *pkt, struct targ *t)
udp.uh_dport = nrand48(t->seed);
naddr = ntohs(ip6.ip6_dst.s6_addr16[group]);
nport = ntohs(udp.uh_dport);
+ udp_sum = new_udp_sum(udp_sum, oaddr, naddr);
+ udp_sum = new_udp_sum(udp_sum, oport, nport);
break;
}
if (oport < g->dst_ip.port1) {
nport = oport + 1;
udp.uh_dport = htons(nport);
+ udp_sum = new_udp_sum(udp_sum, oport, nport);
break;
}
nport = g->dst_ip.port0;
udp.uh_dport = htons(nport);
+ udp_sum = new_udp_sum(udp_sum, oport, nport);
if (oaddr < ntohs(g->dst_ip.ipv6.end.s6_addr16[group])) {
naddr = oaddr + 1;
ip6.ip6_dst.s6_addr16[group] = htons(naddr);
+ udp_sum = new_udp_sum(udp_sum, oaddr, naddr);
break;
}
naddr = ntohs(g->dst_ip.ipv6.start.s6_addr16[group]);
ip6.ip6_dst.s6_addr16[group] = htons(naddr);
+ udp_sum = new_udp_sum(udp_sum, oaddr, naddr);
} while (0);
/* update checksums */
- if (oaddr != naddr)
- udp_sum = cksum_add(udp_sum,
- cksum_add(~oaddr, naddr));
- if (oport != nport)
- udp_sum = cksum_add(udp_sum,
- cksum_add(~oport, nport));
if (udp_sum != 0)
- udp.uh_sum = ~cksum_add(~udp.uh_sum, udp_sum);
+ udp.uh_sum = ~cksum_add(~udp.uh_sum, htons(udp_sum));
memcpy(&pkt->ipv6.ip, &ip6, sizeof(ip6));
memcpy(&pkt->ipv6.udp, &udp, sizeof(udp));
}