net: bridge: use READ_ONCE() and WRITE_ONCE() compiler barriers for fdb->dst

Annotate the writer side of fdb->dst:

- fdb_create()
- br_fdb_update()
- fdb_add_entry()
- br_fdb_external_learn_add()

with WRITE_ONCE() and the reader side:

- br_fdb_test_addr()
- br_fdb_update()
- fdb_fill_info()
- fdb_add_entry()
- fdb_delete_by_addr_and_port()
- br_fdb_external_learn_add()
- br_switchdev_fdb_notify()

with compiler barriers such that the readers do not attempt to reload
fdb->dst multiple times, leading to potentially different destination
ports when the fdb entry is updated concurrently.

This is especially important in read-side sections where fdb->dst is
used more than once, but let's convert all accesses for the sake of
uniformity.

Suggested-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Vladimir Oltean
2021-06-29 17:06:44 +03:00
committed by David S. Miller
parent 84fe73996c
commit 3e19ae7c6f
2 changed files with 21 additions and 14 deletions

View File

@@ -110,6 +110,7 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
void
br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
{
const struct net_bridge_port *dst = READ_ONCE(fdb->dst);
struct switchdev_notifier_fdb_info info = {
.addr = fdb->key.addr.addr,
.vid = fdb->key.vlan_id,
@@ -118,17 +119,17 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
.offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags),
};
if (!fdb->dst)
if (!dst)
return;
switch (type) {
case RTM_DELNEIGH:
call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE,
fdb->dst->dev, &info.info, NULL);
dst->dev, &info.info, NULL);
break;
case RTM_NEWNEIGH:
call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE,
fdb->dst->dev, &info.info, NULL);
dst->dev, &info.info, NULL);
break;
}
}