Merge branch 'net-bridge-take-care-of-p-flags-accesses'

Eric Dumazet says:

====================
net: bridge: take care of p->flags accesses

(struct net_bridge_port)->flags can be read/written locklessly,
and thus can fire KCSAN warnings, or real bugs.

Prefer atomic operations (test_bit(), clear_bit(), set_bit())
and use READ_ONCE() for the remaining uses.
====================

Link: https://patch.msgid.link/20260611203453.3067462-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-06-12 18:03:48 -07:00
commit 0f20e8eda0
14 changed files with 132 additions and 123 deletions

View File

@ -29,7 +29,7 @@ void br_recalculate_neigh_suppress_enabled(struct net_bridge *br)
bool neigh_suppress = false;
list_for_each_entry(p, &br->port_list, list) {
if (p->flags & (BR_NEIGH_SUPPRESS | BR_NEIGH_VLAN_SUPPRESS)) {
if (READ_ONCE(p->flags) & (BR_NEIGH_SUPPRESS | BR_NEIGH_VLAN_SUPPRESS)) {
neigh_suppress = true;
break;
}
@ -206,8 +206,8 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
const struct net_bridge_port *dst = READ_ONCE(f->dst);
bool replied = false;
if ((p && (p->flags & BR_PROXYARP)) ||
(dst && (dst->flags & BR_PROXYARP_WIFI)) ||
if ((p && test_bit(BR_PROXYARP_BIT, &p->flags)) ||
(dst && test_bit(BR_PROXYARP_WIFI_BIT, &dst->flags)) ||
br_is_neigh_suppress_enabled(dst, vid)) {
if (!vid)
br_arp_send(br, p, skb->dev, sip, tip,
@ -511,10 +511,7 @@ bool br_is_neigh_suppress_enabled(const struct net_bridge_port *p, u16 vid)
if (!p)
return false;
if (!vid)
return !!(p->flags & BR_NEIGH_SUPPRESS);
if (p->flags & BR_NEIGH_VLAN_SUPPRESS) {
if (vid && test_bit(BR_NEIGH_VLAN_SUPPRESS_BIT, &p->flags)) {
struct net_bridge_vlan_group *vg = nbp_vlan_group_rcu(p);
struct net_bridge_vlan *v;
@ -522,17 +519,13 @@ bool br_is_neigh_suppress_enabled(const struct net_bridge_port *p, u16 vid)
if (!v)
return false;
return !!(v->priv_flags & BR_VLFLAG_NEIGH_SUPPRESS_ENABLED);
} else {
return !!(p->flags & BR_NEIGH_SUPPRESS);
}
return test_bit(BR_NEIGH_SUPPRESS_BIT, &p->flags);
}
bool br_is_neigh_forward_grat_enabled(const struct net_bridge_port *p, u16 vid)
{
if (!vid)
return !!(p->flags & BR_NEIGH_FORWARD_GRAT);
if (p->flags & BR_NEIGH_VLAN_SUPPRESS) {
if (vid && test_bit(BR_NEIGH_VLAN_SUPPRESS_BIT, &p->flags)) {
struct net_bridge_vlan_group *vg = nbp_vlan_group_rcu(p);
struct net_bridge_vlan *v;
@ -540,7 +533,6 @@ bool br_is_neigh_forward_grat_enabled(const struct net_bridge_port *p, u16 vid)
if (!v)
return false;
return !!(v->priv_flags & BR_VLFLAG_NEIGH_FORWARD_GRAT_ENABLED);
} else {
return !!(p->flags & BR_NEIGH_FORWARD_GRAT);
}
return test_bit(BR_NEIGH_FORWARD_GRAT_BIT, &p->flags);
}

View File

@ -1514,7 +1514,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
trace_br_fdb_external_learn_add(br, p, addr, vid);
if (locked && (!p || !(p->flags & BR_PORT_MAB)))
if (locked && (!p || !test_bit(BR_PORT_MAB_BIT, &p->flags)))
return -EINVAL;
spin_lock_bh(&br->hash_lock);

View File

@ -24,7 +24,7 @@ static inline int should_deliver(const struct net_bridge_port *p,
struct net_bridge_vlan_group *vg;
vg = nbp_vlan_group_rcu(p);
return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
return (test_bit(BR_HAIRPIN_MODE_BIT, &p->flags) || skb->dev != p->dev) &&
(br_mst_is_enabled(p) || p->state == BR_STATE_FORWARDING) &&
br_allowed_egress(vg, skb) && nbp_switchdev_allowed_egress(p, skb) &&
!br_skb_isolated(p, skb);
@ -214,24 +214,24 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
*/
switch (pkt_type) {
case BR_PKT_UNICAST:
if (!(p->flags & BR_FLOOD))
if (!test_bit(BR_FLOOD_BIT, &p->flags))
continue;
break;
case BR_PKT_MULTICAST:
if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev)
if (!test_bit(BR_MCAST_FLOOD_BIT, &p->flags) && skb->dev != br->dev)
continue;
break;
case BR_PKT_BROADCAST:
if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev)
if (!test_bit(BR_BCAST_FLOOD_BIT, &p->flags) && skb->dev != br->dev)
continue;
break;
}
/* Do not flood to ports that enable proxy ARP */
if (p->flags & BR_PROXYARP)
if (test_bit(BR_PROXYARP_BIT, &p->flags))
continue;
if (BR_INPUT_SKB_CB(skb)->proxyarp_replied) {
if (p->flags & BR_PROXYARP_WIFI)
if (test_bit(BR_PROXYARP_WIFI_BIT, &p->flags))
continue;
/* For gratuitous ARPs/NAs, check neigh_forward_grat.
* For regular ARPs/NDs, check only neigh_suppress.
@ -328,7 +328,8 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
if ((unsigned long)lport > (unsigned long)rport) {
port = lport;
if (port->flags & BR_MULTICAST_TO_UNICAST) {
if (test_bit(BR_MULTICAST_TO_UNICAST_BIT,
&port->flags)) {
maybe_deliver_addr(lport, skb, p->eth_addr,
local_orig);
goto delivered;

View File

@ -761,6 +761,6 @@ bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag)
if (!p)
return false;
return p->flags & flag;
return READ_ONCE(p->flags) & flag;
}
EXPORT_SYMBOL_GPL(br_port_flag_is_set);

View File

@ -111,7 +111,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
&state, &vlan))
goto out;
if (p->flags & BR_PORT_LOCKED) {
if (test_bit(BR_PORT_LOCKED_BIT, &p->flags)) {
struct net_bridge_fdb_entry *fdb_src =
br_fdb_find_rcu(br, eth_hdr(skb)->h_source, vid);
@ -119,7 +119,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
/* FDB miss. Create locked FDB entry if MAB is enabled
* and drop the packet.
*/
if (p->flags & BR_PORT_MAB)
if (test_bit(BR_PORT_MAB_BIT, &p->flags))
br_fdb_update(br, p, eth_hdr(skb)->h_source,
vid, BIT(BR_FDB_LOCKED));
goto drop;
@ -140,7 +140,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
nbp_switchdev_frame_mark(p, skb);
/* insert into forwarding database after filtering to avoid spoofing */
if (p->flags & BR_LEARNING)
if (test_bit(BR_LEARNING_BIT, &p->flags))
br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, 0);
promisc = !!(br->dev->flags & IFF_PROMISC);
@ -164,7 +164,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
}
BR_INPUT_SKB_CB(skb)->brdev = br->dev;
BR_INPUT_SKB_CB(skb)->src_port_isolated = !!(p->flags & BR_ISOLATED);
BR_INPUT_SKB_CB(skb)->src_port_isolated = test_bit(BR_ISOLATED_BIT, &p->flags);
if (IS_ENABLED(CONFIG_INET) &&
(skb->protocol == htons(ETH_P_ARP) ||
@ -248,7 +248,7 @@ static void __br_handle_local_finish(struct sk_buff *skb)
u16 vid = 0;
/* check if vlan is allowed, to avoid spoofing */
if ((p->flags & BR_LEARNING) &&
if (test_bit(BR_LEARNING_BIT, &p->flags) &&
nbp_state_should_learn(p) &&
!br_opt_get(p->br, BROPT_NO_LL_LEARN) &&
br_should_learn(p, skb, &vid))
@ -359,7 +359,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
br_tc_skb_miss_set(skb, false);
p = br_port_get_rcu(skb->dev);
if (p->flags & BR_VLAN_TUNNEL)
if (test_bit(BR_VLAN_TUNNEL_BIT, &p->flags))
br_handle_ingress_vlan_tunnel(skb, p, nbp_vlan_group_rcu(p));
if (unlikely(is_link_local_ether_addr(dest))) {

View File

@ -454,7 +454,7 @@ static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp)
state = netif_running(br->dev) ?
BR_STATE_FORWARDING : BR_STATE_DISABLED;
p->state = state;
p->flags &= ~BR_MRP_AWARE;
clear_bit(BR_MRP_AWARE_BIT, &p->flags);
spin_unlock_bh(&br->lock);
br_mrp_port_switchdev_set_state(p, state);
rcu_assign_pointer(mrp->p_port, NULL);
@ -466,7 +466,7 @@ static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp)
state = netif_running(br->dev) ?
BR_STATE_FORWARDING : BR_STATE_DISABLED;
p->state = state;
p->flags &= ~BR_MRP_AWARE;
clear_bit(BR_MRP_AWARE_BIT, &p->flags);
spin_unlock_bh(&br->lock);
br_mrp_port_switchdev_set_state(p, state);
rcu_assign_pointer(mrp->s_port, NULL);
@ -478,7 +478,7 @@ static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp)
state = netif_running(br->dev) ?
BR_STATE_FORWARDING : BR_STATE_DISABLED;
p->state = state;
p->flags &= ~BR_MRP_AWARE;
clear_bit(BR_MRP_AWARE_BIT, &p->flags);
spin_unlock_bh(&br->lock);
br_mrp_port_switchdev_set_state(p, state);
rcu_assign_pointer(mrp->i_port, NULL);
@ -526,14 +526,14 @@ int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance)
p = br_mrp_get_port(br, instance->p_ifindex);
spin_lock_bh(&br->lock);
p->state = BR_STATE_FORWARDING;
p->flags |= BR_MRP_AWARE;
set_bit(BR_MRP_AWARE_BIT, &p->flags);
spin_unlock_bh(&br->lock);
rcu_assign_pointer(mrp->p_port, p);
p = br_mrp_get_port(br, instance->s_ifindex);
spin_lock_bh(&br->lock);
p->state = BR_STATE_FORWARDING;
p->flags |= BR_MRP_AWARE;
set_bit(BR_MRP_AWARE_BIT, &p->flags);
spin_unlock_bh(&br->lock);
rcu_assign_pointer(mrp->s_port, p);
@ -593,7 +593,7 @@ int br_mrp_set_port_state(struct net_bridge_port *p,
{
u32 port_state;
if (!p || !(p->flags & BR_MRP_AWARE))
if (!p || !test_bit(BR_MRP_AWARE_BIT, &p->flags))
return -EINVAL;
spin_lock_bh(&p->br->lock);
@ -619,7 +619,7 @@ int br_mrp_set_port_role(struct net_bridge_port *p,
{
struct br_mrp *mrp;
if (!p || !(p->flags & BR_MRP_AWARE))
if (!p || !test_bit(BR_MRP_AWARE_BIT, &p->flags))
return -EINVAL;
mrp = br_mrp_find_port(p->br, p);
@ -784,7 +784,7 @@ int br_mrp_set_in_role(struct net_bridge *br, struct br_mrp_in_role *role)
state = netif_running(br->dev) ?
BR_STATE_FORWARDING : BR_STATE_DISABLED;
p->state = state;
p->flags &= ~BR_MRP_AWARE;
clear_bit(BR_MRP_AWARE_BIT, &p->flags);
spin_unlock_bh(&br->lock);
br_mrp_port_switchdev_set_state(p, state);
rcu_assign_pointer(mrp->i_port, NULL);
@ -809,7 +809,7 @@ int br_mrp_set_in_role(struct net_bridge *br, struct br_mrp_in_role *role)
p = br_mrp_get_port(br, role->i_ifindex);
spin_lock_bh(&br->lock);
p->state = BR_STATE_FORWARDING;
p->flags |= BR_MRP_AWARE;
set_bit(BR_MRP_AWARE_BIT, &p->flags);
spin_unlock_bh(&br->lock);
rcu_assign_pointer(mrp->i_port, p);
@ -1246,7 +1246,7 @@ static int br_mrp_rcv(struct net_bridge_port *p,
static int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
{
/* If there is no MRP instance do normal forwarding */
if (likely(!(p->flags & BR_MRP_AWARE)))
if (likely(!test_bit(BR_MRP_AWARE_BIT, &p->flags)))
goto out;
return br_mrp_rcv(p, skb, p->dev);

View File

@ -538,9 +538,9 @@ int br_mrp_ring_port_open(struct net_device *dev, u8 loc)
}
if (loc)
p->flags |= BR_MRP_LOST_CONT;
set_bit(BR_MRP_LOST_CONT_BIT, &p->flags);
else
p->flags &= ~BR_MRP_LOST_CONT;
clear_bit(BR_MRP_LOST_CONT_BIT, &p->flags);
br_ifinfo_notify(RTM_NEWLINK, NULL, p);
@ -560,9 +560,9 @@ int br_mrp_in_port_open(struct net_device *dev, u8 loc)
}
if (loc)
p->flags |= BR_MRP_LOST_IN_CONT;
set_bit(BR_MRP_LOST_IN_CONT_BIT, &p->flags);
else
p->flags &= ~BR_MRP_LOST_IN_CONT;
clear_bit(BR_MRP_LOST_IN_CONT_BIT, &p->flags);
br_ifinfo_notify(RTM_NEWLINK, NULL, p);

View File

@ -281,7 +281,7 @@ static bool br_port_group_equal(struct net_bridge_port_group *p,
if (p->key.port != port)
return false;
if (!(port->flags & BR_MULTICAST_TO_UNICAST))
if (!test_bit(BR_MULTICAST_TO_UNICAST_BIT, &port->flags))
return true;
return ether_addr_equal(src, p->eth_addr);
@ -3672,7 +3672,8 @@ br_multicast_leave_group(struct net_bridge_mcast *brmctx,
if (!mp)
goto out;
if (pmctx && (pmctx->port->flags & BR_MULTICAST_FAST_LEAVE)) {
if (pmctx &&
test_bit(BR_MULTICAST_FAST_LEAVE_BIT, &pmctx->port->flags)) {
struct net_bridge_port_group __rcu **pp;
for (pp = &mp->ports;

View File

@ -113,7 +113,7 @@ static size_t br_get_link_af_size_filtered(const struct net_device *dev,
num_vlan_infos = br_get_num_vlan_infos(vg, filter_mask);
rcu_read_unlock();
if (p && (p->flags & BR_VLAN_TUNNEL))
if (p && test_bit(BR_VLAN_TUNNEL_BIT, &p->flags))
vinfo_sz += br_get_vlan_tunnel_info_size(vg);
/* Each VLAN is returned in bridge_vlan_info along with flags */
@ -540,7 +540,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
else
err = br_fill_ifvlaninfo(skb, vg);
if (port && (port->flags & BR_VLAN_TUNNEL))
if (port && test_bit(BR_VLAN_TUNNEL_BIT, &port->flags))
err = br_fill_vlan_tunnel_info(skb, vg);
rcu_read_unlock();
if (err)
@ -823,7 +823,7 @@ static int br_afspec(struct net_bridge *br,
err = 0;
switch (nla_type(attr)) {
case IFLA_BRIDGE_VLAN_TUNNEL_INFO:
if (!p || !(p->flags & BR_VLAN_TUNNEL))
if (!p || !test_bit(BR_VLAN_TUNNEL_BIT, &p->flags))
return -EINVAL;
err = br_parse_vlan_tunnel_info(attr, &tinfo_curr);
if (err)
@ -934,58 +934,67 @@ static int br_set_port_state(struct net_bridge_port *p, u8 state)
}
/* Set/clear or port flags based on attribute */
static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
static void br_set_port_flag(unsigned long *set_flags,
unsigned long *clear_flags,
struct nlattr *tb[],
int attrtype, unsigned long mask)
{
if (!tb[attrtype])
return;
if (nla_get_u8(tb[attrtype]))
p->flags |= mask;
else
p->flags &= ~mask;
if (tb[attrtype]) {
if (nla_get_u8(tb[attrtype]))
*set_flags |= mask;
else
*clear_flags |= mask;
}
}
/* Process bridge protocol info on port */
static int br_setport(struct net_bridge_port *p, struct nlattr *tb[],
struct netlink_ext_ack *extack)
{
unsigned long old_flags, changed_mask;
unsigned long old_flags, flags, changed_mask;
unsigned long set = 0, clear = 0;
bool br_vlan_tunnel_old;
int err;
old_flags = p->flags;
old_flags = READ_ONCE(p->flags);
br_vlan_tunnel_old = (old_flags & BR_VLAN_TUNNEL) ? true : false;
br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE,
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_FAST_LEAVE,
BR_MULTICAST_FAST_LEAVE);
br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST,
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_MCAST_FLOOD,
BR_MCAST_FLOOD);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_MCAST_TO_UCAST,
BR_MULTICAST_TO_UNICAST);
br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS, BR_NEIGH_SUPPRESS);
br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED);
br_set_port_flag(p, tb, IFLA_BRPORT_LOCKED, BR_PORT_LOCKED);
br_set_port_flag(p, tb, IFLA_BRPORT_MAB, BR_PORT_MAB);
br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_BCAST_FLOOD,
BR_BCAST_FLOOD);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_PROXYARP_WIFI,
BR_PROXYARP_WIFI);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_VLAN_TUNNEL,
BR_VLAN_TUNNEL);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_NEIGH_SUPPRESS,
BR_NEIGH_SUPPRESS);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_LOCKED, BR_PORT_LOCKED);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_MAB, BR_PORT_MAB);
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
BR_NEIGH_VLAN_SUPPRESS);
br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_FORWARD_GRAT,
br_set_port_flag(&set, &clear, tb, IFLA_BRPORT_NEIGH_FORWARD_GRAT,
BR_NEIGH_FORWARD_GRAT);
if ((p->flags & BR_PORT_MAB) &&
(!(p->flags & BR_PORT_LOCKED) || !(p->flags & BR_LEARNING))) {
flags = (old_flags | set) & ~clear;
if ((flags & BR_PORT_MAB) &&
(!(flags & BR_PORT_LOCKED) || !(flags & BR_LEARNING))) {
NL_SET_ERR_MSG(extack, "Bridge port must be locked and have learning enabled when MAB is enabled");
p->flags = old_flags;
return -EINVAL;
} else if (!(p->flags & BR_PORT_MAB) && (old_flags & BR_PORT_MAB)) {
}
if (!(flags & BR_PORT_MAB) && (old_flags & BR_PORT_MAB)) {
struct net_bridge_fdb_flush_desc desc = {
.flags = BIT(BR_FDB_LOCKED),
.flags_mask = BIT(BR_FDB_LOCKED),
@ -995,15 +1004,17 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[],
br_fdb_flush(p->br, &desc);
}
changed_mask = old_flags ^ p->flags;
changed_mask = old_flags ^ flags;
err = br_switchdev_set_port_flag(p, p->flags, changed_mask, extack);
if (err) {
p->flags = old_flags;
err = br_switchdev_set_port_flag(p, flags, changed_mask, extack);
if (err)
return err;
}
if (br_vlan_tunnel_old && !(p->flags & BR_VLAN_TUNNEL))
do {
flags = (old_flags | set) & ~clear;
} while (!try_cmpxchg(&p->flags, &old_flags, flags));
if (br_vlan_tunnel_old && !(flags & BR_VLAN_TUNNEL))
nbp_vlan_tunnel_info_flush(p);
br_port_flags_change(p, changed_mask);

View File

@ -39,7 +39,7 @@ void br_set_state(struct net_bridge_port *p, unsigned int state)
/* Don't change the state of the ports if they are driven by a different
* protocol.
*/
if (p->flags & BR_MRP_AWARE)
if (test_bit(BR_MRP_AWARE_BIT, &p->flags))
return;
p->state = state;
@ -179,7 +179,7 @@ static void br_root_selection(struct net_bridge *br)
if (!br_should_become_root_port(p, root_port))
continue;
if (p->flags & BR_ROOT_BLOCK)
if (test_bit(BR_ROOT_BLOCK_BIT, &p->flags))
br_root_port_block(br, p);
else
root_port = p->port_no;

View File

@ -178,7 +178,7 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
if (!ether_addr_equal(eth_hdr(skb)->h_dest, br->group_addr))
goto out;
if (p->flags & BR_BPDU_GUARD) {
if (test_bit(BR_BPDU_GUARD_BIT, &p->flags)) {
br_notice(br, "BPDU received on blocked port %u(%s)\n",
(unsigned int) p->port_no, p->dev->name);
br_stp_disable_port(p);

View File

@ -20,7 +20,7 @@ static bool nbp_switchdev_can_offload_tx_fwd(const struct net_bridge_port *p,
if (br_multicast_igmp_type(skb))
return false;
return (p->flags & BR_TX_FWD_OFFLOAD) &&
return test_bit(BR_TX_FWD_OFFLOAD_BIT, &p->flags) &&
(p->hwdom != BR_INPUT_SKB_CB(skb)->src_hwdom);
}
@ -287,7 +287,7 @@ static int nbp_switchdev_add(struct net_bridge_port *p,
return err;
if (tx_fwd_offload) {
p->flags |= BR_TX_FWD_OFFLOAD;
set_bit(BR_TX_FWD_OFFLOAD_BIT, &p->flags);
static_branch_inc(&br_switchdev_tx_fwd_offload);
}
@ -307,8 +307,8 @@ static void nbp_switchdev_del(struct net_bridge_port *p)
if (p->hwdom)
nbp_switchdev_hwdom_put(p);
if (p->flags & BR_TX_FWD_OFFLOAD) {
p->flags &= ~BR_TX_FWD_OFFLOAD;
if (test_bit(BR_TX_FWD_OFFLOAD_BIT, &p->flags)) {
clear_bit(BR_TX_FWD_OFFLOAD_BIT, &p->flags);
static_branch_dec(&br_switchdev_tx_fwd_offload);
}
}

View File

@ -44,40 +44,44 @@ const struct brport_attribute brport_attr_##_name = { \
.store = _store, \
};
#define BRPORT_ATTR_FLAG(_name, _mask) \
#define BRPORT_ATTR_FLAG(_name, _bitnr) \
static ssize_t show_##_name(struct net_bridge_port *p, char *buf) \
{ \
return sysfs_emit(buf, "%d\n", !!(p->flags & _mask)); \
return sysfs_emit(buf, "%d\n", test_bit(_bitnr, &p->flags)); \
} \
static int store_##_name(struct net_bridge_port *p, unsigned long v) \
{ \
return store_flag(p, v, _mask); \
return store_flag(p, v, _bitnr); \
} \
static BRPORT_ATTR(_name, 0644, \
show_##_name, store_##_name)
static int store_flag(struct net_bridge_port *p, unsigned long v,
unsigned long mask)
unsigned long bitnr)
{
unsigned long oflags, flags = READ_ONCE(p->flags);
struct netlink_ext_ack extack = {0};
unsigned long flags = p->flags;
int err;
oflags = flags;
if (v)
flags |= mask;
__set_bit(bitnr, &flags);
else
flags &= ~mask;
__clear_bit(bitnr, &flags);
if (flags != p->flags) {
err = br_switchdev_set_port_flag(p, flags, mask, &extack);
if (err) {
netdev_err(p->dev, "%s\n", extack._msg);
return err;
}
if (flags == oflags)
return 0;
p->flags = flags;
br_port_flags_change(p, mask);
err = br_switchdev_set_port_flag(p, flags, BIT(bitnr), &extack);
if (err) {
netdev_err(p->dev, "%s\n", extack._msg);
return err;
}
if (v)
set_bit(bitnr, &p->flags);
else
clear_bit(bitnr, &p->flags);
br_port_flags_change(p, BIT(bitnr));
return 0;
}
@ -247,17 +251,17 @@ static int store_backup_port(struct net_bridge_port *p, char *buf)
}
static BRPORT_ATTR_RAW(backup_port, 0644, show_backup_port, store_backup_port);
BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE);
BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD);
BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK);
BRPORT_ATTR_FLAG(learning, BR_LEARNING);
BRPORT_ATTR_FLAG(unicast_flood, BR_FLOOD);
BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP);
BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI);
BRPORT_ATTR_FLAG(multicast_flood, BR_MCAST_FLOOD);
BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD);
BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS);
BRPORT_ATTR_FLAG(isolated, BR_ISOLATED);
BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE_BIT);
BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD_BIT);
BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK_BIT);
BRPORT_ATTR_FLAG(learning, BR_LEARNING_BIT);
BRPORT_ATTR_FLAG(unicast_flood, BR_FLOOD_BIT);
BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP_BIT);
BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI_BIT);
BRPORT_ATTR_FLAG(multicast_flood, BR_MCAST_FLOOD_BIT);
BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD_BIT);
BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS_BIT);
BRPORT_ATTR_FLAG(isolated, BR_ISOLATED_BIT);
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
@ -273,8 +277,8 @@ static int store_multicast_router(struct net_bridge_port *p,
static BRPORT_ATTR(multicast_router, 0644, show_multicast_router,
store_multicast_router);
BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UNICAST);
BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE_BIT);
BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UNICAST_BIT);
#endif
static const struct brport_attribute *brport_attrs[] = {

View File

@ -172,7 +172,7 @@ static int br_vlan_modify_tunnel(const struct net_bridge_port *p,
NL_SET_ERR_MSG_MOD(extack, "Can't modify tunnel mapping of non-port vlans");
return -EINVAL;
}
if (!(p->flags & BR_VLAN_TUNNEL)) {
if (!test_bit(BR_VLAN_TUNNEL_BIT, &p->flags)) {
NL_SET_ERR_MSG_MOD(extack, "Port doesn't have tunnel flag set");
return -EINVAL;
}