Skip to content

Commit 89baa22

Browse files
spikehaxboe
authored andcommitted
io_uring/zcrx: add selftest case for recvzc with read limit
Add a selftest case to iou-zcrx where the sender sends 4x4K = 16K and the receiver does 4x4K recvzc requests. Validate that the requests complete successfully and that the data is not corrupted. Signed-off-by: David Wei <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 6699ec9 commit 89baa22

File tree

2 files changed

+62
-8
lines changed

2 files changed

+62
-8
lines changed

tools/testing/selftests/drivers/net/hw/iou-zcrx.c

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ static int cfg_port = 8000;
6161
static int cfg_payload_len;
6262
static const char *cfg_ifname;
6363
static int cfg_queue_id = -1;
64+
static bool cfg_oneshot;
65+
static int cfg_oneshot_recvs;
66+
static int cfg_send_size = SEND_SIZE;
6467
static struct sockaddr_in6 cfg_addr;
6568

6669
static char payload[SEND_SIZE] __attribute__((aligned(PAGE_SIZE)));
@@ -196,6 +199,17 @@ static void add_recvzc(struct io_uring *ring, int sockfd)
196199
sqe->user_data = 2;
197200
}
198201

202+
static void add_recvzc_oneshot(struct io_uring *ring, int sockfd, size_t len)
203+
{
204+
struct io_uring_sqe *sqe;
205+
206+
sqe = io_uring_get_sqe(ring);
207+
208+
io_uring_prep_rw(IORING_OP_RECV_ZC, sqe, sockfd, NULL, len, 0);
209+
sqe->ioprio |= IORING_RECV_MULTISHOT;
210+
sqe->user_data = 2;
211+
}
212+
199213
static void process_accept(struct io_uring *ring, struct io_uring_cqe *cqe)
200214
{
201215
if (cqe->res < 0)
@@ -204,7 +218,10 @@ static void process_accept(struct io_uring *ring, struct io_uring_cqe *cqe)
204218
error(1, 0, "Unexpected second connection");
205219

206220
connfd = cqe->res;
207-
add_recvzc(ring, connfd);
221+
if (cfg_oneshot)
222+
add_recvzc_oneshot(ring, connfd, PAGE_SIZE);
223+
else
224+
add_recvzc(ring, connfd);
208225
}
209226

210227
static void process_recvzc(struct io_uring *ring, struct io_uring_cqe *cqe)
@@ -218,16 +235,22 @@ static void process_recvzc(struct io_uring *ring, struct io_uring_cqe *cqe)
218235
ssize_t n;
219236
int i;
220237

221-
if (cqe->res == 0 && cqe->flags == 0) {
238+
if (cqe->res == 0 && cqe->flags == 0 && cfg_oneshot_recvs == 0) {
222239
stop = true;
223240
return;
224241
}
225242

226243
if (cqe->res < 0)
227244
error(1, 0, "recvzc(): %d", cqe->res);
228245

229-
if (!(cqe->flags & IORING_CQE_F_MORE))
246+
if (cfg_oneshot) {
247+
if (cqe->res == 0 && cqe->flags == 0 && cfg_oneshot_recvs) {
248+
add_recvzc_oneshot(ring, connfd, PAGE_SIZE);
249+
cfg_oneshot_recvs--;
250+
}
251+
} else if (!(cqe->flags & IORING_CQE_F_MORE)) {
230252
add_recvzc(ring, connfd);
253+
}
231254

232255
rcqe = (struct io_uring_zcrx_cqe *)(cqe + 1);
233256

@@ -237,7 +260,7 @@ static void process_recvzc(struct io_uring *ring, struct io_uring_cqe *cqe)
237260

238261
for (i = 0; i < n; i++) {
239262
if (*(data + i) != payload[(received + i)])
240-
error(1, 0, "payload mismatch");
263+
error(1, 0, "payload mismatch at ", i);
241264
}
242265
received += n;
243266

@@ -313,7 +336,7 @@ static void run_server(void)
313336

314337
static void run_client(void)
315338
{
316-
ssize_t to_send = SEND_SIZE;
339+
ssize_t to_send = cfg_send_size;
317340
ssize_t sent = 0;
318341
ssize_t chunk, res;
319342
int fd;
@@ -360,7 +383,7 @@ static void parse_opts(int argc, char **argv)
360383
usage(argv[0]);
361384
cfg_payload_len = max_payload_len;
362385

363-
while ((c = getopt(argc, argv, "46sch:p:l:i:q:")) != -1) {
386+
while ((c = getopt(argc, argv, "sch:p:l:i:q:o:z:")) != -1) {
364387
switch (c) {
365388
case 's':
366389
if (cfg_client)
@@ -387,6 +410,14 @@ static void parse_opts(int argc, char **argv)
387410
case 'q':
388411
cfg_queue_id = strtoul(optarg, NULL, 0);
389412
break;
413+
case 'o': {
414+
cfg_oneshot = true;
415+
cfg_oneshot_recvs = strtoul(optarg, NULL, 0);
416+
break;
417+
}
418+
case 'z':
419+
cfg_send_size = strtoul(optarg, NULL, 0);
420+
break;
390421
}
391422
}
392423

tools/testing/selftests/drivers/net/hw/iou-zcrx.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,37 @@ def test_zcrx(cfg) -> None:
3434
raise KsftSkipEx('at least 2 combined channels required')
3535
rx_ring = _get_rx_ring_entries(cfg)
3636

37-
rx_cmd = f"{cfg.bin_remote} -s -p 9999 -i {cfg.ifname} -q {combined_chans - 1}"
38-
tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_v6} -p 9999 -l 12840"
37+
try:
38+
ethtool(f"-G {cfg.ifname} rx 64", host=cfg.remote)
39+
ethtool(f"-X {cfg.ifname} equal {combined_chans - 1}", host=cfg.remote)
40+
flow_rule_id = _set_flow_rule(cfg, combined_chans - 1)
41+
42+
rx_cmd = f"{cfg.bin_remote} -s -p 9999 -i {cfg.ifname} -q {combined_chans - 1}"
43+
tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_v6} -p 9999 -l 12840"
44+
with bkg(rx_cmd, host=cfg.remote, exit_wait=True):
45+
wait_port_listen(9999, proto="tcp", host=cfg.remote)
46+
cmd(tx_cmd)
47+
finally:
48+
ethtool(f"-N {cfg.ifname} delete {flow_rule_id}", host=cfg.remote)
49+
ethtool(f"-X {cfg.ifname} default", host=cfg.remote)
50+
ethtool(f"-G {cfg.ifname} rx {rx_ring}", host=cfg.remote)
51+
52+
53+
def test_zcrx_oneshot(cfg) -> None:
54+
cfg.require_v6()
55+
56+
combined_chans = _get_combined_channels(cfg)
57+
if combined_chans < 2:
58+
raise KsftSkipEx('at least 2 combined channels required')
59+
rx_ring = _get_rx_ring_entries(cfg)
3960

4061
try:
4162
ethtool(f"-G {cfg.ifname} rx 64", host=cfg.remote)
4263
ethtool(f"-X {cfg.ifname} equal {combined_chans - 1}", host=cfg.remote)
4364
flow_rule_id = _set_flow_rule(cfg, combined_chans - 1)
4465

66+
rx_cmd = f"{cfg.bin_remote} -s -p 9999 -i {cfg.ifname} -q {combined_chans - 1} -o 4"
67+
tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_v6} -p 9999 -l 4096 -z 16384"
4568
with bkg(rx_cmd, host=cfg.remote, exit_wait=True):
4669
wait_port_listen(9999, proto="tcp", host=cfg.remote)
4770
cmd(tx_cmd)

0 commit comments

Comments
 (0)