[PATCH 4/8] net/bonding: use atomic link status accessors

Stephen Hemminger stephen at networkplumber.org
Sun Aug 30 22:23:46 CEST 2026


The bonding PMD read and wrote rte_eth_dev_data.dev_link directly.
Since a struct rte_eth_link is a 64 bit value that may be updated concurrently
it needs to be done atomically. Use existing helpers.

Fixes: 2efb58cbab6e ("bond: new link bonding library")
Cc: stable at dpdk.org

Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
 drivers/net/bonding/rte_eth_bond_pmd.c | 84 ++++++++++++++++----------
 1 file changed, 51 insertions(+), 33 deletions(-)

diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 7579b97b06..6f3c13d6fb 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -1461,8 +1461,12 @@ link_properties_set(struct rte_eth_dev *ethdev, struct rte_eth_link *member_link
 		 * In any other mode the link properties are set to default
 		 * values of AUTONEG/DUPLEX
 		 */
-		ethdev->data->dev_link.link_autoneg = RTE_ETH_LINK_AUTONEG;
-		ethdev->data->dev_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+		struct rte_eth_link link;
+
+		rte_eth_linkstatus_get(ethdev, &link);
+		link.link_autoneg = RTE_ETH_LINK_AUTONEG;
+		link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+		rte_eth_linkstatus_set(ethdev, &link);
 	}
 }
 
@@ -2077,6 +2081,16 @@ bond_ethdev_primary_set(struct bond_dev_private *internals,
 static int
 bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev);
 
+static void
+bond_ethdev_link_down(struct rte_eth_dev *eth_dev)
+{
+	struct rte_eth_link link;
+
+	rte_eth_linkstatus_get(eth_dev, &link);
+	link.link_status = RTE_ETH_LINK_DOWN;
+	rte_eth_linkstatus_set(eth_dev, &link);
+}
+
 static int
 bond_ethdev_start(struct rte_eth_dev *eth_dev)
 {
@@ -2090,7 +2104,7 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev)
 		return -1;
 	}
 
-	eth_dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
+	bond_ethdev_link_down(eth_dev);
 	eth_dev->data->dev_started = 1;
 
 	internals = eth_dev->data->dev_private;
@@ -2242,7 +2256,7 @@ bond_ethdev_stop(struct rte_eth_dev *eth_dev)
 			tlb_last_obytets[internals->active_members[i]] = 0;
 	}
 
-	eth_dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
+	bond_ethdev_link_down(eth_dev);
 	eth_dev->data->dev_started = 0;
 
 	if (internals->link_status_polling_enabled) {
@@ -2537,6 +2551,7 @@ bond_ethdev_member_link_status_change_monitor(void *cb_arg)
 {
 	struct rte_eth_dev *bonding_ethdev, *member_ethdev;
 	struct bond_dev_private *internals;
+	struct rte_eth_link member_link;
 
 	/* Default value for polling member found is true as we don't want to
 	 * disable the polling thread if we cannot get the lock */
@@ -2569,9 +2584,11 @@ bond_ethdev_member_link_status_change_monitor(void *cb_arg)
 			member_ethdev->dev_ops->link_update(member_ethdev,
 					      internals->members[i].link_status_wait_to_complete);
 
+			rte_eth_linkstatus_get(member_ethdev, &member_link);
+
 			/* if link status has changed since last checked then call lsc
 			 * event callback */
-			if (member_ethdev->data->dev_link.link_status !=
+			if (member_link.link_status !=
 					internals->members[i].last_link_status) {
 				bond_ethdev_lsc_event_callback(internals->members[i].port_id,
 						RTE_ETH_EVENT_INTR_LSC,
@@ -2595,6 +2612,7 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 
 	struct bond_dev_private *bond_ctx;
 	struct rte_eth_link member_link;
+	struct rte_eth_link link;
 
 	bool one_link_update_succeeded;
 	uint32_t idx;
@@ -2602,15 +2620,17 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 
 	bond_ctx = ethdev->data->dev_private;
 
-	ethdev->data->dev_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
+	rte_eth_linkstatus_get(ethdev, &link);
+	link.link_speed = RTE_ETH_SPEED_NUM_NONE;
 
 	if (ethdev->data->dev_started == 0 ||
 			bond_ctx->active_member_count == 0) {
-		ethdev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
+		link.link_status = RTE_ETH_LINK_DOWN;
+		rte_eth_linkstatus_set(ethdev, &link);
 		return 0;
 	}
 
-	ethdev->data->dev_link.link_status = RTE_ETH_LINK_UP;
+	link.link_status = RTE_ETH_LINK_UP;
 
 	if (wait_to_complete)
 		link_update = rte_eth_link_get;
@@ -2623,7 +2643,7 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 		 * Setting link speed to UINT32_MAX to ensure we pick up the
 		 * value of the first active member
 		 */
-		ethdev->data->dev_link.link_speed = UINT32_MAX;
+		link.link_speed = UINT32_MAX;
 
 		/**
 		 * link speed is minimum value of all the members link speed as
@@ -2634,19 +2654,16 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 			ret = link_update(bond_ctx->active_members[idx],
 					  &member_link);
 			if (ret < 0) {
-				ethdev->data->dev_link.link_speed =
-					RTE_ETH_SPEED_NUM_NONE;
+				link.link_speed = RTE_ETH_SPEED_NUM_NONE;
 				RTE_BOND_LOG(ERR,
 					"Member (port %u) link get failed: %s",
 					bond_ctx->active_members[idx],
 					rte_strerror(-ret));
-				return 0;
+				goto done;
 			}
 
-			if (member_link.link_speed <
-					ethdev->data->dev_link.link_speed)
-				ethdev->data->dev_link.link_speed =
-						member_link.link_speed;
+			if (member_link.link_speed < link.link_speed)
+				link.link_speed = member_link.link_speed;
 		}
 		break;
 	case BONDING_MODE_ACTIVE_BACKUP:
@@ -2656,16 +2673,14 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 			RTE_BOND_LOG(ERR, "Member (port %u) link get failed: %s",
 				bond_ctx->current_primary_port,
 				rte_strerror(-ret));
-			return 0;
+			goto done;
 		}
 
-		ethdev->data->dev_link.link_speed = member_link.link_speed;
+		link.link_speed = member_link.link_speed;
 		break;
 	case BONDING_MODE_8023AD:
-		ethdev->data->dev_link.link_autoneg =
-				bond_ctx->mode4.member_link.link_autoneg;
-		ethdev->data->dev_link.link_duplex =
-				bond_ctx->mode4.member_link.link_duplex;
+		link.link_autoneg = bond_ctx->mode4.member_link.link_autoneg;
+		link.link_duplex = bond_ctx->mode4.member_link.link_duplex;
 		/* fall through */
 		/* to update link speed */
 	case BONDING_MODE_ROUND_ROBIN:
@@ -2677,7 +2692,7 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 		 * In theses mode the maximum theoretical link speed is the sum
 		 * of all the members
 		 */
-		ethdev->data->dev_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
+		link.link_speed = RTE_ETH_SPEED_NUM_NONE;
 		one_link_update_succeeded = false;
 
 		for (idx = 0; idx < bond_ctx->active_member_count; idx++) {
@@ -2692,16 +2707,15 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 			}
 
 			one_link_update_succeeded = true;
-			ethdev->data->dev_link.link_speed +=
-					member_link.link_speed;
+			link.link_speed += member_link.link_speed;
 		}
 
-		if (!one_link_update_succeeded) {
+		if (!one_link_update_succeeded)
 			RTE_BOND_LOG(ERR, "All members link get failed");
-			return 0;
-		}
 	}
 
+done:
+	rte_eth_linkstatus_set(ethdev, &link);
 
 	return 0;
 }
@@ -3069,7 +3083,7 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 {
 	struct rte_eth_dev *bonding_eth_dev;
 	struct bond_dev_private *internals;
-	struct rte_eth_link link;
+	struct rte_eth_link link, bond_link;
 	int rc = -1;
 	int ret;
 
@@ -3122,7 +3136,8 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 			goto link_update;
 
 		/* check link state properties if bonding link is up*/
-		if (bonding_eth_dev->data->dev_link.link_status == RTE_ETH_LINK_UP) {
+		rte_eth_linkstatus_get(bonding_eth_dev, &bond_link);
+		if (bond_link.link_status == RTE_ETH_LINK_UP) {
 			if (link_properties_valid(bonding_eth_dev, &link) != 0)
 				RTE_BOND_LOG(ERR, "Invalid link properties "
 					     "for member %d in bonding mode %d",
@@ -3137,8 +3152,10 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 		 */
 		if (internals->active_member_count < 1) {
 			/* If first active member, then change link status */
-			bonding_eth_dev->data->dev_link.link_status =
-								RTE_ETH_LINK_UP;
+			rte_eth_linkstatus_get(bonding_eth_dev, &bond_link);
+			bond_link.link_status = RTE_ETH_LINK_UP;
+			rte_eth_linkstatus_set(bonding_eth_dev, &bond_link);
+
 			internals->current_primary_port = port_id;
 			lsc_flag = 1;
 
@@ -3194,7 +3211,8 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 			rte_eal_alarm_cancel(bond_ethdev_delayed_lsc_propagation,
 					bonding_eth_dev);
 
-		if (bonding_eth_dev->data->dev_link.link_status) {
+		rte_eth_linkstatus_get(bonding_eth_dev, &bond_link);
+		if (bond_link.link_status) {
 			if (internals->link_up_delay_ms > 0)
 				rte_eal_alarm_set(internals->link_up_delay_ms * 1000,
 						bond_ethdev_delayed_lsc_propagation,
-- 
2.53.0



More information about the dev mailing list