From: Weijun Pan <wpan3636@gmail.com>
To: Chas Williams <3chas3@gmail.com>,
"Min Hu (Connor)" <humin29@huawei.com>,
Anatoly Burakov <anatoly.burakov@intel.com>
Cc: dev@dpdk.org, Weijun Pan <wpan3636@gmail.com>
Subject: [RFC PATCH v3] net/bonding: restrict secondary control operations
Date: Wed, 26 Aug 2026 11:10:09 -0500 [thread overview]
Message-ID: <20260826161009.37875-1-wpan3636@gmail.com> (raw)
In-Reply-To: <20260823151625.18687-1-wpan3636@gmail.com>
Bonding configuration and LACP state are owned by the primary
process. Install a reduced dev_ops table in secondary processes so
ethdev rejects control operations, and reject the bonding control
API when called from a non-primary process. Query and detach remain
available.
Bugzilla ID: 1900
Signed-off-by: Weijun Pan <wpan3636@gmail.com>
---
v3:
- Document that secondary bonding Rx/Tx are unsupported.
- Reject secondary LACP runtime state queries.
- Remove private dump from secondary dev_ops.
- Use a common primary-process helper.
- Shorten release notes.
.../link_bonding_poll_mode_drv_lib.rst | 13 +++++
doc/guides/rel_notes/release_26_11.rst | 4 ++
drivers/net/bonding/eth_bond_private.h | 12 +++++
drivers/net/bonding/rte_eth_bond_8023ad.c | 48 +++++++++++++++++
drivers/net/bonding/rte_eth_bond_api.c | 53 ++++++++++++++++++-
drivers/net/bonding/rte_eth_bond_pmd.c | 11 +++-
6 files changed, 139 insertions(+), 2 deletions(-)
diff --git a/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst b/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst
index 2fa1ac4028..8e602e51b1 100644
--- a/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst
+++ b/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst
@@ -254,6 +254,19 @@ Like all other PMD, all functions exported by a PMD are lock-free functions
that are assumed not to be invoked in parallel on different logical cores to
work on the same target object.
+Bonding device configuration and LACP runtime state are owned by the primary
+process. Secondary processes may attach to an existing bonding device for
+supported query and detach operations, but control operations are restricted
+to the primary process.
+
+In a secondary process, bonding control operations such as configuring,
+starting or stopping the device, setting up queues, changing members,
+changing the bonding mode, updating RSS, changing MAC addresses, changing
+MTU, or configuring ``rte_flow`` rules are not supported.
+
+Rx and Tx are not supported on a bonding device in a secondary process;
+receive returns no packets and transmit drops packets.
+
It should also be noted that the PMD receive function should not be invoked
directly on a member devices after they have been to a bonding device since
packets read directly from the member device will no longer be available to the
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index c8cc86295d..1d03e3ee9b 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -55,6 +55,10 @@ New Features
Also, make sure to start the actual text at the margin.
=======================================================
+* **Restricted bonding device control to the primary process.**
+
+ Supported query and detach paths remain available to secondary processes,
+ while bonding device configuration changes are rejected.
Removed Items
-------------
diff --git a/drivers/net/bonding/eth_bond_private.h b/drivers/net/bonding/eth_bond_private.h
index 378bbba4e6..526bcd0363 100644
--- a/drivers/net/bonding/eth_bond_private.h
+++ b/drivers/net/bonding/eth_bond_private.h
@@ -7,12 +7,14 @@
#include <stdint.h>
#include <sys/queue.h>
+#include <stdbool.h>
#include <ethdev_driver.h>
#include <rte_flow.h>
#include <rte_spinlock.h>
#include <rte_bitmap.h>
#include <rte_flow_driver.h>
+#include <rte_eal.h>
#include "rte_eth_bond.h"
#include "eth_bond_8023ad_private.h"
@@ -212,6 +214,16 @@ find_member_by_id(uint16_t *members, uint16_t members_count, uint16_t member_id)
return pos;
}
+static inline int
+bond_check_primary(const char *op, int err)
+{
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ return 0;
+
+ RTE_BOND_LOG(ERR, "%s not supported in non-primary process", op);
+ return err;
+}
+
int
valid_port_id(uint16_t port_id);
diff --git a/drivers/net/bonding/rte_eth_bond_8023ad.c b/drivers/net/bonding/rte_eth_bond_8023ad.c
index d1f30229d0..65f417a444 100644
--- a/drivers/net/bonding/rte_eth_bond_8023ad.c
+++ b/drivers/net/bonding/rte_eth_bond_8023ad.c
@@ -1436,6 +1436,11 @@ rte_eth_bond_8023ad_agg_selection_set(uint16_t port_id,
struct rte_eth_dev *bond_dev;
struct bond_dev_private *internals;
struct mode8023ad_private *mode4;
+ int ret;
+
+ ret = bond_check_primary(__func__, -ENOTSUP);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(port_id) != 0)
return -EINVAL;
@@ -1508,6 +1513,11 @@ rte_eth_bond_8023ad_setup(uint16_t port_id,
{
struct rte_eth_dev *bond_dev;
int err;
+ int ret;
+
+ ret = bond_check_primary(__func__, -ENOTSUP);
+ if (ret != 0)
+ return ret;
err = bond_8023ad_setup_validate(port_id, conf);
if (err != 0)
@@ -1531,6 +1541,11 @@ rte_eth_bond_8023ad_member_info(uint16_t port_id, uint16_t member_id,
struct rte_eth_dev *bond_dev;
struct bond_dev_private *internals;
struct port *port;
+ int ret;
+
+ ret = bond_check_primary(__func__, -ENOTSUP);
+ if (ret != 0)
+ return ret;
if (info == NULL || valid_bonding_port_id(port_id) != 0 ||
rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
@@ -1592,6 +1607,11 @@ rte_eth_bond_8023ad_ext_collect(uint16_t port_id, uint16_t member_id,
{
struct port *port;
int res;
+ int ret;
+
+ ret = bond_check_primary(__func__, -ENOTSUP);
+ if (ret != 0)
+ return ret;
res = bond_8023ad_ext_validate(port_id, member_id);
if (res != 0)
@@ -1614,6 +1634,11 @@ rte_eth_bond_8023ad_ext_distrib(uint16_t port_id, uint16_t member_id,
{
struct port *port;
int res;
+ int ret;
+
+ ret = bond_check_primary(__func__, -ENOTSUP);
+ if (ret != 0)
+ return ret;
res = bond_8023ad_ext_validate(port_id, member_id);
if (res != 0)
@@ -1636,6 +1661,10 @@ rte_eth_bond_8023ad_ext_distrib_get(uint16_t port_id, uint16_t member_id)
struct port *port;
int err;
+ err = bond_check_primary(__func__, -ENOTSUP);
+ if (err != 0)
+ return err;
+
err = bond_8023ad_ext_validate(port_id, member_id);
if (err != 0)
return err;
@@ -1651,6 +1680,10 @@ rte_eth_bond_8023ad_ext_collect_get(uint16_t port_id, uint16_t member_id)
struct port *port;
int err;
+ err = bond_check_primary(__func__, -ENOTSUP);
+ if (err != 0)
+ return err;
+
err = bond_8023ad_ext_validate(port_id, member_id);
if (err != 0)
return err;
@@ -1666,6 +1699,11 @@ rte_eth_bond_8023ad_ext_slowtx(uint16_t port_id, uint16_t member_id,
{
struct port *port;
int res;
+ int ret;
+
+ ret = bond_check_primary(__func__, -ENOTSUP);
+ if (ret != 0)
+ return ret;
res = bond_8023ad_ext_validate(port_id, member_id);
if (res != 0)
@@ -1727,6 +1765,11 @@ rte_eth_bond_8023ad_dedicated_queues_enable(uint16_t port)
{
struct rte_eth_dev *dev;
struct bond_dev_private *internals;
+ int ret;
+
+ ret = bond_check_primary(__func__, -ENOTSUP);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(port) != 0)
return -EINVAL;
@@ -1756,6 +1799,11 @@ rte_eth_bond_8023ad_dedicated_queues_disable(uint16_t port)
{
struct rte_eth_dev *dev;
struct bond_dev_private *internals;
+ int ret;
+
+ ret = bond_check_primary(__func__, -ENOTSUP);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(port) != 0)
return -EINVAL;
diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c
index d9b6f1c417..029e141d89 100644
--- a/drivers/net/bonding/rte_eth_bond_api.c
+++ b/drivers/net/bonding/rte_eth_bond_api.c
@@ -159,6 +159,10 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
char devargs[52];
int ret;
+ ret = bond_check_primary(__func__, -1);
+ if (ret != 0)
+ return ret;
+
if (name == NULL) {
RTE_BOND_LOG(ERR, "Invalid name specified");
return -EINVAL;
@@ -640,9 +644,12 @@ rte_eth_bond_member_add(uint16_t bonding_port_id, uint16_t member_port_id)
{
struct rte_eth_dev *bonding_eth_dev;
struct bond_dev_private *internals;
-
int retval;
+ retval = bond_check_primary(__func__, -1);
+ if (retval != 0)
+ return retval;
+
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
@@ -781,6 +788,10 @@ rte_eth_bond_member_remove(uint16_t bonding_port_id, uint16_t member_port_id)
struct bond_dev_private *internals;
int retval;
+ retval = bond_check_primary(__func__, -1);
+ if (retval != 0)
+ return retval;
+
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
@@ -801,6 +812,11 @@ int
rte_eth_bond_mode_set(uint16_t bonding_port_id, uint8_t mode)
{
struct rte_eth_dev *bonding_eth_dev;
+ int ret;
+
+ ret = bond_check_primary(__func__, -1);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
@@ -833,6 +849,11 @@ int
rte_eth_bond_primary_set(uint16_t bonding_port_id, uint16_t member_port_id)
{
struct bond_dev_private *internals;
+ int ret;
+
+ ret = bond_check_primary(__func__, -1);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
@@ -923,6 +944,11 @@ rte_eth_bond_mac_address_set(uint16_t bonding_port_id,
{
struct rte_eth_dev *bonding_eth_dev;
struct bond_dev_private *internals;
+ int ret;
+
+ ret = bond_check_primary(__func__, -1);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
@@ -949,6 +975,11 @@ rte_eth_bond_mac_address_reset(uint16_t bonding_port_id)
{
struct rte_eth_dev *bonding_eth_dev;
struct bond_dev_private *internals;
+ int ret;
+
+ ret = bond_check_primary(__func__, -1);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
@@ -990,6 +1021,11 @@ int
rte_eth_bond_xmit_policy_set(uint16_t bonding_port_id, uint8_t policy)
{
struct bond_dev_private *internals;
+ int ret;
+
+ ret = bond_check_primary(__func__, -1);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
@@ -1035,6 +1071,11 @@ int
rte_eth_bond_link_monitoring_set(uint16_t bonding_port_id, uint32_t internal_ms)
{
struct bond_dev_private *internals;
+ int ret;
+
+ ret = bond_check_primary(__func__, -1);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
@@ -1064,6 +1105,11 @@ rte_eth_bond_link_down_prop_delay_set(uint16_t bonding_port_id,
{
struct bond_dev_private *internals;
+ int ret;
+
+ ret = bond_check_primary(__func__, -1);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
@@ -1092,6 +1138,11 @@ rte_eth_bond_link_up_prop_delay_set(uint16_t bonding_port_id, uint32_t delay_ms)
{
struct bond_dev_private *internals;
+ int ret;
+
+ ret = bond_check_primary(__func__, -1);
+ if (ret != 0)
+ return ret;
if (valid_bonding_port_id(bonding_port_id) != 0)
return -1;
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 6a4f997b5a..b250d01445 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3644,6 +3644,15 @@ bond_ethdev_priv_dump(struct rte_eth_dev *dev, FILE *f)
return 0;
}
+static const struct eth_dev_ops secondary_dev_ops = {
+ .dev_close = bond_ethdev_close,
+ .dev_infos_get = bond_ethdev_info,
+ .link_update = bond_ethdev_link_update,
+ .stats_get = bond_ethdev_stats_get,
+ .reta_query = bond_ethdev_rss_reta_query,
+ .rss_hash_conf_get = bond_ethdev_rss_hash_conf_get,
+};
+
const struct eth_dev_ops default_dev_ops = {
.dev_start = bond_ethdev_start,
.dev_stop = bond_ethdev_stop,
@@ -3828,7 +3837,7 @@ bond_probe(struct rte_vdev_device *dev)
return -1;
}
- eth_dev->dev_ops = &default_dev_ops;
+ eth_dev->dev_ops = &secondary_dev_ops;
eth_dev->device = &dev->device;
/*
--
2.34.1
next prev parent reply other threads:[~2026-08-26 16:10 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-08 17:42 [RFC PATCH] net/bonding: reject control operations in secondary Weijun Pan
2026-07-22 23:10 ` Stephen Hemminger
2026-07-26 17:32 ` Stephen Hemminger
2026-08-23 15:16 ` [RFC PATCH v2] net/bonding: restrict secondary control operations Weijun Pan
2026-08-23 15:43 ` Stephen Hemminger
2026-08-24 2:39 ` Weijun Pan
2026-08-24 16:15 ` Stephen Hemminger
2026-08-26 16:10 ` Weijun Pan [this message]
2026-08-26 17:53 ` [RFC PATCH v3] " Stephen Hemminger
2026-08-30 1:14 ` [RFC PATCH v4 1/2] net/bonding: skip unavailable member stats Weijun Pan
2026-08-30 1:14 ` [RFC PATCH v4 2/2] net/bonding: restrict secondary control operations Weijun Pan
2026-08-30 4:29 ` Stephen Hemminger
2026-08-30 4:22 ` [RFC PATCH v4 1/2] net/bonding: skip unavailable member stats Stephen Hemminger
2026-08-30 16:35 ` [RFC PATCH v5 " Weijun Pan
2026-08-30 16:35 ` [RFC PATCH v5 2/2] net/bonding: restrict secondary control operations Weijun Pan
2026-08-30 20:23 ` [PATCH 0/8] net/bonding: fixes and per-member statistics Stephen Hemminger
2026-08-30 20:23 ` [PATCH 1/8] net/bonding: fix TLB member ordering with unusable member Stephen Hemminger
2026-08-30 20:23 ` [PATCH 2/8] net/bonding: skip unavailable member stats Stephen Hemminger
2026-08-30 20:23 ` [PATCH 3/8] net/bonding: skip unavailable members in device info Stephen Hemminger
2026-08-30 20:23 ` [PATCH 4/8] net/bonding: use atomic link status accessors Stephen Hemminger
2026-08-30 20:23 ` [PATCH 5/8] net/bonding: restrict control operations in secondary process Stephen Hemminger
2026-08-30 20:23 ` [PATCH 6/8] net/bonding: add extended statistics Stephen Hemminger
2026-08-30 20:23 ` [PATCH 7/8] test/bonding: add extended statistics test Stephen Hemminger
2026-08-30 20:23 ` [PATCH 8/8] doc: add bonding features matrix Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 0/8] net/bonding: fixes and per-member stats Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 1/8] net/bonding: fix TLB member ordering with unusable member Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 2/8] net/bonding: skip unavailable member stats Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 3/8] net/bonding: skip unavailable members in device info Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 4/8] net/bonding: use atomic link status accessors Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 5/8] net/bonding: restrict control ops in secondary process Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 6/8] net/bonding: add extended statistics Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 7/8] test/bonding: add extended statistics test Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 8/8] doc: add bonding features matrix Stephen Hemminger
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=20260826161009.37875-1-wpan3636@gmail.com \
--to=wpan3636@gmail.com \
--cc=3chas3@gmail.com \
--cc=anatoly.burakov@intel.com \
--cc=dev@dpdk.org \
--cc=humin29@huawei.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.