]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
selftests/xsk: account reclaimed invalid Tx descriptors
authorMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Sun, 19 Jul 2026 13:56:09 +0000 (15:56 +0200)
committerJakub Kicinski <kuba@kernel.org>
Fri, 24 Jul 2026 22:12:15 +0000 (15:12 -0700)
Invalid Tx descriptors are now returned through the completion ring,
regardless of whether they form a standalone packet or belong to an
invalid multi-buffer packet.

The selftests previously counted only descriptors belonging to valid
packets, with a special exception for some invalid multi-buffer packets
in verbatim streams. This undercounts completion entries when a
standalone invalid descriptor or another invalid packet is reclaimed by
the kernel.

Keep valid_pkts as the number of packets expected on the Rx side, but
count every descriptor submitted to the Tx ring in valid_frags, as every
such descriptor is now expected to be returned through the completion
ring.

Make fragment counting in verbatim mode follow the packet boundary
instead of stopping at the first invalid fragment. Update custom stream
generation so an invalid middle fragment terminates the generated Rx
packet while Tx completion accounting still covers the complete invalid
packet.

Also add explicit end fragments after invalid middle descriptors. This
exercises the kernel drain logic and verifies that subsequent valid
packets are not interpreted as continuations of the invalid packet.

Reviewed-by: Jason Xing <kernelxing@tencent.com>
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20260719135609.147823-7-maciej.fijalkowski@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
tools/testing/selftests/bpf/prog_tests/test_xsk.c

index de17dd48f176489bf9c30242d07f4681cd010089..38ce6060b8facc20ba8c31ae99528f46abbbaa9e 100644 (file)
@@ -427,14 +427,14 @@ static u32 pkt_nb_frags(u32 frame_size, struct pkt_stream *pkt_stream, struct pk
        }
 
        /* Search for the end of the packet in verbatim mode */
-       if (!pkt_continues(pkt->options) || !pkt->valid)
+       if (!pkt_continues(pkt->options))
                return nb_frags;
 
        next_frag = pkt_stream->current_pkt_nb;
        pkt++;
        while (next_frag++ < pkt_stream->nb_pkts) {
                nb_frags++;
-               if (!pkt_continues(pkt->options) || !pkt->valid)
+               if (!pkt_continues(pkt->options))
                        break;
                pkt++;
        }
@@ -665,11 +665,11 @@ static struct pkt_stream *__pkt_stream_generate_custom(struct ifobject *ifobj, s
                        if (!frame->valid || !pkt_continues(frame->options))
                                payload++;
                } else {
-                       if (frame->valid)
+                       if (frame->valid) {
                                len += frame->len;
-                       if (frame->valid && pkt_continues(frame->options))
-                               continue;
-
+                               if (pkt_continues(frame->options))
+                                       continue;
+                       }
                        pkt->pkt_nb = pkt_nb;
                        pkt->len = len;
                        pkt->valid = frame->valid;
@@ -1250,10 +1250,9 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk,
                        }
                }
 
-               if (pkt && pkt->valid) {
+               if (pkt && pkt->valid)
                        valid_pkts++;
-                       valid_frags += nb_frags;
-               }
+               valid_frags += nb_frags;
        }
 
        pthread_mutex_lock(&pacing_mutex);
@@ -2099,13 +2098,16 @@ int testapp_invalid_desc_mb(struct test_spec *test)
                {0, 0, 0, false, 0},
                /* Invalid address in the second frame */
                {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
-               {umem_sz, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
+               {umem_sz * 2, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
+               {0, MIN_PKT_SIZE, 0, false, 0},
                /* Invalid len in the middle */
                {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
                {0, XSK_UMEM__INVALID_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
+               {0, MIN_PKT_SIZE, 0, false, 0},
                /* Invalid options in the middle */
                {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
                {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XSK_DESC__INVALID_OPTION},
+               {0, MIN_PKT_SIZE, 0, false, 0},
                /* Transmit 2 frags, receive 3 */
                {0, XSK_UMEM__MAX_FRAME_SIZE, 0, true, XDP_PKT_CONTD},
                {0, XSK_UMEM__MAX_FRAME_SIZE, 0, true, 0},
@@ -2117,8 +2119,8 @@ int testapp_invalid_desc_mb(struct test_spec *test)
 
        if (umem->unaligned_mode) {
                /* Crossing a chunk boundary allowed */
-               pkts[12].valid = true;
-               pkts[13].valid = true;
+               pkts[15].valid = true;
+               pkts[16].valid = true;
        }
 
        test->mtu = MAX_ETH_JUMBO_SIZE;