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
This commit is contained in:
Vincenzo Maffione 2023-04-26 20:32:24 +00:00
parent 2d7842d0bf
commit 8c3b8c8386
2 changed files with 88 additions and 5 deletions

View File

@ -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 ,

View File

@ -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 @@ main(int arc, char **argv)
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);