Skip to content

Commit 9038482

Browse files
wdebruijkuba-moo
authored andcommitted
selftests/net: toeplitz: fix race on tpacket_v3 block close
Avoid race between process wakeup and tpacket_v3 block timeout. The test waits for cfg_timeout_msec for packets to arrive. Packets arrive in tpacket_v3 rings, which pass packets ("frames") to the process in batches ("blocks"). The sk waits for req3.tp_retire_blk_tov msec to release a block. Set the block timeout lower than the process waiting time, else the process may find that no block has been released by the time it scans the socket list. Convert to a ring of more than one, smaller, blocks with shorter timeouts. Blocks must be page aligned, so >= 64KB. Fixes: 5ebfb4c ("selftests/net: toeplitz test") Signed-off-by: Willem de Bruijn <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 8ccc993 commit 9038482

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

tools/testing/selftests/net/toeplitz.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,15 @@ static char *recv_frame(const struct ring_state *ring, char *frame)
215215
}
216216

217217
/* A single TPACKET_V3 block can hold multiple frames */
218-
static void recv_block(struct ring_state *ring)
218+
static bool recv_block(struct ring_state *ring)
219219
{
220220
struct tpacket_block_desc *block;
221221
char *frame;
222222
int i;
223223

224224
block = (void *)(ring->mmap + ring->idx * ring_block_sz);
225225
if (!(block->hdr.bh1.block_status & TP_STATUS_USER))
226-
return;
226+
return false;
227227

228228
frame = (char *)block;
229229
frame += block->hdr.bh1.offset_to_first_pkt;
@@ -235,6 +235,8 @@ static void recv_block(struct ring_state *ring)
235235

236236
block->hdr.bh1.block_status = TP_STATUS_KERNEL;
237237
ring->idx = (ring->idx + 1) % ring_block_nr;
238+
239+
return true;
238240
}
239241

240242
/* simple test: sleep once unconditionally and then process all rings */
@@ -245,7 +247,7 @@ static void process_rings(void)
245247
usleep(1000 * cfg_timeout_msec);
246248

247249
for (i = 0; i < num_cpus; i++)
248-
recv_block(&rings[i]);
250+
do {} while (recv_block(&rings[i]));
249251

250252
fprintf(stderr, "count: pass=%u nohash=%u fail=%u\n",
251253
frames_received - frames_nohash - frames_error,
@@ -257,12 +259,12 @@ static char *setup_ring(int fd)
257259
struct tpacket_req3 req3 = {0};
258260
void *ring;
259261

260-
req3.tp_retire_blk_tov = cfg_timeout_msec;
262+
req3.tp_retire_blk_tov = cfg_timeout_msec / 8;
261263
req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;
262264

263265
req3.tp_frame_size = 2048;
264266
req3.tp_frame_nr = 1 << 10;
265-
req3.tp_block_nr = 2;
267+
req3.tp_block_nr = 16;
266268

267269
req3.tp_block_size = req3.tp_frame_size * req3.tp_frame_nr;
268270
req3.tp_block_size /= req3.tp_block_nr;

0 commit comments

Comments
 (0)