From nobody Wed Oct 8 18:13:06 2025 Received: from mail-ed1-f54.google.com (mail-ed1-f54.google.com [209.85.208.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D22A0282E1; Wed, 25 Jun 2025 11:39:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750851601; cv=none; b=pxsrnPVhNX0SNtJ3NJNAA8CsxV/tw4mp5vwl/5VU+Yck2NfsQ9qUJTdtbFOeHlFx8TpK1MFOahATVVn0Sg03DewDTrOBeHAPkuD1Pvf6P4hL7s9YIsNBq13TUHymwGn7+e6Cy6f9ji9I1jvxebt+6WOtlVdK7aJt9LbaioNPOwM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750851601; c=relaxed/simple; bh=W1EexkswfPcZNr3iUS31AuS5Kgo2ZSIFjOO3bhsqMzY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=l7lKYP/aZTAnaTbXLJLoS2ws6Pkg6SGkeiR4DBPxdFn4fIDX9ie90hDAGhR86JPyGRVbE6JUffxfpPkYzYu7vIKIjwlexUrbwktgMVyLnUqNJuzn3/9xD9wElsRuW2c5VfAnIhCgze0G+TJEgu2RdQfxHnlxQ62gbTUIYO0nxzA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.208.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ed1-f54.google.com with SMTP id 4fb4d7f45d1cf-6077d0b9bbeso10896571a12.3; Wed, 25 Jun 2025 04:39:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750851598; x=1751456398; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ePm0T0zc663ZbGV340DcndG+7KFVs4xq2cA81VLyDoA=; b=W1M0Ll05G65NQRnPtpyVYG7bvne+Nb8qcaBY5xwRzJuXBn9JYspEdTADYdz9otNB98 /tK6sqWt6cjQjtamRuITs5XEKwnC3V2DuzDkRtW5fRFJ/Wyk6FrGwTqWLXx7OULB34c8 IBg3C+k9V0SHpnGrEXZCn8rqxC/Zez0LtO1GUs3vYraf1ar5ocTrja25Z8nNnMTONgZA cQekGoCufmLaH9HV7DyB9oGJ7sv4ZVwL8xWFAHtf7k6URRBgXgMGWmptgpIm4Ig2aEhm lFbZ6Rm0jBf+7c2Hn5m/aYh/sS7o0umLIlcq9i4JJC+w+UjGkLMO2/pC70G8/t9JOC8/ T1tQ== X-Forwarded-Encrypted: i=1; AJvYcCUNhhw0xcQY4tiiXJplnJu5e5FIMHpz2R7ZgoBO1Aym9ZFRRF75yrMtMgjCMY6jOusCrTRmIJ5qMuC5O5txy9Ie@vger.kernel.org, AJvYcCWG8a75F76W34W1f2kTlcQaiMHJJbwMI5hDZCeX6i5fpjhIi8ORP3m+JNNwMg/oLYtR7NP5+liU@vger.kernel.org, AJvYcCX44QYxPT0NzFtvz45lP2fVEEuZWcyues70sQnON0uFiFwt40VxMN+hjJXDhJ5o7uqjwNc=@vger.kernel.org X-Gm-Message-State: AOJu0Yx9TkMub5JtliSjoC3ByB37UqhMhiaaGKFwh8b35Byn7osER/zZ kPGsX8s+p0O5mzT/HKi591bW9TzaJ/4PuyMgVxWWkKYJOm5hrIRoWFVI3wYXoGIc X-Gm-Gg: ASbGncuhfCfpCkbhzOS440KSByiQSfDqI16ciaHybKR3qiun5fHRenfbQp3Yr3dgtTi xAbJRz0CpJqrLE4S166OrQjhWyt8548Q8vuZ9HOHnCWs1u4yUrGzRRX22mdgH03lFnIbJPaMxYP 4LBBAgNf2cyFs2spY6gLgBN5yzP9HqNxm5S6lY5moncIuDdCsXId5t1dkrhNIJdj2kjadPDCsU3 oZoGotwcQO2KAWHc5CkJeM9HL2wEMWJynKha4M4//DAWYUz0KUxrNe2AbaDhTU2ZBz5z3YEibzA QX/KsfcE8ywaxWqlF3BejXy+v1+L9Fu1z0+Csrx+9GPAhHEN9MKs X-Google-Smtp-Source: AGHT+IG2xM6ZRiOvuC+JX5cT+LVYS5zYJbG8CqIQXBQAYe1GC+M1/IFtpm8JgzlLbYyeTrhFQyM/KA== X-Received: by 2002:a05:6402:26d1:b0:60b:fb2c:b7b3 with SMTP id 4fb4d7f45d1cf-60c4d21597cmr1904705a12.0.1750851597930; Wed, 25 Jun 2025 04:39:57 -0700 (PDT) Received: from localhost ([2a03:2880:30ff:1::]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-60c2f4683cesm2413673a12.37.2025.06.25.04.39.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Jun 2025 04:39:57 -0700 (PDT) From: Breno Leitao Date: Wed, 25 Jun 2025 04:39:46 -0700 Subject: [PATCH net-next v2 1/4] selftests: drv-net: add helper/wrapper for bpftrace Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250625-netpoll_test-v2-1-47d27775222c@debian.org> References: <20250625-netpoll_test-v2-0-47d27775222c@debian.org> In-Reply-To: <20250625-netpoll_test-v2-0-47d27775222c@debian.org> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Willem de Bruijn , bpf@vger.kernel.org, gustavold@gmail.com, Breno Leitao X-Mailer: b4 0.15-dev-dd21f X-Developer-Signature: v=1; a=openpgp-sha256; l=2232; i=leitao@debian.org; h=from:subject:message-id; bh=I+lAo+Qac5MqwIlBjg9aGwL745T5u3BmIKWuOzlXpBI=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBoW+AKljp+1xHgL9H3RniDgez8LxrtISQB1ECzf Zd3UTWObvaJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaFvgCgAKCRA1o5Of/Hh3 belmD/4o2CfKPSLtgU1BvN0QtjpwO+kigo2dbR5hS60Bz5AI1LTwuIQs4lIBL2s5EZJpAiln6vL 2J5kZFFs2UxgdZ8UtUYdN5ftR1e0AFDc87QthmyHMgE0JiGWH+fUJqIxoVFuyK1qswfeXI4mtq1 AXg9H4jS3FsTOZJ3NG+QKFiBXgDVm8AhlCVn5iUjBDvK7bypaTUONOAgDh1ECnN555EInVZWirC 9HN5PTjG2GQMteA+0RgeMSyhWKo/AwA7Pymc9TfFOOKfKaChs/hhlETm/ORJRzA3GKNss0Hi3Ax xyxUVyvPtJvGy6jA38rd2/VK3RGZ2oKAzqOs/cIcOlp26xlVmxomKfAh6daBI5NZ14hwuYD4Gm1 h8SWVWWZ18BVPLv260BKi2BrquTT0X2CKH53GDjhwNlgn6+cpKN25zHCFATdGEu+VkOLbcsL/Oo krZdgzfrRhheXh2OFxS4OegXlCL0SEHXNOlhOYfuMF8+f/5r/EnbMs75pH4c0ilZOkqpdIpoR8X 4JScaEgvSkzeLhiEdt4PXfD5HJ0vquQ8r+XPTiNiWokyI9xBKgAqY5F5Q+5HQgyIhvq+FXbv2N2 g+xAN4xLjjDfrR9X2C4lFTmzEawkl4/LQN8DJIepSMKQWO0zz8353hczMo62GkxeExgVXqHz5IZ eqdPl4mYoM+Pu0Q== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D From: Jakub Kicinski bpftrace is very useful for low level driver testing. perf or trace-cmd would also do for collecting data from tracepoints, but they require much more post-processing. Add a wrapper for running bpftrace and sanitizing its output. bpftrace has JSON output, which is great, but it prints loose objects and in a slightly inconvenient format. We have to read the objects line by line, and while at it return them indexed by the map name. Signed-off-by: Jakub Kicinski Signed-off-by: Breno Leitao --- tools/testing/selftests/net/lib/py/utils.py | 33 +++++++++++++++++++++++++= ++++ 1 file changed, 33 insertions(+) diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/se= lftests/net/lib/py/utils.py index 34470d65d871a..760ccf6fccccc 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -185,6 +185,39 @@ def ethtool(args, json=3DNone, ns=3DNone, host=3DNone): return tool('ethtool', args, json=3Djson, ns=3Dns, host=3Dhost) =20 =20 +def bpftrace(expr, json=3DNone, ns=3DNone, host=3DNone, timeout=3DNone): + """ + Run bpftrace and return map data (if json=3DTrue). + The output of bpftrace is inconvenient, so the helper converts + to a dict indexed by map name, e.g.: + { + "@": { ... }, + "@map2": { ... }, + } + """ + cmd_arr =3D ['bpftrace'] + # Throw in --quiet if json, otherwise the output has two objects + if json: + cmd_arr +=3D ['-f', 'json', '-q'] + if timeout: + expr +=3D ' interval:s:' + str(timeout) + ' { exit(); }' + cmd_arr +=3D ['-e', expr] + cmd_obj =3D cmd(cmd_arr, ns=3Dns, host=3Dhost, shell=3DFalse) + if json: + # bpftrace prints objects as lines + ret =3D {} + for l in cmd_obj.stdout.split('\n'): + if not l.strip(): + continue + one =3D _json.loads(l) + if one.get('type') !=3D 'map': + continue + for k, v in one["data"].items(): + ret[k] =3D v + return ret + return cmd_obj + + def rand_port(type=3Dsocket.SOCK_STREAM): """ Get a random unprivileged port. --=20 2.47.1 From nobody Wed Oct 8 18:13:06 2025 Received: from mail-ed1-f46.google.com (mail-ed1-f46.google.com [209.85.208.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48EF125D8F7; Wed, 25 Jun 2025 11:40:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750851603; cv=none; b=hSdhf9LXi6J31Dp0HY1WkiIDL2YvNB9t/Ijt3lzeQYJxWivdOYCIzjYZVvrl0I9z20qFsEeP/3MACazXiP/4o3iVLq1MH1zKD+bhrCKs8/Ow6dy6VHTcF4RoMLU/A7reccPct4Y2vUyjJrSKm/7V9T4Ohg+pyCOQCi7kzj4u+tI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750851603; c=relaxed/simple; bh=l/nda0XltKPv0ZkUvAchmFcqXkIO0WFjK5teLGJzfFE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SuZM54jVmySn1X/TwRwZu79F+7KjCAYXRWa4IApo4qBohA6cB+Q0Qq4e1eDVSKguy4oRCjy1V06+Aw7iM+ViyfmAB5M+jKNMC3UtGu0g8yE7diEtVMiCkyaF6ScU0WbtR12WkYSVUsuJv/itV1jiT40mvHmJ/u6xMa7ao5hV2m8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.208.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ed1-f46.google.com with SMTP id 4fb4d7f45d1cf-60c5b7cae8bso539894a12.1; Wed, 25 Jun 2025 04:40:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750851599; x=1751456399; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qT3VxGjg5ZOgOxiB0n/oc2JG8GkxQUHlqVHQBSwcuUw=; b=MlYuyJA2tHEcLm2xVBr0/LfXCw3/6FoyDzChDL38N3HoG8oyhVV5rQr9wsgiJrCV0O CdaS/V+i4kMm6he8w5/1DuUaARbDN4C6drwO8UAMPB93hwOrmZcPaOUuMhvRruBxkPip ULLnm7KFKt6OSM1SLHW+TCDl4ciseiB+Ci7xewREldl1o0r7j6ocmtAu4d2cO1hQDtrG 01yIq6zq5jIg+X1X6Jup8YUHHUmBwMCqV87b58i3bi+/vr6ulJPvJkK0Dfxbg83NzE/e NLQUzr+y7s5Haddq9/ahzr0dtHJylLL7rWpg/H+4WWi5Vxy5M36WCQi52kWXGTLFoen7 w0jg== X-Forwarded-Encrypted: i=1; AJvYcCUGeZVrOChJo+Zxpnt6+i4ImLXoZ1xZSl5rQLtYE8sqOx3NdvP41TVZCh+l9flyuQQS7jg=@vger.kernel.org, AJvYcCUe76iAQqRkp9XRQ1vdnl4xg+8AaN1n7GEVunigPFxVLNYWYF7Sg2y91ABMTO5bzvYisLsZXm6e@vger.kernel.org, AJvYcCWZRk67/KWt5a9Nxot40eD+8S5Fqux3cbHNo33g24AfpdeOCGV8fOllQJfyBv30/yEnE6Y+pp69GbmGqE5BfY50@vger.kernel.org X-Gm-Message-State: AOJu0YwN/jD0zjEFQtjFZtMzvq6sjHzWkeIA8No3Usk6ADstqG/QCP2D wM4MVU7gEFCw72spyR/nUhZP36BGZPgsoAX9k+sjKhrJ0w8I4ZrKuurH X-Gm-Gg: ASbGnctaMX8M1bhymwhF7g68a7zjQekaUQrLAmgirgrXlBx5kfwGCbQc2iIrCbdRp0/ Srn2Iuw9mslhJv7YLwQxRmObVPU6wTkO2QWMZ4+KOpklVX1ge3CU8bSBrJDs8rC7Rn1PEdf7wPr pxLyhhRVvwmDDEgcN/MxJ6ZOyQ6vLgkj9dBJvj25Vsikjh+LOjG+TT6J7Wav20bzU8VB3yy7WuZ PxdQGPeE8Kb8Sv+v8S2+v16lDMep07cQGq/FobXuoy1gWEiZAPX/wrJdtG2oU/FReskdfAj5MUA ySKktRP7B8LTmIwvLKpBT1FYQPJh1QiL+oanLcuiAjH0Ap9fE57i0g== X-Google-Smtp-Source: AGHT+IGwyL4vIDC3UIoBolr9zLc3zbc81T3CSXzzZXAeGlrkeaZuN/J4iuyZ/NpTJWt3hDAIK81XqQ== X-Received: by 2002:a17:907:7e9d:b0:ad2:425c:27ce with SMTP id a640c23a62f3a-ae0be90f2eemr281661166b.2.1750851599255; Wed, 25 Jun 2025 04:39:59 -0700 (PDT) Received: from localhost ([2a03:2880:30ff:72::]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ae0541b74cesm1051024466b.142.2025.06.25.04.39.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Jun 2025 04:39:58 -0700 (PDT) From: Breno Leitao Date: Wed, 25 Jun 2025 04:39:47 -0700 Subject: [PATCH net-next v2 2/4] selftests: drv-net: Improve bpftrace utility error handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250625-netpoll_test-v2-2-47d27775222c@debian.org> References: <20250625-netpoll_test-v2-0-47d27775222c@debian.org> In-Reply-To: <20250625-netpoll_test-v2-0-47d27775222c@debian.org> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Willem de Bruijn , bpf@vger.kernel.org, gustavold@gmail.com, Breno Leitao X-Mailer: b4 0.15-dev-dd21f X-Developer-Signature: v=1; a=openpgp-sha256; l=1094; i=leitao@debian.org; h=from:subject:message-id; bh=l/nda0XltKPv0ZkUvAchmFcqXkIO0WFjK5teLGJzfFE=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBoW+AKJtUozNMIskVSr3fnFpO0qK1UhqbTQYG2r 5CnlBIX7CmJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaFvgCgAKCRA1o5Of/Hh3 betsD/0dDiB8Vne1O00F+BDRbJfQVeifkj9vq8hxwdlkxQ1yHsmzGrzJv10TVdOQXF3E2VpxOZH BFqJg8usEEcctRDXhcbCBUCRSdr4lbSHY/sxx8BhvQzhMy9bmsBSbEcrxvmyJjsiuhGtbtoS0s2 FDyt0/g/XikNLixQjXjjekqOrx3IZpurVScf7pjG+SuKeG6f27jjp/8Nn5atsYTqjVZzH1axqxV yLOD4LSFaTpiUuo4H3Fk5cELz3TvQkEGdgH4gC2MJ8/oM4W0lfFeRj9i3hAwi+BCU7ZgyQyDqgP HO3PLWejTgKiGBfOEU/ojQ5WNe5NbwV5OaAUD9AfpW2v1/lZpUx0Kyi96J84gAK4LOLgT+kzg8m XUgYSg07eKpS0a/9eVXiT8JsHMz7v6iLbvTXmtWtngwEvCFZMzL5IqWe5U8/xGlZF+Kmng1HB3e dDhOOcaSwbyDIX2u+7zyd6opkV2EPTpwX4ac+052D1DoE8fGP8uVmCwhuqM8/FJYgw7Lyr63nKM GziA33LM66RB0NLjrl4fcdnhx/GVeRblUTK6PKx18dzhItbeW8nrsT+d7LrZeE1UUbUWUOxEne4 j70jocMX3sma+vfH7Bv/PYJXV47Zot751TfhLnuhEHRQddFKNHdQy92PNhNAgrmjt1EI8Nz/lcw Eb9AZJ3752thyMQ== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D Enhance the bpftrace function to raise an exception if the underlying bpftrace command returns a non-zero exit code. This helps detect and surface errors from bpftrace execution in test scripts, improving robustness and debugging capabilities. Signed-off-by: Breno Leitao --- tools/testing/selftests/net/lib/py/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/se= lftests/net/lib/py/utils.py index 760ccf6fccccc..c4e26567ee6fb 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -203,6 +203,9 @@ def bpftrace(expr, json=3DNone, ns=3DNone, host=3DNone,= timeout=3DNone): expr +=3D ' interval:s:' + str(timeout) + ' { exit(); }' cmd_arr +=3D ['-e', expr] cmd_obj =3D cmd(cmd_arr, ns=3Dns, host=3Dhost, shell=3DFalse) + if cmd_obj.ret !=3D 0: + raise Exception("Warning: bpftrace command returned a non-zero exi= t code.") + if json: # bpftrace prints objects as lines ret =3D {} --=20 2.47.1 From nobody Wed Oct 8 18:13:06 2025 Received: from mail-ej1-f51.google.com (mail-ej1-f51.google.com [209.85.218.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BB03825E80E; Wed, 25 Jun 2025 11:40:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750851604; cv=none; b=SQaEPeYnVLgck0mtNYvLbDwQEzb40+XjqEj7HTzum0ryIecso/A2iDbLjlS6eLakMbPQkDnFDZbun2uEyQWPJAP4gVec67uI9g45yZtSaoDr5YVU0LK3xf5alCjnaV+astSQkOt65hrF7mbOW/0blG83c0M+YxIqQLdUqX1SnR0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750851604; c=relaxed/simple; bh=XNs8x8ajNJh0fetiIm2YiGOf+JuBt4IW4h9OB4WhzIE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FBjXp7xxsqJpcFg6uNeYFtIMXiH6rN0tg/fqZoGf/oQqpxlUVRccQfdtoE/5nbRAbuTcHRDA6Z8kRiTC16V4nOXwRvc+6gNRwh+6QI25Xfd/CfxQIK/t95QQOSpApoctvuycgCrkkkVzRcpZhIcljKeuYHKeKRgU23I6gyeOvKo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.218.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ej1-f51.google.com with SMTP id a640c23a62f3a-ade4679fba7so263301766b.2; Wed, 25 Jun 2025 04:40:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750851601; x=1751456401; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=XBluJOszNCTRK8dAY0/F78ijOirMy7nuGhXV+efUFY0=; b=aE0DvOqIa2/tIzLY6dv1Mzhqtqgw54OCVqlKZ1Lhv4Y3cAMXPx3v2QJV+zdoYkPhfB DiTOfKPTX4TCQX1hKq6NiGGlg2Z7i1QmY2eoT6oKy8DDhCvvu21IbnknKIE0xLeZoywp +C+NRKWL8Zhv4WZG7mcJRmvZLvNqCuv+8w3sROGWa1vkRJtSAwM2Hoe+Bn1j+Mumk8Vu vR1YMHn8uVhPIBHvPkFoe5Gj1gpXUb12DA0Bag7g0Oy41dQyINUpsJTqJLpXw979KqBd rmT23q9K40tgwk4RsYzFwe51vUwyFIcAjS8k32E+pooh7rmdiAOgtqyt9t5zLu6BkuN8 n99g== X-Forwarded-Encrypted: i=1; AJvYcCUWOtjqS3YC+T2paT4ZGStNkptFH3WSRlCBeqmc0QwoVtA1E0j1quo/iWbv3Fho9re2IxB6C9IAJMAhNiuB/wg5@vger.kernel.org, AJvYcCW0Val+2CSvvks4kGSrkufZlVCrQxt8BvTPRlXJWeRhUQcm0r2p5W4VJEKdRredl5FyE9ZJ5HK/@vger.kernel.org, AJvYcCWqPcIQCkkFCyT7oUTYx3NzbmnL8x3E102JP28D5uVyGZGJEubcb4WDIRWYd2S2oYh+gs8=@vger.kernel.org X-Gm-Message-State: AOJu0Yx22iMF/lNaPRMW99vr7kQMivp3jpEA48cCbph3vTNNjt7vJjOv NGBQJgXMwwNFHORxtWvpie+3dPS2eHLIZVfqgntBvBNDV9GpHNw359Ki X-Gm-Gg: ASbGncsv9n74C6Q+mi6nSoThKSveT1ACrfSfKbUjlPPe8Aix1kE8fv1GPKcU2EcvJJH v5d+mHe6OOyPB/cJZIIrALwajwyKvdpfTLqwARps2PxiIivyOHu/eCelsnYv/ls1EVAqVYJAzgl NAEM5/IO4yDkeTrh+Qqwbdsc5NS+u9yzfx8hvuCxTUi4XG5j+dChMkCQ87aO/pI9StTIw51WXcy nO31WvH15RYGkxjb+HOWcwuXQTAWNu8l/AG9/E3e/ordc3Nb+mzzTb2fl5bbZmZe21FAFq/MVNQ E0wXW3tA02W+p4jP1XrFqxMYG8CyPpJwbql0ERxtlrLoY9U0Jw7K X-Google-Smtp-Source: AGHT+IHpNTp1W7tJfq4L4KfthhwdbcUMxxT1qFXk9AO0VZ5Xmv20HUmqkjjmbnLK3RPqlKFIixNxPg== X-Received: by 2002:a17:907:d24:b0:adf:f3c5:c858 with SMTP id a640c23a62f3a-ae0bf018b47mr264620566b.15.1750851600679; Wed, 25 Jun 2025 04:40:00 -0700 (PDT) Received: from localhost ([2a03:2880:30ff:1::]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ae054209b81sm1049408566b.171.2025.06.25.04.40.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Jun 2025 04:40:00 -0700 (PDT) From: Breno Leitao Date: Wed, 25 Jun 2025 04:39:48 -0700 Subject: [PATCH net-next v2 3/4] selftests: drv-net: Strip '@' prefix from bpftrace map keys Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250625-netpoll_test-v2-3-47d27775222c@debian.org> References: <20250625-netpoll_test-v2-0-47d27775222c@debian.org> In-Reply-To: <20250625-netpoll_test-v2-0-47d27775222c@debian.org> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Willem de Bruijn , bpf@vger.kernel.org, gustavold@gmail.com, Breno Leitao X-Mailer: b4 0.15-dev-dd21f X-Developer-Signature: v=1; a=openpgp-sha256; l=1053; i=leitao@debian.org; h=from:subject:message-id; bh=XNs8x8ajNJh0fetiIm2YiGOf+JuBt4IW4h9OB4WhzIE=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBoW+AKh0+jsKLXI3AbZ4DZBx1prGQzTY0cOOwSR +rkK0YH/BSJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaFvgCgAKCRA1o5Of/Hh3 bU5oD/95q5BM8Sr+/mJTE4kLrtVtHnpMdYsy+kVaSn+Q56G33qiiAaxHOOuwCOh1zQ/g1DtoYn+ 1t9CRBo8caWK7E4W3gTZ/p4xj9mzacSN4InF2PR/AzPUkSNswXPgHXqKKBKsHqqhZzbkZq7lL/7 iX8VhcHi+j3gUZEVOwU8L5k06DNRr1WOGP39pvGIeeZywM+DKGwI9FnWYKTwt2rgGthJujk3M6W 5fTTuN6BZuX7LcHFlgMrocmhX459FiYI2SY5VhGA1YG+vfRF0dXAxxIyeXaYVfOvvrCT8/RT39B hxUxAPelYRk3tocZgn9n2eHGyrhiJDdkUPJfToVkF9Ukoa3QCe6P68FQoKO1IEDMAfqVivKtOGH 2k95KzqJz60FcyYQPIvPFmxYNQTDc7zMqT8hHNXlwg2vKG3xR9TZ01OHnHqmKmU0N5USNF6D0p8 4+3FADzczgjJLhnEAaKzpTH+j/6FasG7wSpFY7AInadPC4znJnyRCjiM5xPaa/SG2EeaFSXLmMZ LJ/FAgVb0XZwSWpgyjavhTqQgzZigPMrZtdkNyXNZ4YXJHk27DPa5NnP5ltsEWPfOPg6/GmpnWQ t0bEb3fOJXCV2ANzemPwXTLq3QdIuzTblQKSTwvTQ8JLBIVNEewqwsN9vFpsLsBmTNju44TYd9E J5DCgwQ/su8812A== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D The '@' prefix in bpftrace map keys is specific to bpftrace and can be safely removed when processing results. This patch modifies the bpftrace utility to strip the '@' from map keys before storing them in the result dictionary, making the keys more consistent with Python conventions. Signed-off-by: Breno Leitao --- tools/testing/selftests/net/lib/py/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/se= lftests/net/lib/py/utils.py index c4e26567ee6fb..31d4d63621c5f 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -216,6 +216,8 @@ def bpftrace(expr, json=3DNone, ns=3DNone, host=3DNone,= timeout=3DNone): if one.get('type') !=3D 'map': continue for k, v in one["data"].items(): + if k.startswith('@'): + k =3D k.lstrip('@') ret[k] =3D v return ret return cmd_obj --=20 2.47.1 From nobody Wed Oct 8 18:13:06 2025 Received: from mail-ej1-f53.google.com (mail-ej1-f53.google.com [209.85.218.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4DA18282E1; Wed, 25 Jun 2025 11:40:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750851606; cv=none; b=uX48NdYwgcNn/e+YSPgXl3Vg9O8lGLIyzdNOye6X4++xLkZOPSbxIckfmEFkrOPyUTR58FUNUhIHhrljGRmeA5xAKV5ilv0jmw6J2EUd56l52qPMAf1Sw3jEhcx8TigECSMKqXQOkzCiGYDjievTAPAWskLzZZvJDoEohss5JgY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750851606; c=relaxed/simple; bh=1V77keAYAKO6PhvNwWxLz4ndN9mg0VbwyJete+lTLnM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EhuOQKjqL8TmP/ihIxYf2LweT7JJHwK+euybLH18CHjvah5Q3qCfGatfUzyw03zMk0xkra4RsTVElL1Ho2o6KW301TjX406VEDQ9C2p3arLD5SPkwaoqPN3NAC+VAxqoq6O32Ml5DsA8CDRlsWc1fkCYudo80SyU1YsKjvKFC9U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.218.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ej1-f53.google.com with SMTP id a640c23a62f3a-ae0bde4d5c9so160096166b.3; Wed, 25 Jun 2025 04:40:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750851602; x=1751456402; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=cVW00fFHOK2coUP4Gz0tDc16N3MRKLw8p2gbcpvVlgE=; b=Jta7b60AWaI6pfnH57bkLqf+ImrK2GZjgKjLQ1Fyc3YRuvYVpNmmn8/beIItEQv+d/ omtQWHG55HxHsjwbdu81DfOhB00KhzygoEWecQB6O+l91fAqv21t2Xth1BJNPhV3mr2W qUZTzr+9Cq9estkRmPwN1HXZagpmu0DbKfJuwlEFijyqlVZOkPCCZyhMgHTkxCaRxMyY HFGFFd/G3kxKa5wqtI9NqYIMWA/jAuX4iiLHi+7czQKG0ssBJl53y0THl1YNpxdIfDgb UEQaVUoBwVMTCmGCSThqE7//ccZPc4wGtDBJQ1h/Tla34e0UkFvID6AN8wlpFbRDLR9i SWug== X-Forwarded-Encrypted: i=1; AJvYcCWL9lR5QaYRh0f7rKc7pFb+gTmBJySLaWsaU0o9VdcNqU10XkPRs5OzEMlSLpmXV22iHaEBlndHJsNVR2JJyWJU@vger.kernel.org, AJvYcCX+vdopMZEtyUl8QDoyEmriV8esp0kmmihl6HAXcgLehXNXyg9L6chG5t3xAhJrsvjQasWF0Jbv@vger.kernel.org, AJvYcCX4RddUxvd11QVknpAdq+stYjd0lVvTk2nbtb634AI93d6pBMVV22KXFE/g/mb94jkdGNg=@vger.kernel.org X-Gm-Message-State: AOJu0YwKdcC9GZ+tHk2BzzHmXxMy0X3P88LQYXWPjljBfSFh8UCImItg OVQ1tDQv54qV4C8VOCDAkJkE254DDtCd/60EQrrv229pwfqsinJqyXdS X-Gm-Gg: ASbGncu1cbP0+dvHtR95Xf7PDrWMaMvX6VFvkXKSBI+BmteI6SwL8RWJOHhn6hnSQy7 H8II7sDoTly/58P47MA+Z0J9KRbSCazkA2/Z6JMHlzWCizSaXtYRiYhQ8rGgAQHEE7NnufjDOh8 OHs30qxT/Ve3JZL8gwS/hXXOSsOASoIFLQ1bJwx+f41wONqVBQPd9v6mJHor/ll4QqghD3Rn1o3 EkEoOGyzqviRjt67V+NACXKjRrfWNMnTRqvkDkzZ8meURTaJZt1Bpu4XZFDaU3ViQXrG45Ei9q0 9fIhxtQNaSwqWDagv6p3X/YvcJIz8loSkyW9PNFKqY9qzmfnpg3O X-Google-Smtp-Source: AGHT+IFWeDT3WFcvAAUQ2yYtbpblEQUEljeqldWF+Glyck2/grkcGnp4zPYUorlpdUaDZe7lzpNtXQ== X-Received: by 2002:a17:906:c14f:b0:ade:3bec:ea29 with SMTP id a640c23a62f3a-ae0be8942d4mr251406966b.25.1750851602212; Wed, 25 Jun 2025 04:40:02 -0700 (PDT) Received: from localhost ([2a03:2880:30ff:9::]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ae054209349sm1036314866b.152.2025.06.25.04.40.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Jun 2025 04:40:01 -0700 (PDT) From: Breno Leitao Date: Wed, 25 Jun 2025 04:39:49 -0700 Subject: [PATCH net-next v2 4/4] selftests: net: add netpoll basic functionality test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250625-netpoll_test-v2-4-47d27775222c@debian.org> References: <20250625-netpoll_test-v2-0-47d27775222c@debian.org> In-Reply-To: <20250625-netpoll_test-v2-0-47d27775222c@debian.org> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Willem de Bruijn , bpf@vger.kernel.org, gustavold@gmail.com, Breno Leitao X-Mailer: b4 0.15-dev-dd21f X-Developer-Signature: v=1; a=openpgp-sha256; l=14021; i=leitao@debian.org; h=from:subject:message-id; bh=1V77keAYAKO6PhvNwWxLz4ndN9mg0VbwyJete+lTLnM=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBoW+AL6cjhhRMViKrBgizp0Kh0Xy/ViYLyqGc3D mrf/PlPvemJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCaFvgCwAKCRA1o5Of/Hh3 bQ6jD/sFcz4/EAY3iJhC5jjZDeaaUfJMORjyaYrOrIbrugtBOomWE5YDN6vqLx2wSgdhDRcDnvG IZZ5qw7+7DgmT3QJiyOqj8TaneQgbiNY5qmQOux5ZIZA5x5Bfl3ipRpJ7FMSSa9YnyW1ryIVmgG sobwYGnZAMd+nu9/Smfh3XNBol23dsJJc7ux4qeFe0sHU+5lkQ1jX5IkGMMZdiAmGqSuKcb4P/9 yOCPEcnICOOvYjp1tcoy41CDH3rmatXTs+fGzOue+i3r/L1WOX8qQ4ZK8QJiqz5YP8IplhhWnNn 4BHU1YEp445nzDzr1AEq5VpHcgrIj0G4DYNF7x7NZ7KtdY5qdbI1RUIChC/czJUjq0deQE3Q/tq EMwGqVbsCSOC3MnwTlnIAmfdPaou4HjLZRubqosUiY3HJjkwHzgFCDRDJNlLWW16I5zR3ziFZrm guuXKUGqvecPs8OcGr27ZC/cjdpk8Mg0QwFJV+BjAUFt0FjiptjWokeyovqNQyr8Xlt2pf1kry9 2J4UMr8jcUY6r8XAt66MdXYLLRrrqXE/+GXqzD5nEKGJBxgiPt59r7JZryMoslrr3M1/ClWt7M2 jiuWChTrNV52x5tgGfk6GqvBCwCOxELWG+yvoZxTpMYYKK0cgajk+Pg6NlhFieyqCxByy6Zisy4 DPLNI+3XS9SlWUw== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D Add a basic selftest for the netpoll polling mechanism, specifically targeting the netpoll poll() side. The test creates a scenario where network transmission is running at maximum speed, and netpoll needs to poll the NIC. This is achieved by: 1. Configuring a single RX/TX queue to create contention 2. Generating background traffic to saturate the interface 3. Sending netconsole messages to trigger netpoll polling 4. Using dynamic netconsole targets via configfs 5. Delete and create new netconsole targets after some messages 6. Start a bpftrace in parallel to make sure netpoll_poll_dev() is called 7. If bpftrace exists and netpoll_poll_dev() was called, stop. The test validates a critical netpoll code path by monitoring traffic flow and ensuring netpoll_poll_dev() is called when the normal TX path is blocked. This addresses a gap in netpoll test coverage for a path that is tricky for the network stack. Signed-off-by: Breno Leitao --- tools/testing/selftests/drivers/net/Makefile | 1 + .../testing/selftests/drivers/net/netpoll_basic.py | 344 +++++++++++++++++= ++++ 2 files changed, 345 insertions(+) diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/s= elftests/drivers/net/Makefile index bd309b2d39095..9bd84d6b542e5 100644 --- a/tools/testing/selftests/drivers/net/Makefile +++ b/tools/testing/selftests/drivers/net/Makefile @@ -16,6 +16,7 @@ TEST_PROGS :=3D \ netcons_fragmented_msg.sh \ netcons_overflow.sh \ netcons_sysdata.sh \ + netpoll_basic.py \ ping.py \ queues.py \ stats.py \ diff --git a/tools/testing/selftests/drivers/net/netpoll_basic.py b/tools/t= esting/selftests/drivers/net/netpoll_basic.py new file mode 100755 index 0000000000000..dfb52d6793466 --- /dev/null +++ b/tools/testing/selftests/drivers/net/netpoll_basic.py @@ -0,0 +1,344 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# Author: Breno Leitao +""" + This test aims to evaluate the netpoll polling mechanism (as in + netpoll_poll_dev()). It presents a complex scenario where the network + attempts to send a packet but fails, prompting it to poll the NIC from wi= thin + the netpoll TX side. + + This has been a crucial path in netpoll that was previously untested. Jak= ub + suggested using a single RX/TX queue, pushing traffic to the NIC, and then + sending netpoll messages (via netconsole) to trigger the poll. + + In parallel, bpftrace is used to detect if netpoll_poll_dev() was called.= If + so, the test passes, otherwise it will be skipped. This test is very depe= ndent on + the driver and environment, given we are trying to trigger a tricky scena= rio. +""" + +import errno +import logging +import os +import random +import string +import threading +import time + +from lib.py import ( + bpftrace, + ethtool, + GenerateTraffic, + ksft_exit, + ksft_pr, + ksft_run, + KsftFailEx, + KsftSkipEx, + NetdevFamily, + NetDrvEpEnv, +) + +# Configure logging +logging.basicConfig( + level=3Dlogging.INFO, + format=3D"%(asctime)s - %(levelname)s - %(message)s", +) + +NETCONSOLE_CONFIGFS_PATH: str =3D "/sys/kernel/config/netconsole" +NETCONS_REMOTE_PORT: int =3D 6666 +NETCONS_LOCAL_PORT: int =3D 1514 +# Max number of netcons messages to send. Each iteration will setup +# netconsole and send 10 messages +ITERATIONS: int =3D 20 +# MAPS contains the information coming from bpftrace +# it will have only one key: @hits, which tells the number of times +# netpoll_poll_dev() was called +MAPS: dict[str, int] =3D {} +# Thread to run bpftrace in parallel +BPF_THREAD: threading.Thread =3D None +# Time bpftrace will be running in parallel. +BPFTRACE_TIMEOUT: int =3D 15 + + +def ethtool_read_rx_tx_queue(interface_name: str) -> tuple[int, int]: + """ + Read the number of RX and TX queues using ethtool. This will be used + to restore it after the test + """ + try: + ethtool_result =3D ethtool(f"-g {interface_name}").stdout + for line in ethtool_result.splitlines(): + if line.startswith("RX:"): + rx_queue =3D int(line.split()[1]) + if line.startswith("TX:"): + tx_queue =3D int(line.split()[1]) + except IndexError as exception: + raise KsftSkipEx( + f"Failed to read RX/TX queues numbers: {exception}. Not going = to mess with them." + ) from exception + + return rx_queue, tx_queue + + +def ethtool_set_rx_tx_queue(interface_name: str, rx_val: int, tx_val: int)= -> None: + """Set the number of RX and TX queues to 1 using ethtool""" + try: + # This don't need to be reverted, since interfaces will be deleted= after test + ethtool(f"-G {interface_name} rx {rx_val} tx {tx_val}") + except Exception as exception: + raise KsftSkipEx( + f"Failed to configure RX/TX queues: {exception}. Ethtool not a= vailable?" + ) from exception + + +def netcons_generate_random_target_name() -> str: + """Generate a random target name starting with 'netcons'""" + random_suffix =3D "".join(random.choices(string.ascii_lowercase + stri= ng.digits, k=3D8)) + return f"netcons_{random_suffix}" + + +def netcons_create_target( + config_data: dict[str, str], + target_name: str, +) -> None: + """Create a netconsole dynamic target against the interfaces""" + logging.debug("Using netconsole name: %s", target_name) + try: + os.makedirs(f"{NETCONSOLE_CONFIGFS_PATH}/{target_name}", exist_ok= =3DTrue) + logging.debug( + "Created target directory: %s/%s", NETCONSOLE_CONFIGFS_PATH, t= arget_name + ) + except OSError as exception: + if exception.errno !=3D errno.EEXIST: + raise KsftFailEx( + f"Failed to create netconsole target directory: {exception= }" + ) from exception + + try: + for key, value in config_data.items(): + path =3D f"{NETCONSOLE_CONFIGFS_PATH}/{target_name}/{key}" + logging.debug("Writing %s to %s", key, path) + with open(path, "w", encoding=3D"utf-8") as file: + # Always convert to string to write to file + file.write(str(value)) + file.close() + + # Read all configuration values for debugging purposes + for debug_key in config_data.keys(): + with open( + f"{NETCONSOLE_CONFIGFS_PATH}/{target_name}/{debug_key}", + "r", + encoding=3D"utf-8", + ) as file: + content =3D file.read() + logging.debug( + "%s/%s/%s : %s", + NETCONSOLE_CONFIGFS_PATH, + target_name, + debug_key, + content, + ) + + except Exception as exception: + raise KsftFailEx( + f"Failed to configure netconsole target: {exception}" + ) from exception + + +def netcons_configure_target( + cfg: NetDrvEpEnv, interface_name: str, target_name: str +) -> None: + """Configure netconsole on the interface with the given target name""" + config_data =3D { + "extended": "1", + "dev_name": interface_name, + "local_port": NETCONS_LOCAL_PORT, + "remote_port": NETCONS_REMOTE_PORT, + "local_ip": cfg.addr_v["4"] if cfg.addr_ipver =3D=3D "4" else cfg.= addr_v["6"], + "remote_ip": ( + cfg.remote_addr_v["4"] if cfg.addr_ipver =3D=3D "4" else cfg.r= emote_addr_v["6"] + ), + "remote_mac": "00:00:00:00:00:00", # Not important for this test + "enabled": "1", + } + + netcons_create_target(config_data, target_name) + logging.debug( + "Created netconsole target: %s on interface %s", target_name, inte= rface_name + ) + + +def netcons_delete_target(name: str) -> None: + """Delete a netconsole dynamic target""" + target_path =3D f"{NETCONSOLE_CONFIGFS_PATH}/{name}" + try: + if os.path.exists(target_path): + os.rmdir(target_path) + except OSError as exception: + raise KsftFailEx( + f"Failed to delete netconsole target: {exception}" + ) from exception + + +def netcons_load_module() -> None: + """Try to load the netconsole module""" + os.system("modprobe netconsole") + + +def bpftrace_call() -> None: + """Call bpftrace to find how many times netpoll_poll_dev() is called. + Output is saved in the global variable `maps`""" + + # This is going to update the global variable, that will be seen by the + # main function + global MAPS # pylint: disable=3DW0603 + + # This will be passed to bpftrace as in bpftrace -e "expr" + expr =3D "BEGIN{ @hits =3D 0;} kprobe:netpoll_poll_dev { @hits +=3D 1;= }" + + MAPS =3D bpftrace(expr, timeout=3DBPFTRACE_TIMEOUT, json=3DTrue) + logging.debug("BPFtrace output: %s", MAPS) + + +def bpftrace_start(): + """Start a thread to call `call_bpf` in parallel for 2 seconds.""" + global BPF_THREAD # pylint: disable=3DW0603 + + BPF_THREAD =3D threading.Thread(target=3Dbpftrace_call) + BPF_THREAD.start() + if not BPF_THREAD.is_alive(): + raise KsftSkipEx("BPFtrace thread is not alive. Skipping test") + + +def bpftrace_stop() -> None: + """Stop the bpftrace thread""" + if BPF_THREAD: + BPF_THREAD.join() + + +def bpftrace_any_hit(join: bool) -> bool: + """Check if netpoll_poll_dev() was called by checking the global varia= ble `maps`""" + if BPF_THREAD.is_alive(): + if join: + # Wait for bpftrace to finish + BPF_THREAD.join() + else: + # bpftrace is still running, so, we will not check the result = yet + return False + + logging.debug("MAPS coming from bpftrace =3D %s", MAPS) + if "hits" not in MAPS.keys(): + raise KsftFailEx(f"bpftrace failed to run!?: {MAPS}") + + return MAPS["hits"] > 0 + + +def do_netpoll_flush_monitored( + cfg: NetDrvEpEnv, netdevnl: NetdevFamily, ifname: str, target_name: str +) -> None: + """Print messages to the console, trying to trigger a netpoll poll""" + # Start bpftrace in parallel, so, it is watching + # netpoll_poll_dev() while we are sending netconsole messages + bpftrace_start() + + do_netpoll_flush(cfg, netdevnl, ifname, target_name) + + if bpftrace_any_hit(join=3DTrue): + ksft_pr("netpoll_poll_dev() was called. Success") + return + + raise KsftSkipEx("netpoll_poll_dev() was not called. Skipping test") + + +def do_netpoll_flush( + cfg: NetDrvEpEnv, netdevnl: NetdevFamily, ifname: str, target_name: str +) -> None: + """Print messages to the console, trying to trigger a netpoll poll""" + netcons_configure_target(cfg, ifname, target_name) + retry =3D 0 + + for i in range(int(ITERATIONS)): + msg =3D f"netcons test #{i}" + + with open("/dev/kmsg", "w", encoding=3D"utf-8") as kmsg: + for j in range(10): + try: + kmsg.write(f"{msg}-{j}\n") + except OSError as exception: + # in some cases, kmsg can be busy, so, we will retry + time.sleep(1) + retry +=3D 1 + if retry < 5: + logging.info("Failed to write to kmsg. Retrying") + # Just retry a few times + continue + raise KsftFailEx( + f"Failed to write to kmsg: {exception}" + ) from exception + + if bpftrace_any_hit(join=3DFalse): + # Check if netpoll_poll_dev() was called, but do not wait = for it + # to finish. + ksft_pr("netpoll_poll_dev() was called. Success") + return + + # Every 5 iterations, toggle netconsole + netcons_delete_target(target_name) + netcons_configure_target(cfg, ifname, target_name) + # If we sleep here, we will have a better chance of triggering + # This number is based on a few tests I ran while developing this = test + time.sleep(0.4) + + +def test_netpoll(cfg: NetDrvEpEnv, netdevnl: NetdevFamily) -> None: + """ + Test netpoll by sending traffic to the interface and then sending + netconsole messages to trigger a poll + """ + + target_name =3D netcons_generate_random_target_name() + ifname =3D cfg.dev["ifname"] + traffic =3D None + original_queues =3D ethtool_read_rx_tx_queue(ifname) + + try: + # Set RX/TX queues to 1 to force congestion + ethtool_set_rx_tx_queue(ifname, 1, 1) + + traffic =3D GenerateTraffic(cfg) + do_netpoll_flush_monitored(cfg, netdevnl, ifname, target_name) + finally: + if traffic: + traffic.stop() + + # Revert RX/TX queues + ethtool_set_rx_tx_queue(ifname, original_queues[0], original_queue= s[1]) + netcons_delete_target(target_name) + bpftrace_stop() + + +def test_check_dependencies() -> None: + """Check if the dependencies are met""" + if not os.path.exists(NETCONSOLE_CONFIGFS_PATH): + raise KsftSkipEx( + f"Directory {NETCONSOLE_CONFIGFS_PATH} does not exist. CONFIG_= NETCONSOLE_DYNAMIC might not be set." + ) + + +def main() -> None: + """Main function to run the test""" + netcons_load_module() + test_check_dependencies() + netdevnl =3D NetdevFamily() + with NetDrvEpEnv(__file__, nsim_test=3DTrue) as cfg: + ksft_run( + [test_netpoll], + args=3D( + cfg, + netdevnl, + ), + ) + ksft_exit() + + +if __name__ =3D=3D "__main__": + main() --=20 2.47.1