Netdev List
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com,
	andrew+netdev@lunn.ch, horms@kernel.org, jv@jvosburgh.net,
	haiyangz@microsoft.com, ast@kernel.org, hawk@kernel.org,
	john.fastabend@gmail.com, sdf@fomichev.me, bpf@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org,
	Jakub Kicinski <kuba@kernel.org>
Subject: [PATCH net-next 5/5] selftests/bpf: check replacing and detaching XDP on a bond through a link
Date: Thu, 12 Nov 2026 15:50:27 -0800	[thread overview]
Message-ID: <20261112235027.4072149-6-kuba@kernel.org> (raw)
In-Reply-To: <20261112235027.4072149-1-kuba@kernel.org>

The bond tests attach and destroy links, but never replace the program
behind one, or detach it without closing the link. Both only ever
operate on the device the link was created on, and rely on the bond to
pass the change down to its slaves.

Check that the slave follows the replacement and the detach, and that
the program which got replaced is released - the bond used to leak it.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
 .../selftests/bpf/prog_tests/xdp_bonding.c    | 96 +++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c b/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c
index ab0f01be4131..05f2e8079858 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c
@@ -516,6 +516,99 @@ static void test_xdp_bonding_nested(struct skeletons *skeletons)
 	system("ip link del bond_nest2");
 }
 
+/*
+ * Replace, then detach the program on a bond through its link. The link only
+ * knows about the bond, the slave has to follow it, and the replaced program
+ * has to be released.
+ */
+static void test_xdp_bonding_link_update(struct skeletons *skeletons)
+{
+	LIBBPF_OPTS(bpf_prog_load_opts, opts, .expected_attach_type = BPF_XDP);
+	struct bpf_program *new_prog = skeletons->xdp_dummy->progs.xdp_dummy_prog;
+	struct bpf_insn insns[] = {
+		BPF_MOV64_IMM(BPF_REG_0, XDP_PASS),
+		BPF_EXIT_INSN(),
+	};
+	int veth, bond, err, fd, old_fd = -1, link_fd = -1;
+	struct bpf_prog_info info = {};
+	__u32 old_id, new_id, id, len;
+
+	if (!ASSERT_OK(system("ip link add veth type veth"), "add veth"))
+		goto out;
+	if (!ASSERT_OK(system("ip link add bond type bond"), "add bond"))
+		goto out;
+
+	veth = if_nametoindex("veth");
+	if (!ASSERT_GT(veth, 0, "if_nametoindex veth"))
+		goto out;
+	bond = if_nametoindex("bond");
+	if (!ASSERT_GT(bond, 0, "if_nametoindex bond"))
+		goto out;
+
+	err = system("ip link set veth master bond");
+	if (!ASSERT_OK(err, "set veth master"))
+		goto out;
+
+	/* same attach type as the skeleton's, or the link won't take it */
+	old_fd = bpf_prog_load(BPF_PROG_TYPE_XDP, "xdp_old", "GPL", insns,
+			       ARRAY_SIZE(insns), &opts);
+	if (!ASSERT_GE(old_fd, 0, "load old program"))
+		goto out;
+	len = sizeof(info);
+	if (!ASSERT_OK(bpf_prog_get_info_by_fd(old_fd, &info, &len), "old program info"))
+		goto out;
+	old_id = info.id;
+
+	memset(&info, 0, sizeof(info));
+	len = sizeof(info);
+	err = bpf_prog_get_info_by_fd(bpf_program__fd(new_prog), &info, &len);
+	if (!ASSERT_OK(err, "new program info"))
+		goto out;
+	new_id = info.id;
+
+	link_fd = bpf_link_create(old_fd, bond, BPF_XDP, NULL);
+	if (!ASSERT_GE(link_fd, 0, "attach old program to bond"))
+		goto out;
+
+	err = bpf_xdp_query_id(veth, XDP_FLAGS_DRV_MODE, &id);
+	if (!ASSERT_OK(err, "query veth") ||
+	    !ASSERT_EQ(id, old_id, "veth runs the old program"))
+		goto out;
+
+	err = bpf_link_update(link_fd, bpf_program__fd(new_prog), NULL);
+	if (!ASSERT_OK(err, "replace the program through the link"))
+		goto out;
+
+	err = bpf_xdp_query_id(veth, XDP_FLAGS_DRV_MODE, &id);
+	if (!ASSERT_OK(err, "query veth") ||
+	    !ASSERT_EQ(id, new_id, "veth follows to the new program"))
+		goto out;
+
+	/* nothing but our fd should be holding on to the old program now */
+	close(old_fd);
+	old_fd = -1;
+	fd = bpf_prog_get_fd_by_id(old_id);
+	if (!ASSERT_EQ(fd, -ENOENT, "old program released") && fd >= 0)
+		close(fd);
+
+	err = bpf_link_detach(link_fd);
+	if (!ASSERT_OK(err, "detach the link"))
+		goto out;
+
+	err = bpf_xdp_query_id(veth, XDP_FLAGS_DRV_MODE, &id);
+	if (!ASSERT_OK(err, "query veth"))
+		goto out;
+	ASSERT_EQ(id, 0, "veth has no program left");
+
+out:
+	if (link_fd >= 0)
+		close(link_fd);
+	if (old_fd >= 0)
+		close(old_fd);
+	system("ip link del veth");
+	system("ip link del bond");
+}
+
 /*
  * Test that XDP redirect via xdp_master_redirect() does not crash when
  * the bond master device is not up. When bond is in round-robin mode but
@@ -826,6 +919,9 @@ void serial_test_xdp_bonding(void)
 	if (test__start_subtest("xdp_bonding_nested"))
 		test_xdp_bonding_nested(&skeletons);
 
+	if (test__start_subtest("xdp_bonding_link_update"))
+		test_xdp_bonding_link_update(&skeletons);
+
 	if (test__start_subtest("xdp_bonding_features"))
 		test_xdp_bonding_features(&skeletons);
 
-- 
2.56.0


      parent reply	other threads:[~2026-11-12 23:50 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12 23:50 [PATCH net-next 0/5] net: make xdp config checks effective vs netif_xdp_propagate() Jakub Kicinski
2026-11-12 23:50 ` [PATCH net-next 1/5] net: don't safety-check device features for XDP uninstall Jakub Kicinski
2026-11-12 23:50 ` [PATCH net-next 2/5] net: move dev_xdp_set_link() and dev_xdp_set_prog() up Jakub Kicinski
2026-11-12 23:50 ` [PATCH net-next 3/5] net: record XDP programs propagated to lower devices Jakub Kicinski
2026-11-12 23:50 ` [PATCH net-next 4/5] selftests/bpf: check XDP attach on a nested bond slave Jakub Kicinski
2026-11-12 23:50 ` Jakub Kicinski [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261112235027.4072149-6-kuba@kernel.org \
    --to=kuba@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=haiyangz@microsoft.com \
    --cc=hawk@kernel.org \
    --cc=horms@kernel.org \
    --cc=john.fastabend@gmail.com \
    --cc=jv@jvosburgh.net \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sdf@fomichev.me \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox