diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c index 5263232278b4..23eb6931a2b4 100644 --- a/net/bridge/br_arp_nd_proxy.c +++ b/net/bridge/br_arp_nd_proxy.c @@ -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); } diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index a114373c9816..e4570bbed854 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -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); diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 4a77d0743374..46c762ca5177 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -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; diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 463c3c7083dc..7ed19aa8ae59 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -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); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 470615675bdc..ddb8f002a40e 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -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))) { diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c index f1aa67f7a051..3f7126a7d720 100644 --- a/net/bridge/br_mrp.c +++ b/net/bridge/br_mrp.c @@ -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); diff --git a/net/bridge/br_mrp_netlink.c b/net/bridge/br_mrp_netlink.c index 86f0e75d6e34..39f07e13fba5 100644 --- a/net/bridge/br_mrp_netlink.c +++ b/net/bridge/br_mrp_netlink.c @@ -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); diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index c2c93c740415..6b3ac473fd22 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -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; diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 7cb24de9c77d..b2cd4e39326d 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -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); diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index b33eb085d9b6..46919d73d42f 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -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; diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 7895489ac6fe..74ec42ba1e7d 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -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); diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index ee3ad9dfbab9..990c6b38fd39 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -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); } } diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 1923c004f0d2..bde731c01e10 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -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[] = { diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c index 92af1e558fda..fcc200c3e3da 100644 --- a/net/bridge/br_vlan_options.c +++ b/net/bridge/br_vlan_options.c @@ -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; }