Skip to content

Commit 063ec71

Browse files
committed
xdp-trafficgen: Support specifying the packet size for UDP packets
Instead of hard-coding the packet size to 64 bytes, support specifying a custom packet size on the command line. Signed-off-by: Toke Høiland-Jørgensen <[email protected]>
1 parent e4df54b commit 063ec71

File tree

3 files changed

+59
-16
lines changed

3 files changed

+59
-16
lines changed

xdp-trafficgen/README.org

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ Enable dynamic port mode where the destination port is varied over a range of
8181
Number of packets to send before exiting. If not supplied, =xdp-trafficgen= will
8282
keep sending packets until interrupted.
8383

84+
** -s, --pkt-size <bytes>
85+
Size of each UDP packet being sent, including the Ethernet header. The minimum
86+
size, which is also the default, is 64 bytes.
87+
8488
** -t, --threads <threads>
8589
Number of simultaneous threads to transmit from. Each thread will be pinned to a
8690
separate CPU core if possible. Defaults to 1.

xdp-trafficgen/xdp-trafficgen.8

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ Enable dynamic port mode where the destination port is varied over a range of
9494
Number of packets to send before exiting. If not supplied, \fIxdp\-trafficgen\fP will
9595
keep sending packets until interrupted.
9696

97+
.SS "-s, --pkt-size <bytes>"
98+
.PP
99+
Size of each UDP packet being sent, including the Ethernet header. The minimum
100+
size, which is also the default, is 64 bytes.
101+
97102
.SS "-t, --threads <threads>"
98103
.PP
99104
Number of simultaneous threads to transmit from. Each thread will be pinned to a

xdp-trafficgen/xdp-trafficgen.c

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -276,47 +276,73 @@ static const struct udpopt {
276276
__u16 dyn_ports;
277277
__u16 threads;
278278
__u16 interval;
279+
__u16 pkt_size;
279280
} defaults_udp = {
280281
.interval = 1,
281282
.threads = 1,
283+
.pkt_size = 64,
282284
};
283285

284-
static int prepare_udp_pkt(const struct udpopt *cfg)
286+
static struct udp_packet *prepare_udp_pkt(const struct udpopt *cfg)
285287
{
286288
struct mac_addr src_mac = cfg->src_mac;
289+
struct udp_packet *pkt = NULL;
290+
__u16 payload_len;
287291
int err;
288292

289293
if (macaddr_is_null(&src_mac)) {
290294
err = get_mac_addr(cfg->iface.ifindex, &src_mac);
291295
if (err)
292-
return err;
296+
goto err;
297+
}
298+
299+
if (cfg->pkt_size < sizeof(*pkt)) {
300+
pr_warn("Mininum packet size is %zu bytes\n", sizeof(*pkt));
301+
goto err;
293302
}
294-
memcpy(pkt_udp.eth.h_source, &src_mac, sizeof(src_mac));
303+
304+
305+
pkt = calloc(1, cfg->pkt_size);
306+
if (!pkt)
307+
goto err;
308+
309+
memcpy(pkt, &pkt_udp, sizeof(*pkt));
310+
311+
payload_len = cfg->pkt_size - offsetof(struct udp_packet, udp);
312+
pkt->iph.payload_len = bpf_htons(payload_len);
313+
pkt->udp.len = bpf_htons(payload_len);
314+
315+
memcpy(pkt->eth.h_source, &src_mac, sizeof(src_mac));
295316
if (!macaddr_is_null(&cfg->dst_mac))
296-
memcpy(pkt_udp.eth.h_dest, &cfg->dst_mac, sizeof(cfg->dst_mac));
317+
memcpy(pkt->eth.h_dest, &cfg->dst_mac, sizeof(cfg->dst_mac));
297318

298319
if (!ipaddr_is_null(&cfg->src_ip)) {
299320
if (cfg->src_ip.af != AF_INET6) {
300321
pr_warn("Only IPv6 is supported\n");
301-
return 1;
322+
goto err;
302323
}
303-
pkt_udp.iph.saddr = cfg->src_ip.addr.addr6;
324+
pkt->iph.saddr = cfg->src_ip.addr.addr6;
304325
}
305326

306327
if (!ipaddr_is_null(&cfg->dst_ip)) {
307328
if (cfg->dst_ip.af != AF_INET6) {
308329
pr_warn("Only IPv6 is supported\n");
309-
return 1;
330+
goto err;
310331
}
311-
pkt_udp.iph.daddr = cfg->dst_ip.addr.addr6;
332+
pkt->iph.daddr = cfg->dst_ip.addr.addr6;
312333
}
313334

314335
if (cfg->src_port)
315-
pkt_udp.udp.source = bpf_htons(cfg->src_port);
336+
pkt->udp.source = bpf_htons(cfg->src_port);
316337
if (cfg->dst_port)
317-
pkt_udp.udp.dest = bpf_htons(cfg->dst_port);
318-
pkt_udp.udp.check = calc_udp_cksum(&pkt_udp);
319-
return 0;
338+
pkt->udp.dest = bpf_htons(cfg->dst_port);
339+
pkt->udp.check = calc_udp_cksum(pkt);
340+
341+
return pkt;
342+
343+
err:
344+
free(pkt);
345+
return NULL;
320346
}
321347

322348
static struct prog_option udp_options[] = {
@@ -352,6 +378,10 @@ static struct prog_option udp_options[] = {
352378
.short_opt = 'n',
353379
.metavar = "<port>",
354380
.help = "Number of packets to send"),
381+
DEFINE_OPTION("pkt-size", OPT_U16, struct udpopt, pkt_size,
382+
.short_opt = 's',
383+
.metavar = "<bytes>",
384+
.help = "Packet size. Default 64."),
355385
DEFINE_OPTION("threads", OPT_U16, struct udpopt, threads,
356386
.short_opt = 't',
357387
.metavar = "<threads>",
@@ -374,12 +404,12 @@ int do_udp(const void *opt, __unused const char *pin_root_path)
374404

375405
DECLARE_LIBXDP_OPTS(xdp_program_opts, opts);
376406
struct thread_config *t = NULL, tcfg = {
377-
.pkt = &pkt_udp,
378-
.pkt_size = sizeof(pkt_udp),
407+
.pkt_size = cfg->pkt_size,
379408
.num_pkts = cfg->num_pkts,
380409
};
381410
struct trafficgen_state bpf_state = {};
382411
struct xdp_trafficgen *skel = NULL;
412+
struct udp_packet *payload = NULL;
383413
pthread_t *runner_threads = NULL;
384414
struct xdp_program *prog = NULL;
385415
int err = 0, i;
@@ -390,9 +420,12 @@ int do_udp(const void *opt, __unused const char *pin_root_path)
390420
if (err)
391421
return err;
392422

393-
err = prepare_udp_pkt(cfg);
394-
if (err)
423+
payload = prepare_udp_pkt(cfg);
424+
if (!payload) {
425+
err = -ENOMEM;
395426
goto out;
427+
}
428+
tcfg.pkt = payload;
396429

397430
skel = xdp_trafficgen__open();
398431
if (!skel) {
@@ -463,6 +496,7 @@ int do_udp(const void *opt, __unused const char *pin_root_path)
463496
xdp_program__close(prog);
464497
xdp_trafficgen__destroy(skel);
465498
free(runner_threads);
499+
free(payload);
466500
free(t);
467501
return err;
468502
}

0 commit comments

Comments
 (0)