Merge branch 'net-bridge-vlan-minor-cleanups-and-annotations'

Nikolay Aleksandrov says:

====================
net: bridge: vlan: minor cleanups and annotations

In preparation for a complete vlan fast-path re-work, this set cleans up
a few minor things - removing legacy code barriers that don't help,
                     annotating lockless accesses and using proper helpers.

No functional changes are intended. Sashiko will find many pre-existing
problems, none of them are related to this set. I will try to fix
everything pre-existing separately in -net, there will probably be a few
critical items. So if there are missed places to annotate, or if there're
actual functional changes, these obviously should be addressed in this set.
====================

Link: https://patch.msgid.link/20260903143138.1574598-1-razor@blackwall.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-09-07 17:26:12 -07:00
commit 3604abae0f
9 changed files with 85 additions and 68 deletions

View File

@ -521,7 +521,8 @@ bool br_is_neigh_suppress_enabled(const struct net_bridge_port *p, u16 vid)
v = br_vlan_find(vg, vid);
if (!v)
return false;
return !!(v->priv_flags & BR_VLFLAG_NEIGH_SUPPRESS_ENABLED);
return !!(READ_ONCE(v->priv_flags) &
BR_VLFLAG_NEIGH_SUPPRESS_ENABLED);
}
return test_bit(BR_NEIGH_SUPPRESS_BIT, &p->flags);
}
@ -535,7 +536,8 @@ bool br_is_neigh_forward_grat_enabled(const struct net_bridge_port *p, u16 vid)
v = br_vlan_find(vg, vid);
if (!v)
return false;
return !!(v->priv_flags & BR_VLFLAG_NEIGH_FORWARD_GRAT_ENABLED);
return !!(READ_ONCE(v->priv_flags) &
BR_VLFLAG_NEIGH_FORWARD_GRAT_ENABLED);
}
return test_bit(BR_NEIGH_FORWARD_GRAT_BIT, &p->flags);
}

View File

@ -70,7 +70,7 @@ int br_mst_get_state(const struct net_device *dev, u16 msti, u8 *state)
list_for_each_entry(v, &vg->vlan_list, vlist) {
if (v->brvlan->msti == msti) {
*state = v->state;
*state = br_vlan_get_state(v);
return 0;
}
}
@ -86,7 +86,7 @@ static void br_mst_vlan_set_state(struct net_bridge_vlan_group *vg,
if (br_vlan_get_state(v) == state)
return;
if (v->vid == vg->pvid)
if (v->vid == br_get_pvid(vg))
br_vlan_set_pvid_state(vg, state);
br_vlan_set_state(v, state);
@ -123,7 +123,7 @@ int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,
err = 0;
list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
if (v->brvlan->msti != msti)
if (READ_ONCE(v->brvlan->msti) != msti)
continue;
br_mst_vlan_set_state(vg, v, state);
@ -145,7 +145,7 @@ static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti)
* it.
*/
if (v != pv && v->brvlan->msti == msti) {
br_mst_vlan_set_state(vg, pv, v->state);
br_mst_vlan_set_state(vg, pv, br_vlan_get_state(v));
return;
}
}
@ -176,7 +176,7 @@ int br_mst_vlan_set_msti(struct net_bridge_vlan *mv, u16 msti)
if (err && err != -EOPNOTSUPP)
return err;
mv->msti = msti;
WRITE_ONCE(mv->msti, msti);
list_for_each_entry(p, &mv->br->port_list, list) {
vg = nbp_vlan_group(p);
@ -249,7 +249,9 @@ size_t br_mst_info_size(const struct net_bridge_vlan_group *vg)
sz = nla_total_size(0);
list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
if (test_bit(v->brvlan->msti, seen))
u16 msti = READ_ONCE(v->brvlan->msti);
if (test_bit(msti, seen))
continue;
/* IFLA_BRIDGE_MST_ENTRY */
@ -259,7 +261,7 @@ size_t br_mst_info_size(const struct net_bridge_vlan_group *vg)
/* IFLA_BRIDGE_MST_ENTRY_STATE */
nla_total_size(sizeof(u8));
__set_bit(v->brvlan->msti, seen);
__set_bit(msti, seen);
}
return sz;
@ -280,7 +282,8 @@ int br_mst_fill_info(struct sk_buff *skb,
nest = nla_nest_start_noflag(skb, IFLA_BRIDGE_MST_ENTRY);
if (!nest ||
nla_put_u16(skb, IFLA_BRIDGE_MST_ENTRY_MSTI, v->brvlan->msti) ||
nla_put_u8(skb, IFLA_BRIDGE_MST_ENTRY_STATE, v->state)) {
nla_put_u8(skb, IFLA_BRIDGE_MST_ENTRY_STATE,
br_vlan_get_state(v))) {
err = -EMSGSIZE;
break;
}

View File

@ -923,7 +923,7 @@ static void __br_multicast_query_handle_vlan(struct net_bridge_mcast *brmctx,
else if (br_multicast_ctx_is_vlan(brmctx))
vlan = brmctx->vlan;
if (vlan && !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)) {
if (vlan && !(READ_ONCE(vlan->flags) & BRIDGE_VLAN_INFO_UNTAGGED)) {
u16 vlan_proto;
if (br_vlan_get_proto(brmctx->br->dev, &vlan_proto) != 0)
@ -2183,7 +2183,7 @@ static void br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)
spin_lock_bh(&br->multicast_lock);
if (br_multicast_port_ctx_is_vlan(pmctx) &&
!(pmctx->vlan->priv_flags & BR_VLFLAG_MCAST_ENABLED)) {
!(READ_ONCE(pmctx->vlan->priv_flags) & BR_VLFLAG_MCAST_ENABLED)) {
spin_unlock_bh(&br->multicast_lock);
return;
}
@ -2220,7 +2220,7 @@ static void br_multicast_disable_port_ctx(struct net_bridge_mcast_port *pmctx)
spin_lock_bh(&br->multicast_lock);
if (br_multicast_port_ctx_is_vlan(pmctx) &&
!(pmctx->vlan->priv_flags & BR_VLFLAG_MCAST_ENABLED)) {
!(READ_ONCE(pmctx->vlan->priv_flags) & BR_VLFLAG_MCAST_ENABLED)) {
spin_unlock_bh(&br->multicast_lock);
return;
}
@ -4094,7 +4094,8 @@ int br_multicast_rcv(struct net_bridge_mcast **brmctx,
*pmctx = &vlan->port_mcast_ctx;
}
if (!(masterv->priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED))
if (!(READ_ONCE(masterv->priv_flags) &
BR_VLFLAG_GLOBAL_MCAST_ENABLED))
return 0;
}
@ -4394,7 +4395,8 @@ void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
return;
spin_lock_bh(&br->multicast_lock);
vlan->priv_flags ^= BR_VLFLAG_MCAST_ENABLED;
WRITE_ONCE(vlan->priv_flags, vlan->priv_flags ^
BR_VLFLAG_MCAST_ENABLED);
spin_unlock_bh(&br->multicast_lock);
if (on)
@ -4410,7 +4412,8 @@ void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
br = vlan->port->br;
spin_lock_bh(&br->multicast_lock);
vlan->priv_flags ^= BR_VLFLAG_MCAST_ENABLED;
WRITE_ONCE(vlan->priv_flags, vlan->priv_flags ^
BR_VLFLAG_MCAST_ENABLED);
if (on)
__br_multicast_enable_port_ctx(&vlan->port_mcast_ctx);
else
@ -4488,7 +4491,8 @@ bool br_multicast_toggle_global_vlan(struct net_bridge_vlan *vlan, bool on)
if (on == !!(vlan->priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED))
return false;
vlan->priv_flags ^= BR_VLFLAG_GLOBAL_MCAST_ENABLED;
WRITE_ONCE(vlan->priv_flags, vlan->priv_flags ^
BR_VLFLAG_GLOBAL_MCAST_ENABLED);
br_multicast_toggle_vlan(vlan, on);
return true;

View File

@ -41,7 +41,7 @@ static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg,
if (v->vid == pvid)
flags |= BRIDGE_VLAN_INFO_PVID;
if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)
if (READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED)
flags |= BRIDGE_VLAN_INFO_UNTAGGED;
if (vid_range_start == 0) {
@ -81,7 +81,7 @@ static int br_get_num_vlan_infos(struct net_bridge_vlan_group *vg,
return 0;
if (filter_mask & RTEXT_FILTER_BRVLAN)
return vg->num_vlans;
return READ_ONCE(vg->num_vlans);
rcu_read_lock();
num_vlans = __get_num_vlan_infos(vg, filter_mask);
@ -385,7 +385,7 @@ static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb,
if (v->vid == pvid)
flags |= BRIDGE_VLAN_INFO_PVID;
if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)
if (READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED)
flags |= BRIDGE_VLAN_INFO_UNTAGGED;
if (vid_range_start == 0) {
@ -437,7 +437,7 @@ static int br_fill_ifvlaninfo(struct sk_buff *skb,
if (v->vid == pvid)
vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)
if (READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED)
vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
@ -531,7 +531,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
else
vg = br_vlan_group_rcu(br);
if (!vg || !vg->num_vlans) {
if (!vg || !READ_ONCE(vg->num_vlans)) {
rcu_read_unlock();
goto done;
}

View File

@ -29,8 +29,10 @@ static size_t __get_vlan_tinfo_size(void)
bool vlan_tunid_inrange(const struct net_bridge_vlan *v_curr,
const struct net_bridge_vlan *v_last)
{
__be32 tunid_curr = tunnel_id_to_key32(v_curr->tinfo.tunnel_id);
__be32 tunid_last = tunnel_id_to_key32(v_last->tinfo.tunnel_id);
__be32 tunid_curr, tunid_last;
tunid_curr = tunnel_id_to_key32(READ_ONCE(v_curr->tinfo.tunnel_id));
tunid_last = tunnel_id_to_key32(READ_ONCE(v_last->tinfo.tunnel_id));
return (be32_to_cpu(tunid_curr) - be32_to_cpu(tunid_last)) == 1;
}
@ -43,7 +45,7 @@ static int __get_num_vlan_tunnel_infos(struct net_bridge_vlan_group *vg)
/* Count number of vlan infos */
list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
/* only a context, bridge vlan not activated */
if (!br_vlan_should_use(v) || !v->tinfo.tunnel_id)
if (!br_vlan_should_use(v) || !READ_ONCE(v->tinfo.tunnel_id))
continue;
if (!vtbegin) {
@ -124,19 +126,19 @@ static int br_fill_vlan_tinfo_range(struct sk_buff *skb,
if (vtend && (vtend->vid - vtbegin->vid) > 0) {
/* add range to skb */
err = br_fill_vlan_tinfo(skb, vtbegin->vid,
vtbegin->tinfo.tunnel_id,
READ_ONCE(vtbegin->tinfo.tunnel_id),
BRIDGE_VLAN_INFO_RANGE_BEGIN);
if (err)
return err;
err = br_fill_vlan_tinfo(skb, vtend->vid,
vtend->tinfo.tunnel_id,
READ_ONCE(vtend->tinfo.tunnel_id),
BRIDGE_VLAN_INFO_RANGE_END);
if (err)
return err;
} else {
err = br_fill_vlan_tinfo(skb, vtbegin->vid,
vtbegin->tinfo.tunnel_id,
READ_ONCE(vtbegin->tinfo.tunnel_id),
0);
if (err)
return err;

View File

@ -665,13 +665,13 @@ static inline int br_is_root_bridge(const struct net_bridge *br)
/* check if a VLAN entry is global */
static inline bool br_vlan_is_master(const struct net_bridge_vlan *v)
{
return v->flags & BRIDGE_VLAN_INFO_MASTER;
return READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_MASTER;
}
/* check if a VLAN entry is used by the bridge */
static inline bool br_vlan_is_brentry(const struct net_bridge_vlan *v)
{
return v->flags & BRIDGE_VLAN_INFO_BRENTRY;
return READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_BRENTRY;
}
/* check if we should use the vlan entry, returns false if it's only context */
@ -687,6 +687,15 @@ static inline bool br_vlan_should_use(const struct net_bridge_vlan *v)
return true;
}
/* The vlan state can be changed with only rcu held by the mst code so
* annotate the lock-free read. br_vlan_set_state() is kept further down
* because it needs br_multicast_update_vlan_mcast_ctx().
*/
static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)
{
return READ_ONCE(v->state);
}
static inline bool nbp_state_should_learn(const struct net_bridge_port *p)
{
return p->state == BR_STATE_LEARNING || p->state == BR_STATE_FORWARDING;
@ -1273,21 +1282,24 @@ br_multicast_ctx_vlan_global_disabled(const struct net_bridge_mcast *brmctx)
{
return br_multicast_ctx_is_vlan(brmctx) &&
(!br_opt_get(brmctx->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED) ||
!(brmctx->vlan->priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED));
!(READ_ONCE(brmctx->vlan->priv_flags) &
BR_VLFLAG_GLOBAL_MCAST_ENABLED));
}
static inline bool
br_multicast_ctx_vlan_disabled(const struct net_bridge_mcast *brmctx)
{
return br_multicast_ctx_is_vlan(brmctx) &&
!(brmctx->vlan->priv_flags & BR_VLFLAG_MCAST_ENABLED);
!(READ_ONCE(brmctx->vlan->priv_flags) &
BR_VLFLAG_MCAST_ENABLED);
}
static inline bool
br_multicast_port_ctx_vlan_disabled(const struct net_bridge_mcast_port *pmctx)
{
return br_multicast_port_ctx_is_vlan(pmctx) &&
!(pmctx->vlan->priv_flags & BR_VLFLAG_MCAST_ENABLED);
!(READ_ONCE(pmctx->vlan->priv_flags) &
BR_VLFLAG_MCAST_ENABLED);
}
static inline bool
@ -1296,7 +1308,7 @@ br_multicast_port_ctx_state_disabled(const struct net_bridge_mcast_port *pmctx)
return pmctx->port->state == BR_STATE_DISABLED ||
(br_multicast_port_ctx_is_vlan(pmctx) &&
(br_multicast_port_ctx_vlan_disabled(pmctx) ||
pmctx->vlan->state == BR_STATE_DISABLED));
br_vlan_get_state(pmctx->vlan) == BR_STATE_DISABLED));
}
static inline bool
@ -1305,7 +1317,7 @@ br_multicast_port_ctx_state_stopped(const struct net_bridge_mcast_port *pmctx)
return br_multicast_port_ctx_state_disabled(pmctx) ||
pmctx->port->state == BR_STATE_BLOCKING ||
(br_multicast_port_ctx_is_vlan(pmctx) &&
pmctx->vlan->state == BR_STATE_BLOCKING);
br_vlan_get_state(pmctx->vlan) == BR_STATE_BLOCKING);
}
static inline bool
@ -1687,8 +1699,7 @@ static inline u16 br_get_pvid(const struct net_bridge_vlan_group *vg)
if (!vg)
return 0;
smp_rmb();
return vg->pvid;
return READ_ONCE(vg->pvid);
}
static inline u16 br_vlan_flags(const struct net_bridge_vlan *v, u16 pvid)
@ -1914,14 +1925,6 @@ bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr,
bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
const struct net_bridge_vlan *v_opts);
/* vlan state manipulation helpers using *_ONCE to annotate lock-free access,
* while br_vlan_set_state() may access data protected by multicast_lock.
*/
static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)
{
return READ_ONCE(v->state);
}
static inline void br_vlan_set_state(struct net_bridge_vlan *v, u8 state)
{
WRITE_ONCE(v->state, state);

View File

@ -40,9 +40,8 @@ static void __vlan_add_pvid(struct net_bridge_vlan_group *vg,
if (vg->pvid == v->vid)
return;
smp_wmb();
br_vlan_set_pvid_state(vg, v->state);
vg->pvid = v->vid;
br_vlan_set_pvid_state(vg, br_vlan_get_state(v));
WRITE_ONCE(vg->pvid, v->vid);
}
static void __vlan_delete_pvid(struct net_bridge_vlan_group *vg, u16 vid)
@ -50,8 +49,7 @@ static void __vlan_delete_pvid(struct net_bridge_vlan_group *vg, u16 vid)
if (vg->pvid != vid)
return;
smp_wmb();
vg->pvid = 0;
WRITE_ONCE(vg->pvid, 0);
}
/* Update the BRIDGE_VLAN_INFO_PVID and BRIDGE_VLAN_INFO_UNTAGGED flags of @v.
@ -62,6 +60,7 @@ static bool __vlan_flags_update(struct net_bridge_vlan *v, u16 flags,
bool commit)
{
struct net_bridge_vlan_group *vg;
u16 vlan_flags;
bool change;
if (br_vlan_is_master(v))
@ -70,8 +69,9 @@ static bool __vlan_flags_update(struct net_bridge_vlan *v, u16 flags,
vg = nbp_vlan_group(v->port);
/* check if anything would be changed on commit */
vlan_flags = v->flags;
change = !!(flags & BRIDGE_VLAN_INFO_PVID) == !!(vg->pvid != v->vid) ||
((flags ^ v->flags) & BRIDGE_VLAN_INFO_UNTAGGED);
((flags ^ vlan_flags) & BRIDGE_VLAN_INFO_UNTAGGED);
if (!commit)
goto out;
@ -82,9 +82,10 @@ static bool __vlan_flags_update(struct net_bridge_vlan *v, u16 flags,
__vlan_delete_pvid(vg, v->vid);
if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
v->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
vlan_flags |= BRIDGE_VLAN_INFO_UNTAGGED;
else
v->flags &= ~BRIDGE_VLAN_INFO_UNTAGGED;
vlan_flags &= ~BRIDGE_VLAN_INFO_UNTAGGED;
WRITE_ONCE(v->flags, vlan_flags);
out:
return change;
@ -343,7 +344,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
goto out_filt;
}
}
vg->num_vlans++;
WRITE_ONCE(vg->num_vlans, vg->num_vlans + 1);
}
/* set the state before publishing */
@ -366,7 +367,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
out_fdb_insert:
if (br_vlan_should_use(v)) {
br_fdb_find_delete_local(br, p, dev->dev_addr, v->vid);
vg->num_vlans--;
WRITE_ONCE(vg->num_vlans, vg->num_vlans - 1);
}
out_filt:
@ -415,8 +416,8 @@ static int __vlan_del(struct net_bridge_vlan *v)
}
if (br_vlan_should_use(v)) {
v->flags &= ~BRIDGE_VLAN_INFO_BRENTRY;
vg->num_vlans--;
WRITE_ONCE(v->flags, v->flags & ~BRIDGE_VLAN_INFO_BRENTRY);
WRITE_ONCE(vg->num_vlans, vg->num_vlans - 1);
}
if (masterv != v) {
@ -524,7 +525,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
* hardware on each egress port as appropriate. So only strip the VLAN
* header if forwarding offload is not being used.
*/
if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED &&
if (READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED &&
!br_switchdev_frame_uses_tx_fwd_offload(skb))
__vlan_hwaccel_clear_tag(skb);
@ -694,7 +695,7 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid)
return true;
vg = nbp_vlan_group_rcu(p);
if (!vg || !vg->num_vlans)
if (!vg || !READ_ONCE(vg->num_vlans))
return false;
if (!br_vlan_get_tag(skb, vid) && skb->vlan_proto != br->vlan_proto)
@ -755,8 +756,8 @@ static int br_vlan_add_existing(struct net_bridge *br,
}
refcount_inc(&vlan->refcnt);
vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY;
vg->num_vlans++;
WRITE_ONCE(vlan->flags, vlan->flags | BRIDGE_VLAN_INFO_BRENTRY);
WRITE_ONCE(vg->num_vlans, vg->num_vlans + 1);
*changed = true;
br_multicast_toggle_one_vlan(vlan, true);
}
@ -1491,12 +1492,12 @@ int br_vlan_fill_forward_path_mode(struct net_bridge *br,
if (!v || !br_vlan_should_use(v))
return -EINVAL;
if (!(v->flags & BRIDGE_VLAN_INFO_UNTAGGED))
if (!(READ_ONCE(v->flags) & BRIDGE_VLAN_INFO_UNTAGGED))
return 0;
if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
else if (v->priv_flags & BR_VLFLAG_TAGGING_BY_SWITCHDEV)
else if (READ_ONCE(v->priv_flags) & BR_VLFLAG_TAGGING_BY_SWITCHDEV)
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW;
else
path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
@ -1552,7 +1553,7 @@ int br_vlan_get_info_rcu(const struct net_device *dev, u16 vid,
return -ENOENT;
p_vinfo->vid = vid;
p_vinfo->flags = v->flags;
p_vinfo->flags = READ_ONCE(v->flags);
if (vid == br_get_pvid(vg))
p_vinfo->flags |= BRIDGE_VLAN_INFO_PVID;
return 0;

View File

@ -43,7 +43,7 @@ bool br_vlan_opts_eq_range(const struct net_bridge_vlan *v_curr,
u8 range_mc_rtr = br_vlan_multicast_router(range_end);
u8 curr_mc_rtr = br_vlan_multicast_router(v_curr);
if (v_curr->state != range_end->state)
if (br_vlan_get_state(v_curr) != br_vlan_get_state(range_end))
return false;
if (!__vlan_tun_can_enter_range(v_curr, range_end))
@ -276,7 +276,8 @@ static int br_vlan_process_one_opts(const struct net_bridge *br,
}
if (val != enabled) {
v->priv_flags ^= BR_VLFLAG_NEIGH_SUPPRESS_ENABLED;
WRITE_ONCE(v->priv_flags, v->priv_flags ^
BR_VLFLAG_NEIGH_SUPPRESS_ENABLED);
*changed = true;
}
}
@ -292,7 +293,8 @@ static int br_vlan_process_one_opts(const struct net_bridge *br,
}
if (val != enabled) {
v->priv_flags ^= BR_VLFLAG_NEIGH_FORWARD_GRAT_ENABLED;
WRITE_ONCE(v->priv_flags, v->priv_flags ^
BR_VLFLAG_NEIGH_FORWARD_GRAT_ENABLED);
*changed = true;
}
}

View File

@ -22,7 +22,7 @@ static inline int br_vlan_tunid_cmp(struct rhashtable_compare_arg *arg,
const struct net_bridge_vlan *vle = ptr;
__be64 tunid = *(__be64 *)arg->key;
return vle->tinfo.tunnel_id != tunid;
return READ_ONCE(vle->tinfo.tunnel_id) != tunid;
}
static const struct rhashtable_params br_vlan_tunnel_rht_params = {