* [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