Netdev List
 help / color / mirror / Atom feed
* [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I)
@ 2026-06-03  6:20 Eric Dumazet
  2026-06-03  6:20 ` [PATCH v2 net-next 01/11] bridge: add a READ_ONCE() in br_timer_value() Eric Dumazet
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

medium-term goal is to allow "ip link show" dump commands to run without RTNL.

This round of patches adds/fixes some lockess accesses in bridge.

This is not complete, more patches will come later.

Ultimately all changes to p->flags should use set_bit()/clear_bit().

v2: addressed Ido's feedback (patches 5 & 6).

Eric Dumazet (11):
  bridge: add a READ_ONCE() in br_timer_value()
  bridge: add bridge_flags_bit enum
  bridge: use BR_PROMISC_BIT
  bridge: use BR_ADMIN_COST_BIT
  bridge: provide lockless access to p->path_cost
  bridge: provide lockless access to p->designated_cost
  bridge: provide lockless access to p->designated_port
  bridge: provide lockless access to p->priority
  bridge: provide lockless access to p->port_id
  bridge: provide lockless access to p->config_pending
  bridge: read p->flags once in br_port_fill_attrs()

 include/linux/if_bridge.h | 78 ++++++++++++++++++++++++++-------------
 net/bridge/br_if.c        |  8 ++--
 net/bridge/br_ioctl.c     | 10 ++---
 net/bridge/br_netlink.c   | 55 ++++++++++++++-------------
 net/bridge/br_private.h   |  2 +-
 net/bridge/br_stp.c       | 45 +++++++++++++---------
 net/bridge/br_stp_if.c    | 16 ++++----
 net/bridge/br_stp_timer.c |  2 +-
 net/bridge/br_sysfs_if.c  | 12 +++---
 9 files changed, 134 insertions(+), 94 deletions(-)

-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 01/11] bridge: add a READ_ONCE() in br_timer_value()
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:42   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 02/11] bridge: add bridge_flags_bit enum Eric Dumazet
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

br_timer_value() can be called locklessly, the expires field
could be changed concurrently.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 net/bridge/br_stp_timer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index e5d453305381baa34225a144ac99e98f2a62d810..83cc9c6a3943508eb94d20ddc1b7e737a58d7abb 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -160,5 +160,5 @@ void br_stp_port_timer_init(struct net_bridge_port *p)
 unsigned long br_timer_value(const struct timer_list *timer)
 {
 	return timer_pending(timer)
-		? jiffies_delta_to_clock_t(timer->expires - jiffies) : 0;
+		? jiffies_delta_to_clock_t(READ_ONCE(timer->expires) - jiffies) : 0;
 }
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 02/11] bridge: add bridge_flags_bit enum
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
  2026-06-03  6:20 ` [PATCH v2 net-next 01/11] bridge: add a READ_ONCE() in br_timer_value() Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:42   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 03/11] bridge: use BR_PROMISC_BIT Eric Dumazet
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

We want to use atomic operations for lockless p->flags changes
and reads.

Add definitions for bits in addition of masks so that we can use
test_bit(), clear_bit() and set_bit() in subsequent patches.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 include/linux/if_bridge.h | 78 ++++++++++++++++++++++++++-------------
 1 file changed, 53 insertions(+), 25 deletions(-)

diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index ec9ffea1e46ede3762f108f6e7085ebb1bf1d2e1..75673b8bffcb8ad6396e6a05b8af8150208fb6fe 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -36,32 +36,60 @@ struct br_ip_list {
 	struct br_ip addr;
 };
 
-#define BR_HAIRPIN_MODE		BIT(0)
-#define BR_BPDU_GUARD		BIT(1)
-#define BR_ROOT_BLOCK		BIT(2)
-#define BR_MULTICAST_FAST_LEAVE	BIT(3)
-#define BR_ADMIN_COST		BIT(4)
-#define BR_LEARNING		BIT(5)
-#define BR_FLOOD		BIT(6)
+enum bridge_flags_bit {
+	BR_HAIRPIN_MODE_BIT,
+	BR_BPDU_GUARD_BIT,
+	BR_ROOT_BLOCK_BIT,
+	BR_MULTICAST_FAST_LEAVE_BIT,
+	BR_ADMIN_COST_BIT,
+	BR_LEARNING_BIT,
+	BR_FLOOD_BIT,
+	BR_PROMISC_BIT,
+	BR_PROXYARP_BIT,
+	BR_LEARNING_SYNC_BIT,
+	BR_PROXYARP_WIFI_BIT,
+	BR_MCAST_FLOOD_BIT,
+	BR_MULTICAST_TO_UNICAST_BIT,
+	BR_VLAN_TUNNEL_BIT,
+	BR_BCAST_FLOOD_BIT,
+	BR_NEIGH_SUPPRESS_BIT,
+	BR_ISOLATED_BIT,
+	BR_MRP_AWARE_BIT,
+	BR_MRP_LOST_CONT_BIT,
+	BR_MRP_LOST_IN_CONT_BIT,
+	BR_TX_FWD_OFFLOAD_BIT,
+	BR_PORT_LOCKED_BIT,
+	BR_PORT_MAB_BIT,
+	BR_NEIGH_VLAN_SUPPRESS_BIT,
+	BR_NEIGH_FORWARD_GRAT_BIT,
+};
+
+#define BR_HAIRPIN_MODE		BIT(BR_HAIRPIN_MODE_BIT)
+#define BR_BPDU_GUARD		BIT(BR_BPDU_GUARD_BIT)
+#define BR_ROOT_BLOCK		BIT(BR_ROOT_BLOCK_BIT)
+#define BR_MULTICAST_FAST_LEAVE	BIT(BR_MULTICAST_FAST_LEAVE_BIT)
+#define BR_ADMIN_COST		BIT(BR_ADMIN_COST_BIT)
+#define BR_LEARNING		BIT(BR_LEARNING_BIT)
+#define BR_FLOOD		BIT(BR_FLOOD_BIT)
 #define BR_AUTO_MASK		(BR_FLOOD | BR_LEARNING)
-#define BR_PROMISC		BIT(7)
-#define BR_PROXYARP		BIT(8)
-#define BR_LEARNING_SYNC	BIT(9)
-#define BR_PROXYARP_WIFI	BIT(10)
-#define BR_MCAST_FLOOD		BIT(11)
-#define BR_MULTICAST_TO_UNICAST	BIT(12)
-#define BR_VLAN_TUNNEL		BIT(13)
-#define BR_BCAST_FLOOD		BIT(14)
-#define BR_NEIGH_SUPPRESS	BIT(15)
-#define BR_ISOLATED		BIT(16)
-#define BR_MRP_AWARE		BIT(17)
-#define BR_MRP_LOST_CONT	BIT(18)
-#define BR_MRP_LOST_IN_CONT	BIT(19)
-#define BR_TX_FWD_OFFLOAD	BIT(20)
-#define BR_PORT_LOCKED		BIT(21)
-#define BR_PORT_MAB		BIT(22)
-#define BR_NEIGH_VLAN_SUPPRESS	BIT(23)
-#define BR_NEIGH_FORWARD_GRAT	BIT(24)
+#define BR_PROMISC		BIT(BR_PROMISC_BIT)
+#define BR_PROXYARP		BIT(BR_PROXYARP_BIT)
+#define BR_LEARNING_SYNC	BIT(BR_LEARNING_SYNC_BIT)
+#define BR_PROXYARP_WIFI	BIT(BR_PROXYARP_WIFI_BIT)
+#define BR_MCAST_FLOOD		BIT(BR_MCAST_FLOOD_BIT)
+#define BR_MULTICAST_TO_UNICAST	BIT(BR_MULTICAST_TO_UNICAST_BIT)
+#define BR_VLAN_TUNNEL		BIT(BR_VLAN_TUNNEL_BIT)
+#define BR_BCAST_FLOOD		BIT(BR_BCAST_FLOOD_BIT)
+#define BR_NEIGH_SUPPRESS	BIT(BR_NEIGH_SUPPRESS_BIT)
+#define BR_ISOLATED		BIT(BR_ISOLATED_BIT)
+#define BR_MRP_AWARE		BIT(BR_MRP_AWARE_BIT)
+#define BR_MRP_LOST_CONT	BIT(BR_MRP_LOST_CONT_BIT)
+#define BR_MRP_LOST_IN_CONT	BIT(BR_MRP_LOST_IN_CONT_BIT)
+#define BR_TX_FWD_OFFLOAD	BIT(BR_TX_FWD_OFFLOAD_BIT)
+#define BR_PORT_LOCKED		BIT(BR_PORT_LOCKED_BIT)
+#define BR_PORT_MAB		BIT(BR_PORT_MAB_BIT)
+#define BR_NEIGH_VLAN_SUPPRESS	BIT(BR_NEIGH_VLAN_SUPPRESS_BIT)
+#define BR_NEIGH_FORWARD_GRAT	BIT(BR_NEIGH_FORWARD_GRAT_BIT)
 
 #define BR_DEFAULT_AGEING_TIME	(300 * HZ)
 
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 03/11] bridge: use BR_PROMISC_BIT
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
  2026-06-03  6:20 ` [PATCH v2 net-next 01/11] bridge: add a READ_ONCE() in br_timer_value() Eric Dumazet
  2026-06-03  6:20 ` [PATCH v2 net-next 02/11] bridge: add bridge_flags_bit enum Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:42   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 04/11] bridge: use BR_ADMIN_COST_BIT Eric Dumazet
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

Use BR_PROMISC_BIT and set_bit(), clear_bit() and test_bit() lockless
functions.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 net/bridge/br_if.c      | 4 ++--
 net/bridge/br_private.h | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index d39571e13744431f5e4c67f34ee7de34eb8bb6b0..3169fab686a534cf2a6458ff228eee2b6fc7e7e4 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -110,7 +110,7 @@ static void br_port_set_promisc(struct net_bridge_port *p)
 		return;
 
 	br_fdb_unsync_static(p->br, p);
-	p->flags |= BR_PROMISC;
+	set_bit(BR_PROMISC_BIT, &p->flags);
 }
 
 static void br_port_clear_promisc(struct net_bridge_port *p)
@@ -133,7 +133,7 @@ static void br_port_clear_promisc(struct net_bridge_port *p)
 		return;
 
 	dev_set_promiscuity(p->dev, -1);
-	p->flags &= ~BR_PROMISC;
+	clear_bit(BR_PROMISC_BIT, &p->flags);
 }
 
 /* When a port is added or removed or when certain port flags
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 02671e648dac7ab6fd59b80e044f62b00a8e4a8a..d55ea9516e3e369bb9e0045fca5b8d034ef5a45f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -452,7 +452,7 @@ struct net_bridge_port {
 #define kobj_to_brport(obj)	container_of(obj, struct net_bridge_port, kobj)
 
 #define br_auto_port(p) ((p)->flags & BR_AUTO_MASK)
-#define br_promisc_port(p) ((p)->flags & BR_PROMISC)
+#define br_promisc_port(p) test_bit(BR_PROMISC_BIT, &(p)->flags)
 
 static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
 {
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 04/11] bridge: use BR_ADMIN_COST_BIT
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
                   ` (2 preceding siblings ...)
  2026-06-03  6:20 ` [PATCH v2 net-next 03/11] bridge: use BR_PROMISC_BIT Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:43   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 05/11] bridge: provide lockless access to p->path_cost Eric Dumazet
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

Use set_bit() and test_bit() lockless functions.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 net/bridge/br_if.c     | 2 +-
 net/bridge/br_stp_if.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 3169fab686a534cf2a6458ff228eee2b6fc7e7e4..0bd5cf925fa321b785e3578d6e99d8d7003fa89f 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -75,7 +75,7 @@ void br_port_carrier_check(struct net_bridge_port *p, bool *notified)
 	struct net_device *dev = p->dev;
 	struct net_bridge *br = p->br;
 
-	if (!(p->flags & BR_ADMIN_COST) &&
+	if (!test_bit(BR_ADMIN_COST_BIT, &p->flags) &&
 	    netif_running(dev) && netif_oper_up(dev))
 		p->path_cost = port_cost(dev);
 
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 28c1d3f7e22f6e0a0edd8b3b3f501ea7acc31394..b29dc97b9ad8a5b5c56517d34fe426abd00e2ad6 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -340,7 +340,7 @@ int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost)
 	    path_cost > BR_MAX_PATH_COST)
 		return -ERANGE;
 
-	p->flags |= BR_ADMIN_COST;
+	set_bit(BR_ADMIN_COST_BIT, &p->flags);
 	p->path_cost = path_cost;
 	br_configuration_update(p->br);
 	br_port_state_selection(p->br);
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 05/11] bridge: provide lockless access to p->path_cost
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
                   ` (3 preceding siblings ...)
  2026-06-03  6:20 ` [PATCH v2 net-next 04/11] bridge: use BR_ADMIN_COST_BIT Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:44   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 06/11] bridge: provide lockless access to p->designated_cost Eric Dumazet
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

Add READ_ONCE()/WRITE_ONCE() annotations around p->path_cost.

This is needed at least for sysfs show_path_cost(), BRCTL_GET_PORT_INFO
and upcoming RTNL avoidance in "ip link" dumps (cf br_port_fill_attrs()).

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/bridge/br_if.c       |  2 +-
 net/bridge/br_ioctl.c    |  2 +-
 net/bridge/br_netlink.c  |  2 +-
 net/bridge/br_stp.c      | 17 +++++++++++------
 net/bridge/br_stp_if.c   |  2 +-
 net/bridge/br_sysfs_if.c |  2 +-
 6 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 0bd5cf925fa321b785e3578d6e99d8d7003fa89f..ab012e4762998fe8a133dd551e7f4f0efc6718c6 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -77,7 +77,7 @@ void br_port_carrier_check(struct net_bridge_port *p, bool *notified)
 
 	if (!test_bit(BR_ADMIN_COST_BIT, &p->flags) &&
 	    netif_running(dev) && netif_oper_up(dev))
-		p->path_cost = port_cost(dev);
+		WRITE_ONCE(p->path_cost, port_cost(dev));
 
 	*notified = false;
 	if (!netif_running(br->dev))
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 766c43b327af830a80fba11c940ba34eb03c50c9..07cfcb821e27ebcb72901a365a3f06491f8b0bc3 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -259,7 +259,7 @@ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
 		memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
 		p.port_id = pt->port_id;
 		p.designated_port = pt->designated_port;
-		p.path_cost = pt->path_cost;
+		p.path_cost = READ_ONCE(pt->path_cost);
 		p.designated_cost = pt->designated_cost;
 		p.state = pt->state;
 		p.top_change_ack = pt->topology_change_ack;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index a104b25c871d263e4b5701f1be05cb17fbfce28f..08718ebe282aa1d089a127cdc7c24fda5a0a38a5 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -240,7 +240,7 @@ static int br_port_fill_attrs(struct sk_buff *skb,
 
 	if (nla_put_u8(skb, IFLA_BRPORT_STATE, p->state) ||
 	    nla_put_u16(skb, IFLA_BRPORT_PRIORITY, p->priority) ||
-	    nla_put_u32(skb, IFLA_BRPORT_COST, p->path_cost) ||
+	    nla_put_u32(skb, IFLA_BRPORT_COST, READ_ONCE(p->path_cost)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_MODE, mode) ||
 	    nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_PROTECT,
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 024210f95468308066827ac2ae71f68f99fa77f5..2d9d0823aa56b63a62ed51c49df54055294e82ad 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -102,8 +102,9 @@ struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no)
 static int br_should_become_root_port(const struct net_bridge_port *p,
 				      u16 root_port)
 {
-	struct net_bridge *br;
+	u32 p_path_cost, rp_path_cost;
 	struct net_bridge_port *rp;
+	struct net_bridge *br;
 	int t;
 
 	br = p->br;
@@ -125,11 +126,14 @@ static int br_should_become_root_port(const struct net_bridge_port *p,
 	else if (t > 0)
 		return 0;
 
-	if (p->designated_cost + p->path_cost <
-	    rp->designated_cost + rp->path_cost)
+	p_path_cost = READ_ONCE(p->path_cost);
+	rp_path_cost = READ_ONCE(rp->path_cost);
+
+	if (p->designated_cost + p_path_cost <
+	    rp->designated_cost + rp_path_cost)
 		return 1;
-	else if (p->designated_cost + p->path_cost >
-		 rp->designated_cost + rp->path_cost)
+	else if (p->designated_cost + p_path_cost >
+		 rp->designated_cost + rp_path_cost)
 		return 0;
 
 	t = memcmp(&p->designated_bridge, &rp->designated_bridge, 8);
@@ -187,7 +191,8 @@ static void br_root_selection(struct net_bridge *br)
 	} else {
 		p = br_get_port(br, root_port);
 		br->designated_root = p->designated_root;
-		br->root_path_cost = p->designated_cost + p->path_cost;
+		br->root_path_cost = p->designated_cost +
+				     READ_ONCE(p->path_cost);
 	}
 }
 
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index b29dc97b9ad8a5b5c56517d34fe426abd00e2ad6..e5d43492d2dcf0615ee984bc190d7ce2264aaab0 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -341,7 +341,7 @@ int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost)
 		return -ERANGE;
 
 	set_bit(BR_ADMIN_COST_BIT, &p->flags);
-	p->path_cost = path_cost;
+	WRITE_ONCE(p->path_cost, path_cost);
 	br_configuration_update(p->br);
 	br_port_state_selection(p->br);
 	return 0;
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index d6df81fa0d13fe7e732b69f881b947da2066d9ef..23574476d7f701080452777ab2c23a42b4defba4 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -83,7 +83,7 @@ static int store_flag(struct net_bridge_port *p, unsigned long v,
 
 static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
 {
-	return sysfs_emit(buf, "%d\n", p->path_cost);
+	return sysfs_emit(buf, "%d\n", READ_ONCE(p->path_cost));
 }
 
 static int store_path_cost(struct net_bridge_port *p, unsigned long v)
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 06/11] bridge: provide lockless access to p->designated_cost
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
                   ` (4 preceding siblings ...)
  2026-06-03  6:20 ` [PATCH v2 net-next 05/11] bridge: provide lockless access to p->path_cost Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:46   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 07/11] bridge: provide lockless access to p->designated_port Eric Dumazet
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

Add READ_ONCE()/WRITE_ONCE() annotations around p->designated_cost

This is needed at least for sysfs show_designated_cost(), BRCTL_GET_PORT_INFO
and upcoming RTNL avoidance in "ip link" dumps (cf br_port_fill_attrs()).

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/bridge/br_ioctl.c    |  2 +-
 net/bridge/br_netlink.c  |  3 ++-
 net/bridge/br_stp.c      | 28 ++++++++++++++++------------
 net/bridge/br_sysfs_if.c |  2 +-
 4 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 07cfcb821e27ebcb72901a365a3f06491f8b0bc3..a507c7b369ac49803019cdca7836c7fb9ef4459e 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -260,7 +260,7 @@ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
 		p.port_id = pt->port_id;
 		p.designated_port = pt->designated_port;
 		p.path_cost = READ_ONCE(pt->path_cost);
-		p.designated_cost = pt->designated_cost;
+		p.designated_cost = READ_ONCE(pt->designated_cost);
 		p.state = pt->state;
 		p.top_change_ack = pt->topology_change_ack;
 		p.config_pending = pt->config_pending;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 08718ebe282aa1d089a127cdc7c24fda5a0a38a5..296f62ebdd4a6f3d404b5902fe661995bd1ca0f5 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -264,7 +264,8 @@ static int br_port_fill_attrs(struct sk_buff *skb,
 	    nla_put(skb, IFLA_BRPORT_BRIDGE_ID, sizeof(struct ifla_bridge_id),
 		    &p->designated_bridge) ||
 	    nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_PORT, p->designated_port) ||
-	    nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_COST, p->designated_cost) ||
+	    nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_COST,
+			READ_ONCE(p->designated_cost)) ||
 	    nla_put_u16(skb, IFLA_BRPORT_ID, p->port_id) ||
 	    nla_put_u16(skb, IFLA_BRPORT_NO, p->port_no) ||
 	    nla_put_u8(skb, IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 2d9d0823aa56b63a62ed51c49df54055294e82ad..88da86a6ba4406ac77d0b13e0a340e87e281c11a 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -102,7 +102,7 @@ struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no)
 static int br_should_become_root_port(const struct net_bridge_port *p,
 				      u16 root_port)
 {
-	u32 p_path_cost, rp_path_cost;
+	u32 p_path_cost, rp_path_cost, p_designated_cost, rp_designated_cost;
 	struct net_bridge_port *rp;
 	struct net_bridge *br;
 	int t;
@@ -128,12 +128,14 @@ static int br_should_become_root_port(const struct net_bridge_port *p,
 
 	p_path_cost = READ_ONCE(p->path_cost);
 	rp_path_cost = READ_ONCE(rp->path_cost);
+	p_designated_cost = READ_ONCE(p->designated_cost);
+	rp_designated_cost = READ_ONCE(rp->designated_cost);
 
-	if (p->designated_cost + p_path_cost <
-	    rp->designated_cost + rp_path_cost)
+	if (p_designated_cost + p_path_cost <
+	    rp_designated_cost + rp_path_cost)
 		return 1;
-	else if (p->designated_cost + p_path_cost >
-		 rp->designated_cost + rp_path_cost)
+	else if (p_designated_cost + p_path_cost >
+		 rp_designated_cost + rp_path_cost)
 		return 0;
 
 	t = memcmp(&p->designated_bridge, &rp->designated_bridge, 8);
@@ -191,7 +193,7 @@ static void br_root_selection(struct net_bridge *br)
 	} else {
 		p = br_get_port(br, root_port);
 		br->designated_root = p->designated_root;
-		br->root_path_cost = p->designated_cost +
+		br->root_path_cost = READ_ONCE(p->designated_cost) +
 				     READ_ONCE(p->path_cost);
 	}
 }
@@ -257,7 +259,7 @@ static void br_record_config_information(struct net_bridge_port *p,
 					 const struct br_config_bpdu *bpdu)
 {
 	p->designated_root = bpdu->root;
-	p->designated_cost = bpdu->root_path_cost;
+	WRITE_ONCE(p->designated_cost, bpdu->root_path_cost);
 	p->designated_bridge = bpdu->bridge_id;
 	p->designated_port = bpdu->port_id;
 	p->designated_age = jiffies - bpdu->message_age;
@@ -302,9 +304,10 @@ static int br_should_become_designated_port(const struct net_bridge_port *p)
 	if (memcmp(&p->designated_root, &br->designated_root, 8))
 		return 1;
 
-	if (br->root_path_cost < p->designated_cost)
+	t = br->root_path_cost - READ_ONCE(p->designated_cost);
+	if (t < 0)
 		return 1;
-	else if (br->root_path_cost > p->designated_cost)
+	else if (t > 0)
 		return 0;
 
 	t = memcmp(&br->bridge_id, &p->designated_bridge, 8);
@@ -344,9 +347,10 @@ static int br_supersedes_port_info(const struct net_bridge_port *p,
 	else if (t > 0)
 		return 0;
 
-	if (bpdu->root_path_cost < p->designated_cost)
+	t = bpdu->root_path_cost < READ_ONCE(p->designated_cost);
+	if (t < 0)
 		return 1;
-	else if (bpdu->root_path_cost > p->designated_cost)
+	else if (t > 0)
 		return 0;
 
 	t = memcmp(&bpdu->bridge_id, &p->designated_bridge, 8);
@@ -426,7 +430,7 @@ void br_become_designated_port(struct net_bridge_port *p)
 
 	br = p->br;
 	p->designated_root = br->designated_root;
-	p->designated_cost = br->root_path_cost;
+	WRITE_ONCE(p->designated_cost, br->root_path_cost);
 	p->designated_bridge = br->bridge_id;
 	p->designated_port = p->port_id;
 }
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 23574476d7f701080452777ab2c23a42b4defba4..36b832902d33a492e91d53a4248778b3ee2322ca 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -135,7 +135,7 @@ static BRPORT_ATTR(designated_port, 0444, show_designated_port, NULL);
 
 static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf)
 {
-	return sysfs_emit(buf, "%d\n", p->designated_cost);
+	return sysfs_emit(buf, "%d\n", READ_ONCE(p->designated_cost));
 }
 static BRPORT_ATTR(designated_cost, 0444, show_designated_cost, NULL);
 
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 07/11] bridge: provide lockless access to p->designated_port
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
                   ` (5 preceding siblings ...)
  2026-06-03  6:20 ` [PATCH v2 net-next 06/11] bridge: provide lockless access to p->designated_cost Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:47   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 08/11] bridge: provide lockless access to p->priority Eric Dumazet
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

Add READ_ONCE()/WRITE_ONCE() annotations around p->designated_port

This is needed at least for sysfs show_designated_port(), BRCTL_GET_PORT_INFO
and upcoming RTNL avoidance in "ip link" dumps (cf br_port_fill_attrs()).

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 net/bridge/br_ioctl.c    | 2 +-
 net/bridge/br_netlink.c  | 3 ++-
 net/bridge/br_stp.c      | 4 ++--
 net/bridge/br_stp_if.c   | 2 +-
 net/bridge/br_sysfs_if.c | 2 +-
 5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index a507c7b369ac49803019cdca7836c7fb9ef4459e..2be802991f70ab3ce48ade5da6d1488e072dbec6 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -258,7 +258,7 @@ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
 		memcpy(&p.designated_root, &pt->designated_root, 8);
 		memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
 		p.port_id = pt->port_id;
-		p.designated_port = pt->designated_port;
+		p.designated_port = READ_ONCE(pt->designated_port);
 		p.path_cost = READ_ONCE(pt->path_cost);
 		p.designated_cost = READ_ONCE(pt->designated_cost);
 		p.state = pt->state;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 296f62ebdd4a6f3d404b5902fe661995bd1ca0f5..a722db89aef6bbb6ecc77c7e0f173dc79418797f 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -263,7 +263,8 @@ static int br_port_fill_attrs(struct sk_buff *skb,
 		    &p->designated_root) ||
 	    nla_put(skb, IFLA_BRPORT_BRIDGE_ID, sizeof(struct ifla_bridge_id),
 		    &p->designated_bridge) ||
-	    nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_PORT, p->designated_port) ||
+	    nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_PORT,
+			READ_ONCE(p->designated_port)) ||
 	    nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_COST,
 			READ_ONCE(p->designated_cost)) ||
 	    nla_put_u16(skb, IFLA_BRPORT_ID, p->port_id) ||
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 88da86a6ba4406ac77d0b13e0a340e87e281c11a..f5ea14bb8fb865045d50fb09296d0db466e8fc6e 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -261,7 +261,7 @@ static void br_record_config_information(struct net_bridge_port *p,
 	p->designated_root = bpdu->root;
 	WRITE_ONCE(p->designated_cost, bpdu->root_path_cost);
 	p->designated_bridge = bpdu->bridge_id;
-	p->designated_port = bpdu->port_id;
+	WRITE_ONCE(p->designated_port, bpdu->port_id);
 	p->designated_age = jiffies - bpdu->message_age;
 
 	mod_timer(&p->message_age_timer, jiffies
@@ -432,7 +432,7 @@ void br_become_designated_port(struct net_bridge_port *p)
 	p->designated_root = br->designated_root;
 	WRITE_ONCE(p->designated_cost, br->root_path_cost);
 	p->designated_bridge = br->bridge_id;
-	p->designated_port = p->port_id;
+	WRITE_ONCE(p->designated_port, p->port_id);
 }
 
 
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index e5d43492d2dcf0615ee984bc190d7ce2264aaab0..7b0d1a334785047905a00694fd65e3212b160e5d 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -320,7 +320,7 @@ int br_stp_set_port_priority(struct net_bridge_port *p, unsigned long newprio)
 
 	new_port_id = br_make_port_id(newprio, p->port_no);
 	if (br_is_designated_port(p))
-		p->designated_port = new_port_id;
+		WRITE_ONCE(p->designated_port, new_port_id);
 
 	p->port_id = new_port_id;
 	p->priority = newprio;
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 36b832902d33a492e91d53a4248778b3ee2322ca..1023f97b1c9a22a1f79c3c734aef9bd41832ea39 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -129,7 +129,7 @@ static BRPORT_ATTR(designated_bridge, 0444, show_designated_bridge, NULL);
 
 static ssize_t show_designated_port(struct net_bridge_port *p, char *buf)
 {
-	return sysfs_emit(buf, "%d\n", p->designated_port);
+	return sysfs_emit(buf, "%d\n", READ_ONCE(p->designated_port));
 }
 static BRPORT_ATTR(designated_port, 0444, show_designated_port, NULL);
 
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 08/11] bridge: provide lockless access to p->priority
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
                   ` (6 preceding siblings ...)
  2026-06-03  6:20 ` [PATCH v2 net-next 07/11] bridge: provide lockless access to p->designated_port Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:49   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 09/11] bridge: provide lockless access to p->port_id Eric Dumazet
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

sysfs show_priority() needs this.

Also br_port_fill_attrs() might in the future run without RTNL.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 net/bridge/br_netlink.c  | 2 +-
 net/bridge/br_stp_if.c   | 2 +-
 net/bridge/br_sysfs_if.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index a722db89aef6bbb6ecc77c7e0f173dc79418797f..fc25c6b6cc9713080873976f443da1fbd764aafe 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -239,7 +239,7 @@ static int br_port_fill_attrs(struct sk_buff *skb,
 	u64 timerval;
 
 	if (nla_put_u8(skb, IFLA_BRPORT_STATE, p->state) ||
-	    nla_put_u16(skb, IFLA_BRPORT_PRIORITY, p->priority) ||
+	    nla_put_u16(skb, IFLA_BRPORT_PRIORITY, READ_ONCE(p->priority)) ||
 	    nla_put_u32(skb, IFLA_BRPORT_COST, READ_ONCE(p->path_cost)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_MODE, mode) ||
 	    nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) ||
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 7b0d1a334785047905a00694fd65e3212b160e5d..3524bb7e87f0586774a883720be9fa8eb60f0370 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -323,7 +323,7 @@ int br_stp_set_port_priority(struct net_bridge_port *p, unsigned long newprio)
 		WRITE_ONCE(p->designated_port, new_port_id);
 
 	p->port_id = new_port_id;
-	p->priority = newprio;
+	WRITE_ONCE(p->priority, newprio);
 	if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) &&
 	    p->port_id < p->designated_port) {
 		br_become_designated_port(p);
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 1023f97b1c9a22a1f79c3c734aef9bd41832ea39..3f666d4fef42324a4751779153ecc48bdb44b85a 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -100,7 +100,7 @@ static BRPORT_ATTR(path_cost, 0644, show_path_cost, store_path_cost);
 
 static ssize_t show_priority(struct net_bridge_port *p, char *buf)
 {
-	return sysfs_emit(buf, "%d\n", p->priority);
+	return sysfs_emit(buf, "%d\n", READ_ONCE(p->priority));
 }
 
 static int store_priority(struct net_bridge_port *p, unsigned long v)
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 09/11] bridge: provide lockless access to p->port_id
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
                   ` (7 preceding siblings ...)
  2026-06-03  6:20 ` [PATCH v2 net-next 08/11] bridge: provide lockless access to p->priority Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:50   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 10/11] bridge: provide lockless access to p->config_pending Eric Dumazet
  2026-06-03  6:20 ` [PATCH v2 net-next 11/11] bridge: read p->flags once in br_port_fill_attrs() Eric Dumazet
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

sysfs show_port_id() and BRCTL_GET_PORT_INFO need this.

This will be needed for upcoming RTNL avoidance in "ip link"
dumps (cf br_port_fill_attrs()).

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 net/bridge/br_ioctl.c    | 2 +-
 net/bridge/br_netlink.c  | 2 +-
 net/bridge/br_stp_if.c   | 4 ++--
 net/bridge/br_sysfs_if.c | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 2be802991f70ab3ce48ade5da6d1488e072dbec6..a017374c6e659498d98c6af3f8d8e46a8b93570e 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -257,7 +257,7 @@ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
 		memset(&p, 0, sizeof(struct __port_info));
 		memcpy(&p.designated_root, &pt->designated_root, 8);
 		memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
-		p.port_id = pt->port_id;
+		p.port_id = READ_ONCE(pt->port_id);
 		p.designated_port = READ_ONCE(pt->designated_port);
 		p.path_cost = READ_ONCE(pt->path_cost);
 		p.designated_cost = READ_ONCE(pt->designated_cost);
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index fc25c6b6cc9713080873976f443da1fbd764aafe..f8266a7a9e2b910f1b4e08792b2940ae0fd2bba2 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -267,7 +267,7 @@ static int br_port_fill_attrs(struct sk_buff *skb,
 			READ_ONCE(p->designated_port)) ||
 	    nla_put_u16(skb, IFLA_BRPORT_DESIGNATED_COST,
 			READ_ONCE(p->designated_cost)) ||
-	    nla_put_u16(skb, IFLA_BRPORT_ID, p->port_id) ||
+	    nla_put_u16(skb, IFLA_BRPORT_ID, READ_ONCE(p->port_id)) ||
 	    nla_put_u16(skb, IFLA_BRPORT_NO, p->port_no) ||
 	    nla_put_u8(skb, IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
 		       p->topology_change_ack) ||
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 3524bb7e87f0586774a883720be9fa8eb60f0370..8a418f6af423ccba88fae57d2254e35e1ae4a1a0 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -34,7 +34,7 @@ void br_init_port(struct net_bridge_port *p)
 {
 	int err;
 
-	p->port_id = br_make_port_id(p->priority, p->port_no);
+	WRITE_ONCE(p->port_id, br_make_port_id(p->priority, p->port_no));
 	br_become_designated_port(p);
 	br_set_state(p, BR_STATE_BLOCKING);
 	p->topology_change_ack = 0;
@@ -322,7 +322,7 @@ int br_stp_set_port_priority(struct net_bridge_port *p, unsigned long newprio)
 	if (br_is_designated_port(p))
 		WRITE_ONCE(p->designated_port, new_port_id);
 
-	p->port_id = new_port_id;
+	WRITE_ONCE(p->port_id, new_port_id);
 	WRITE_ONCE(p->priority, newprio);
 	if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) &&
 	    p->port_id < p->designated_port) {
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 3f666d4fef42324a4751779153ecc48bdb44b85a..1cc474ed0fdc02234a9f9d6b936247c34cbb127d 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -141,7 +141,7 @@ static BRPORT_ATTR(designated_cost, 0444, show_designated_cost, NULL);
 
 static ssize_t show_port_id(struct net_bridge_port *p, char *buf)
 {
-	return sysfs_emit(buf, "0x%x\n", p->port_id);
+	return sysfs_emit(buf, "0x%x\n", READ_ONCE(p->port_id));
 }
 static BRPORT_ATTR(port_id, 0444, show_port_id, NULL);
 
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 10/11] bridge: provide lockless access to p->config_pending
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
                   ` (8 preceding siblings ...)
  2026-06-03  6:20 ` [PATCH v2 net-next 09/11] bridge: provide lockless access to p->port_id Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:51   ` Nikolay Aleksandrov
  2026-06-03  6:20 ` [PATCH v2 net-next 11/11] bridge: read p->flags once in br_port_fill_attrs() Eric Dumazet
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

Needed for sysfs show_config_pending(), BRCTL_GET_PORT_INFO
and upcoming RTNL avoidance in "ip link" dumps (cf br_port_fill_attrs()).

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 net/bridge/br_ioctl.c    | 2 +-
 net/bridge/br_netlink.c  | 2 +-
 net/bridge/br_stp.c      | 8 ++++----
 net/bridge/br_stp_if.c   | 4 ++--
 net/bridge/br_sysfs_if.c | 2 +-
 5 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index a017374c6e659498d98c6af3f8d8e46a8b93570e..39f3ffcfa2d33f15cec6e61490100925eefc7e68 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -263,7 +263,7 @@ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
 		p.designated_cost = READ_ONCE(pt->designated_cost);
 		p.state = pt->state;
 		p.top_change_ack = pt->topology_change_ack;
-		p.config_pending = pt->config_pending;
+		p.config_pending = READ_ONCE(pt->config_pending);
 		p.message_age_timer_value = br_timer_value(&pt->message_age_timer);
 		p.forward_delay_timer_value = br_timer_value(&pt->forward_delay_timer);
 		p.hold_timer_value = br_timer_value(&pt->hold_timer);
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index f8266a7a9e2b910f1b4e08792b2940ae0fd2bba2..ead66dbe1bb7679af18d5f0c2fdea6be2574727d 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -271,7 +271,7 @@ static int br_port_fill_attrs(struct sk_buff *skb,
 	    nla_put_u16(skb, IFLA_BRPORT_NO, p->port_no) ||
 	    nla_put_u8(skb, IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
 		       p->topology_change_ack) ||
-	    nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, p->config_pending) ||
+	    nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, READ_ONCE(p->config_pending)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(p->flags &
 							BR_VLAN_TUNNEL)) ||
 	    nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask) ||
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index f5ea14bb8fb865045d50fb09296d0db466e8fc6e..f84e0389ab9d4c95d0123b926e1a12b0dbc83f93 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -220,7 +220,7 @@ void br_transmit_config(struct net_bridge_port *p)
 	struct net_bridge *br;
 
 	if (timer_pending(&p->hold_timer)) {
-		p->config_pending = 1;
+		WRITE_ONCE(p->config_pending, 1);
 		return;
 	}
 
@@ -247,7 +247,7 @@ void br_transmit_config(struct net_bridge_port *p)
 	if (bpdu.message_age < br->max_age) {
 		br_send_config_bpdu(p, &bpdu);
 		p->topology_change_ack = 0;
-		p->config_pending = 0;
+		WRITE_ONCE(p->config_pending, 0);
 		if (p->br->stp_enabled == BR_KERNEL_STP)
 			mod_timer(&p->hold_timer,
 				  round_jiffies(jiffies + BR_HOLD_TIME));
@@ -488,14 +488,14 @@ void br_port_state_selection(struct net_bridge *br)
 		/* Don't change port states if userspace is handling STP */
 		if (br->stp_enabled != BR_USER_STP) {
 			if (p->port_no == br->root_port) {
-				p->config_pending = 0;
+				WRITE_ONCE(p->config_pending, 0);
 				p->topology_change_ack = 0;
 				br_make_forwarding(p);
 			} else if (br_is_designated_port(p)) {
 				timer_delete(&p->message_age_timer);
 				br_make_forwarding(p);
 			} else {
-				p->config_pending = 0;
+				WRITE_ONCE(p->config_pending, 0);
 				p->topology_change_ack = 0;
 				br_make_blocking(p);
 			}
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 8a418f6af423ccba88fae57d2254e35e1ae4a1a0..a7e5422eb5d140b501a7dcebf0238d5a77c5f4a1 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -38,7 +38,7 @@ void br_init_port(struct net_bridge_port *p)
 	br_become_designated_port(p);
 	br_set_state(p, BR_STATE_BLOCKING);
 	p->topology_change_ack = 0;
-	p->config_pending = 0;
+	WRITE_ONCE(p->config_pending, 0);
 
 	err = __set_ageing_time(p->dev, p->br->ageing_time);
 	if (err)
@@ -105,7 +105,7 @@ void br_stp_disable_port(struct net_bridge_port *p)
 	br_become_designated_port(p);
 	br_set_state(p, BR_STATE_DISABLED);
 	p->topology_change_ack = 0;
-	p->config_pending = 0;
+	WRITE_ONCE(p->config_pending, 0);
 
 	br_ifinfo_notify(RTM_NEWLINK, NULL, p);
 
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 1cc474ed0fdc02234a9f9d6b936247c34cbb127d..1923c004f0d2b746902f5b6de1bbb72f7f824125 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -160,7 +160,7 @@ static BRPORT_ATTR(change_ack, 0444, show_change_ack, NULL);
 
 static ssize_t show_config_pending(struct net_bridge_port *p, char *buf)
 {
-	return sysfs_emit(buf, "%d\n", p->config_pending);
+	return sysfs_emit(buf, "%d\n", READ_ONCE(p->config_pending));
 }
 static BRPORT_ATTR(config_pending, 0444, show_config_pending, NULL);
 
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v2 net-next 11/11] bridge: read p->flags once in br_port_fill_attrs()
  2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
                   ` (9 preceding siblings ...)
  2026-06-03  6:20 ` [PATCH v2 net-next 10/11] bridge: provide lockless access to p->config_pending Eric Dumazet
@ 2026-06-03  6:20 ` Eric Dumazet
  2026-06-03  7:52   ` Nikolay Aleksandrov
  10 siblings, 1 reply; 23+ messages in thread
From: Eric Dumazet @ 2026-06-03  6:20 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, Nikolay Aleksandrov, netdev,
	eric.dumazet, Eric Dumazet

We might run br_port_fill_attrs() locklessly in the future.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 net/bridge/br_netlink.c | 41 +++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index ead66dbe1bb7679af18d5f0c2fdea6be2574727d..7cb24de9c77d3d15892723f77288c27a15a6a0ad 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -234,7 +234,8 @@ static inline size_t br_nlmsg_size(struct net_device *dev, u32 filter_mask)
 static int br_port_fill_attrs(struct sk_buff *skb,
 			      const struct net_bridge_port *p)
 {
-	u8 mode = !!(p->flags & BR_HAIRPIN_MODE);
+	unsigned long flags = READ_ONCE(p->flags);
+	u8 mode = !!(flags & BR_HAIRPIN_MODE);
 	struct net_bridge_port *backup_p;
 	u64 timerval;
 
@@ -242,23 +243,23 @@ static int br_port_fill_attrs(struct sk_buff *skb,
 	    nla_put_u16(skb, IFLA_BRPORT_PRIORITY, READ_ONCE(p->priority)) ||
 	    nla_put_u32(skb, IFLA_BRPORT_COST, READ_ONCE(p->path_cost)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_MODE, mode) ||
-	    nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) ||
+	    nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(flags & BR_BPDU_GUARD)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_PROTECT,
-		       !!(p->flags & BR_ROOT_BLOCK)) ||
+		       !!(flags & BR_ROOT_BLOCK)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE,
-		       !!(p->flags & BR_MULTICAST_FAST_LEAVE)) ||
+		       !!(flags & BR_MULTICAST_FAST_LEAVE)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_MCAST_TO_UCAST,
-		       !!(p->flags & BR_MULTICAST_TO_UNICAST)) ||
-	    nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) ||
+		       !!(flags & BR_MULTICAST_TO_UNICAST)) ||
+	    nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(flags & BR_LEARNING)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
-		       !!(p->flags & BR_FLOOD)) ||
+		       !!(flags & BR_FLOOD)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_MCAST_FLOOD,
-		       !!(p->flags & BR_MCAST_FLOOD)) ||
+		       !!(flags & BR_MCAST_FLOOD)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_BCAST_FLOOD,
-		       !!(p->flags & BR_BCAST_FLOOD)) ||
-	    nla_put_u8(skb, IFLA_BRPORT_PROXYARP, !!(p->flags & BR_PROXYARP)) ||
+		       !!(flags & BR_BCAST_FLOOD)) ||
+	    nla_put_u8(skb, IFLA_BRPORT_PROXYARP, !!(flags & BR_PROXYARP)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_PROXYARP_WIFI,
-		       !!(p->flags & BR_PROXYARP_WIFI)) ||
+		       !!(flags & BR_PROXYARP_WIFI)) ||
 	    nla_put(skb, IFLA_BRPORT_ROOT_ID, sizeof(struct ifla_bridge_id),
 		    &p->designated_root) ||
 	    nla_put(skb, IFLA_BRPORT_BRIDGE_ID, sizeof(struct ifla_bridge_id),
@@ -272,22 +273,22 @@ static int br_port_fill_attrs(struct sk_buff *skb,
 	    nla_put_u8(skb, IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
 		       p->topology_change_ack) ||
 	    nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, READ_ONCE(p->config_pending)) ||
-	    nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(p->flags &
+	    nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(flags &
 							BR_VLAN_TUNNEL)) ||
 	    nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask) ||
 	    nla_put_u8(skb, IFLA_BRPORT_NEIGH_SUPPRESS,
-		       !!(p->flags & BR_NEIGH_SUPPRESS)) ||
-	    nla_put_u8(skb, IFLA_BRPORT_MRP_RING_OPEN, !!(p->flags &
+		       !!(flags & BR_NEIGH_SUPPRESS)) ||
+	    nla_put_u8(skb, IFLA_BRPORT_MRP_RING_OPEN, !!(flags &
 							  BR_MRP_LOST_CONT)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_MRP_IN_OPEN,
-		       !!(p->flags & BR_MRP_LOST_IN_CONT)) ||
-	    nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(p->flags & BR_ISOLATED)) ||
-	    nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(p->flags & BR_PORT_LOCKED)) ||
-	    nla_put_u8(skb, IFLA_BRPORT_MAB, !!(p->flags & BR_PORT_MAB)) ||
+		       !!(flags & BR_MRP_LOST_IN_CONT)) ||
+	    nla_put_u8(skb, IFLA_BRPORT_ISOLATED, !!(flags & BR_ISOLATED)) ||
+	    nla_put_u8(skb, IFLA_BRPORT_LOCKED, !!(flags & BR_PORT_LOCKED)) ||
+	    nla_put_u8(skb, IFLA_BRPORT_MAB, !!(flags & BR_PORT_MAB)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
-		       !!(p->flags & BR_NEIGH_VLAN_SUPPRESS)) ||
+		       !!(flags & BR_NEIGH_VLAN_SUPPRESS)) ||
 	    nla_put_u8(skb, IFLA_BRPORT_NEIGH_FORWARD_GRAT,
-		       !!(p->flags & BR_NEIGH_FORWARD_GRAT)))
+		       !!(flags & BR_NEIGH_FORWARD_GRAT)))
 		return -EMSGSIZE;
 
 	timerval = br_timer_value(&p->message_age_timer);
-- 
2.54.0.1013.g208068f2d8-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 01/11] bridge: add a READ_ONCE() in br_timer_value()
  2026-06-03  6:20 ` [PATCH v2 net-next 01/11] bridge: add a READ_ONCE() in br_timer_value() Eric Dumazet
@ 2026-06-03  7:42   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:42 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> br_timer_value() can be called locklessly, the expires field
> could be changed concurrently.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
>   net/bridge/br_stp_timer.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
> index e5d453305381baa34225a144ac99e98f2a62d810..83cc9c6a3943508eb94d20ddc1b7e737a58d7abb 100644
> --- a/net/bridge/br_stp_timer.c
> +++ b/net/bridge/br_stp_timer.c
> @@ -160,5 +160,5 @@ void br_stp_port_timer_init(struct net_bridge_port *p)
>   unsigned long br_timer_value(const struct timer_list *timer)
>   {
>   	return timer_pending(timer)
> -		? jiffies_delta_to_clock_t(timer->expires - jiffies) : 0;
> +		? jiffies_delta_to_clock_t(READ_ONCE(timer->expires) - jiffies) : 0;
>   }

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 02/11] bridge: add bridge_flags_bit enum
  2026-06-03  6:20 ` [PATCH v2 net-next 02/11] bridge: add bridge_flags_bit enum Eric Dumazet
@ 2026-06-03  7:42   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:42 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> We want to use atomic operations for lockless p->flags changes
> and reads.
> 
> Add definitions for bits in addition of masks so that we can use
> test_bit(), clear_bit() and set_bit() in subsequent patches.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
>   include/linux/if_bridge.h | 78 ++++++++++++++++++++++++++-------------
>   1 file changed, 53 insertions(+), 25 deletions(-)
> 
> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
> index ec9ffea1e46ede3762f108f6e7085ebb1bf1d2e1..75673b8bffcb8ad6396e6a05b8af8150208fb6fe 100644
> --- a/include/linux/if_bridge.h
> +++ b/include/linux/if_bridge.h
> @@ -36,32 +36,60 @@ struct br_ip_list {
>   	struct br_ip addr;
>   };
>   
> -#define BR_HAIRPIN_MODE		BIT(0)
> -#define BR_BPDU_GUARD		BIT(1)
> -#define BR_ROOT_BLOCK		BIT(2)
> -#define BR_MULTICAST_FAST_LEAVE	BIT(3)
> -#define BR_ADMIN_COST		BIT(4)
> -#define BR_LEARNING		BIT(5)
> -#define BR_FLOOD		BIT(6)
> +enum bridge_flags_bit {
> +	BR_HAIRPIN_MODE_BIT,
> +	BR_BPDU_GUARD_BIT,
> +	BR_ROOT_BLOCK_BIT,
> +	BR_MULTICAST_FAST_LEAVE_BIT,
> +	BR_ADMIN_COST_BIT,
> +	BR_LEARNING_BIT,
> +	BR_FLOOD_BIT,
> +	BR_PROMISC_BIT,
> +	BR_PROXYARP_BIT,
> +	BR_LEARNING_SYNC_BIT,
> +	BR_PROXYARP_WIFI_BIT,
> +	BR_MCAST_FLOOD_BIT,
> +	BR_MULTICAST_TO_UNICAST_BIT,
> +	BR_VLAN_TUNNEL_BIT,
> +	BR_BCAST_FLOOD_BIT,
> +	BR_NEIGH_SUPPRESS_BIT,
> +	BR_ISOLATED_BIT,
> +	BR_MRP_AWARE_BIT,
> +	BR_MRP_LOST_CONT_BIT,
> +	BR_MRP_LOST_IN_CONT_BIT,
> +	BR_TX_FWD_OFFLOAD_BIT,
> +	BR_PORT_LOCKED_BIT,
> +	BR_PORT_MAB_BIT,
> +	BR_NEIGH_VLAN_SUPPRESS_BIT,
> +	BR_NEIGH_FORWARD_GRAT_BIT,
> +};
> +
> +#define BR_HAIRPIN_MODE		BIT(BR_HAIRPIN_MODE_BIT)
> +#define BR_BPDU_GUARD		BIT(BR_BPDU_GUARD_BIT)
> +#define BR_ROOT_BLOCK		BIT(BR_ROOT_BLOCK_BIT)
> +#define BR_MULTICAST_FAST_LEAVE	BIT(BR_MULTICAST_FAST_LEAVE_BIT)
> +#define BR_ADMIN_COST		BIT(BR_ADMIN_COST_BIT)
> +#define BR_LEARNING		BIT(BR_LEARNING_BIT)
> +#define BR_FLOOD		BIT(BR_FLOOD_BIT)
>   #define BR_AUTO_MASK		(BR_FLOOD | BR_LEARNING)
> -#define BR_PROMISC		BIT(7)
> -#define BR_PROXYARP		BIT(8)
> -#define BR_LEARNING_SYNC	BIT(9)
> -#define BR_PROXYARP_WIFI	BIT(10)
> -#define BR_MCAST_FLOOD		BIT(11)
> -#define BR_MULTICAST_TO_UNICAST	BIT(12)
> -#define BR_VLAN_TUNNEL		BIT(13)
> -#define BR_BCAST_FLOOD		BIT(14)
> -#define BR_NEIGH_SUPPRESS	BIT(15)
> -#define BR_ISOLATED		BIT(16)
> -#define BR_MRP_AWARE		BIT(17)
> -#define BR_MRP_LOST_CONT	BIT(18)
> -#define BR_MRP_LOST_IN_CONT	BIT(19)
> -#define BR_TX_FWD_OFFLOAD	BIT(20)
> -#define BR_PORT_LOCKED		BIT(21)
> -#define BR_PORT_MAB		BIT(22)
> -#define BR_NEIGH_VLAN_SUPPRESS	BIT(23)
> -#define BR_NEIGH_FORWARD_GRAT	BIT(24)
> +#define BR_PROMISC		BIT(BR_PROMISC_BIT)
> +#define BR_PROXYARP		BIT(BR_PROXYARP_BIT)
> +#define BR_LEARNING_SYNC	BIT(BR_LEARNING_SYNC_BIT)
> +#define BR_PROXYARP_WIFI	BIT(BR_PROXYARP_WIFI_BIT)
> +#define BR_MCAST_FLOOD		BIT(BR_MCAST_FLOOD_BIT)
> +#define BR_MULTICAST_TO_UNICAST	BIT(BR_MULTICAST_TO_UNICAST_BIT)
> +#define BR_VLAN_TUNNEL		BIT(BR_VLAN_TUNNEL_BIT)
> +#define BR_BCAST_FLOOD		BIT(BR_BCAST_FLOOD_BIT)
> +#define BR_NEIGH_SUPPRESS	BIT(BR_NEIGH_SUPPRESS_BIT)
> +#define BR_ISOLATED		BIT(BR_ISOLATED_BIT)
> +#define BR_MRP_AWARE		BIT(BR_MRP_AWARE_BIT)
> +#define BR_MRP_LOST_CONT	BIT(BR_MRP_LOST_CONT_BIT)
> +#define BR_MRP_LOST_IN_CONT	BIT(BR_MRP_LOST_IN_CONT_BIT)
> +#define BR_TX_FWD_OFFLOAD	BIT(BR_TX_FWD_OFFLOAD_BIT)
> +#define BR_PORT_LOCKED		BIT(BR_PORT_LOCKED_BIT)
> +#define BR_PORT_MAB		BIT(BR_PORT_MAB_BIT)
> +#define BR_NEIGH_VLAN_SUPPRESS	BIT(BR_NEIGH_VLAN_SUPPRESS_BIT)
> +#define BR_NEIGH_FORWARD_GRAT	BIT(BR_NEIGH_FORWARD_GRAT_BIT)
>   
>   #define BR_DEFAULT_AGEING_TIME	(300 * HZ)
>   

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 03/11] bridge: use BR_PROMISC_BIT
  2026-06-03  6:20 ` [PATCH v2 net-next 03/11] bridge: use BR_PROMISC_BIT Eric Dumazet
@ 2026-06-03  7:42   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:42 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> Use BR_PROMISC_BIT and set_bit(), clear_bit() and test_bit() lockless
> functions.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
>   net/bridge/br_if.c      | 4 ++--
>   net/bridge/br_private.h | 2 +-
>   2 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
> index d39571e13744431f5e4c67f34ee7de34eb8bb6b0..3169fab686a534cf2a6458ff228eee2b6fc7e7e4 100644
> --- a/net/bridge/br_if.c
> +++ b/net/bridge/br_if.c
> @@ -110,7 +110,7 @@ static void br_port_set_promisc(struct net_bridge_port *p)
>   		return;
>   
>   	br_fdb_unsync_static(p->br, p);
> -	p->flags |= BR_PROMISC;
> +	set_bit(BR_PROMISC_BIT, &p->flags);
>   }
>   
>   static void br_port_clear_promisc(struct net_bridge_port *p)
> @@ -133,7 +133,7 @@ static void br_port_clear_promisc(struct net_bridge_port *p)
>   		return;
>   
>   	dev_set_promiscuity(p->dev, -1);
> -	p->flags &= ~BR_PROMISC;
> +	clear_bit(BR_PROMISC_BIT, &p->flags);
>   }
>   
>   /* When a port is added or removed or when certain port flags
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 02671e648dac7ab6fd59b80e044f62b00a8e4a8a..d55ea9516e3e369bb9e0045fca5b8d034ef5a45f 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -452,7 +452,7 @@ struct net_bridge_port {
>   #define kobj_to_brport(obj)	container_of(obj, struct net_bridge_port, kobj)
>   
>   #define br_auto_port(p) ((p)->flags & BR_AUTO_MASK)
> -#define br_promisc_port(p) ((p)->flags & BR_PROMISC)
> +#define br_promisc_port(p) test_bit(BR_PROMISC_BIT, &(p)->flags)
>   
>   static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
>   {

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 04/11] bridge: use BR_ADMIN_COST_BIT
  2026-06-03  6:20 ` [PATCH v2 net-next 04/11] bridge: use BR_ADMIN_COST_BIT Eric Dumazet
@ 2026-06-03  7:43   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:43 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> Use set_bit() and test_bit() lockless functions.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
>   net/bridge/br_if.c     | 2 +-
>   net/bridge/br_stp_if.c | 2 +-
>   2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
> index 3169fab686a534cf2a6458ff228eee2b6fc7e7e4..0bd5cf925fa321b785e3578d6e99d8d7003fa89f 100644
> --- a/net/bridge/br_if.c
> +++ b/net/bridge/br_if.c
> @@ -75,7 +75,7 @@ void br_port_carrier_check(struct net_bridge_port *p, bool *notified)
>   	struct net_device *dev = p->dev;
>   	struct net_bridge *br = p->br;
>   
> -	if (!(p->flags & BR_ADMIN_COST) &&
> +	if (!test_bit(BR_ADMIN_COST_BIT, &p->flags) &&
>   	    netif_running(dev) && netif_oper_up(dev))
>   		p->path_cost = port_cost(dev);
>   
> diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
> index 28c1d3f7e22f6e0a0edd8b3b3f501ea7acc31394..b29dc97b9ad8a5b5c56517d34fe426abd00e2ad6 100644
> --- a/net/bridge/br_stp_if.c
> +++ b/net/bridge/br_stp_if.c
> @@ -340,7 +340,7 @@ int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost)
>   	    path_cost > BR_MAX_PATH_COST)
>   		return -ERANGE;
>   
> -	p->flags |= BR_ADMIN_COST;
> +	set_bit(BR_ADMIN_COST_BIT, &p->flags);
>   	p->path_cost = path_cost;
>   	br_configuration_update(p->br);
>   	br_port_state_selection(p->br);

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 05/11] bridge: provide lockless access to p->path_cost
  2026-06-03  6:20 ` [PATCH v2 net-next 05/11] bridge: provide lockless access to p->path_cost Eric Dumazet
@ 2026-06-03  7:44   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:44 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> Add READ_ONCE()/WRITE_ONCE() annotations around p->path_cost.
> 
> This is needed at least for sysfs show_path_cost(), BRCTL_GET_PORT_INFO
> and upcoming RTNL avoidance in "ip link" dumps (cf br_port_fill_attrs()).
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
>   net/bridge/br_if.c       |  2 +-
>   net/bridge/br_ioctl.c    |  2 +-
>   net/bridge/br_netlink.c  |  2 +-
>   net/bridge/br_stp.c      | 17 +++++++++++------
>   net/bridge/br_stp_if.c   |  2 +-
>   net/bridge/br_sysfs_if.c |  2 +-
>   6 files changed, 16 insertions(+), 11 deletions(-)
> 

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 06/11] bridge: provide lockless access to p->designated_cost
  2026-06-03  6:20 ` [PATCH v2 net-next 06/11] bridge: provide lockless access to p->designated_cost Eric Dumazet
@ 2026-06-03  7:46   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:46 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> Add READ_ONCE()/WRITE_ONCE() annotations around p->designated_cost
> 
> This is needed at least for sysfs show_designated_cost(), BRCTL_GET_PORT_INFO
> and upcoming RTNL avoidance in "ip link" dumps (cf br_port_fill_attrs()).
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
>   net/bridge/br_ioctl.c    |  2 +-
>   net/bridge/br_netlink.c  |  3 ++-
>   net/bridge/br_stp.c      | 28 ++++++++++++++++------------
>   net/bridge/br_sysfs_if.c |  2 +-
>   4 files changed, 20 insertions(+), 15 deletions(-)
> 

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 07/11] bridge: provide lockless access to p->designated_port
  2026-06-03  6:20 ` [PATCH v2 net-next 07/11] bridge: provide lockless access to p->designated_port Eric Dumazet
@ 2026-06-03  7:47   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:47 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> Add READ_ONCE()/WRITE_ONCE() annotations around p->designated_port
> 
> This is needed at least for sysfs show_designated_port(), BRCTL_GET_PORT_INFO
> and upcoming RTNL avoidance in "ip link" dumps (cf br_port_fill_attrs()).
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
>   net/bridge/br_ioctl.c    | 2 +-
>   net/bridge/br_netlink.c  | 3 ++-
>   net/bridge/br_stp.c      | 4 ++--
>   net/bridge/br_stp_if.c   | 2 +-
>   net/bridge/br_sysfs_if.c | 2 +-
>   5 files changed, 7 insertions(+), 6 deletions(-)
> 

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 08/11] bridge: provide lockless access to p->priority
  2026-06-03  6:20 ` [PATCH v2 net-next 08/11] bridge: provide lockless access to p->priority Eric Dumazet
@ 2026-06-03  7:49   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:49 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> sysfs show_priority() needs this.
> 
> Also br_port_fill_attrs() might in the future run without RTNL.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
>   net/bridge/br_netlink.c  | 2 +-
>   net/bridge/br_stp_if.c   | 2 +-
>   net/bridge/br_sysfs_if.c | 2 +-
>   3 files changed, 3 insertions(+), 3 deletions(-)
> 

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 09/11] bridge: provide lockless access to p->port_id
  2026-06-03  6:20 ` [PATCH v2 net-next 09/11] bridge: provide lockless access to p->port_id Eric Dumazet
@ 2026-06-03  7:50   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:50 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> sysfs show_port_id() and BRCTL_GET_PORT_INFO need this.
> 
> This will be needed for upcoming RTNL avoidance in "ip link"
> dumps (cf br_port_fill_attrs()).
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
>   net/bridge/br_ioctl.c    | 2 +-
>   net/bridge/br_netlink.c  | 2 +-
>   net/bridge/br_stp_if.c   | 4 ++--
>   net/bridge/br_sysfs_if.c | 2 +-
>   4 files changed, 5 insertions(+), 5 deletions(-)
> 

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 10/11] bridge: provide lockless access to p->config_pending
  2026-06-03  6:20 ` [PATCH v2 net-next 10/11] bridge: provide lockless access to p->config_pending Eric Dumazet
@ 2026-06-03  7:51   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:51 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> Needed for sysfs show_config_pending(), BRCTL_GET_PORT_INFO
> and upcoming RTNL avoidance in "ip link" dumps (cf br_port_fill_attrs()).
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
>   net/bridge/br_ioctl.c    | 2 +-
>   net/bridge/br_netlink.c  | 2 +-
>   net/bridge/br_stp.c      | 8 ++++----
>   net/bridge/br_stp_if.c   | 4 ++--
>   net/bridge/br_sysfs_if.c | 2 +-
>   5 files changed, 9 insertions(+), 9 deletions(-)
> 

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 net-next 11/11] bridge: read p->flags once in br_port_fill_attrs()
  2026-06-03  6:20 ` [PATCH v2 net-next 11/11] bridge: read p->flags once in br_port_fill_attrs() Eric Dumazet
@ 2026-06-03  7:52   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 23+ messages in thread
From: Nikolay Aleksandrov @ 2026-06-03  7:52 UTC (permalink / raw)
  To: Eric Dumazet, David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Ido Schimmel, netdev, eric.dumazet

On 03/06/2026 09:20, Eric Dumazet wrote:
> We might run br_port_fill_attrs() locklessly in the future.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
> ---
>   net/bridge/br_netlink.c | 41 +++++++++++++++++++++--------------------
>   1 file changed, 21 insertions(+), 20 deletions(-)
> 

Acked-by: Nikolay Aleksandrov <razor@blackwall.org>


^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2026-06-03  7:53 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-03  6:20 [PATCH v2 net-next 00/11] bridge: prepare lockless br_port_fill_attrs() (I) Eric Dumazet
2026-06-03  6:20 ` [PATCH v2 net-next 01/11] bridge: add a READ_ONCE() in br_timer_value() Eric Dumazet
2026-06-03  7:42   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 02/11] bridge: add bridge_flags_bit enum Eric Dumazet
2026-06-03  7:42   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 03/11] bridge: use BR_PROMISC_BIT Eric Dumazet
2026-06-03  7:42   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 04/11] bridge: use BR_ADMIN_COST_BIT Eric Dumazet
2026-06-03  7:43   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 05/11] bridge: provide lockless access to p->path_cost Eric Dumazet
2026-06-03  7:44   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 06/11] bridge: provide lockless access to p->designated_cost Eric Dumazet
2026-06-03  7:46   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 07/11] bridge: provide lockless access to p->designated_port Eric Dumazet
2026-06-03  7:47   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 08/11] bridge: provide lockless access to p->priority Eric Dumazet
2026-06-03  7:49   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 09/11] bridge: provide lockless access to p->port_id Eric Dumazet
2026-06-03  7:50   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 10/11] bridge: provide lockless access to p->config_pending Eric Dumazet
2026-06-03  7:51   ` Nikolay Aleksandrov
2026-06-03  6:20 ` [PATCH v2 net-next 11/11] bridge: read p->flags once in br_port_fill_attrs() Eric Dumazet
2026-06-03  7:52   ` Nikolay Aleksandrov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox