Commit b0fdb999 authored by David S. Miller's avatar David S. Miller

Merge branch 'switchdev-notifiers'

Vladimir Oltean says:

====================
Plug the last 2 holes in the switchdev notifiers for local FDB entries

The work for trapping local FDB entries to the CPU in switchdev/DSA
started with the "RX filtering in DSA" series:
https://patchwork.kernel.org/project/netdevbpf/cover/20210629140658.2510288-1-olteanv@gmail.com/
and was continued with further improvements such as "Fan out FDB entries
pointing towards the bridge to all switchdev member ports":
https://patchwork.kernel.org/project/netdevbpf/cover/20210719135140.278938-1-vladimir.oltean@nxp.com/
https://patchwork.kernel.org/project/netdevbpf/cover/20210720173557.999534-1-vladimir.oltean@nxp.com/

There are only 2 more issues left to be addressed (famous last words),
and these are:
- dynamically learned FDB entries towards interfaces foreign to DSA need
  to be replayed too
- adding/deleting a VLAN on a port causes the local FDB entries in that
  VLAN to be prematurely deleted

This patch series addresses both, and patch 2 depends on 1 to work properly.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1159da64 52e4bec1
......@@ -732,11 +732,11 @@ static inline size_t fdb_nlmsg_size(void)
+ nla_total_size(sizeof(u8)); /* NFEA_ACTIVITY_NOTIFY */
}
static int br_fdb_replay_one(struct notifier_block *nb,
static int br_fdb_replay_one(struct net_bridge *br, struct notifier_block *nb,
const struct net_bridge_fdb_entry *fdb,
struct net_device *dev, unsigned long action,
const void *ctx)
unsigned long action, const void *ctx)
{
const struct net_bridge_port *p = READ_ONCE(fdb->dst);
struct switchdev_notifier_fdb_info item;
int err;
......@@ -745,15 +745,15 @@ static int br_fdb_replay_one(struct notifier_block *nb,
item.added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
item.offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags);
item.is_local = test_bit(BR_FDB_LOCAL, &fdb->flags);
item.info.dev = dev;
item.info.dev = item.is_local ? br->dev : p->dev;
item.info.ctx = ctx;
err = nb->notifier_call(nb, action, &item);
return notifier_to_errno(err);
}
int br_fdb_replay(const struct net_device *br_dev, const struct net_device *dev,
const void *ctx, bool adding, struct notifier_block *nb)
int br_fdb_replay(const struct net_device *br_dev, const void *ctx, bool adding,
struct notifier_block *nb)
{
struct net_bridge_fdb_entry *fdb;
struct net_bridge *br;
......@@ -766,9 +766,6 @@ int br_fdb_replay(const struct net_device *br_dev, const struct net_device *dev,
if (!netif_is_bridge_master(br_dev))
return -EINVAL;
if (!netif_is_bridge_port(dev) && !netif_is_bridge_master(dev))
return -EINVAL;
br = netdev_priv(br_dev);
if (adding)
......@@ -779,14 +776,7 @@ int br_fdb_replay(const struct net_device *br_dev, const struct net_device *dev,
rcu_read_lock();
hlist_for_each_entry_rcu(fdb, &br->fdb_list, fdb_node) {
const struct net_bridge_port *dst = READ_ONCE(fdb->dst);
struct net_device *dst_dev;
dst_dev = dst ? dst->dev : br->dev;
if (dst_dev && dst_dev != dev)
continue;
err = br_fdb_replay_one(nb, fdb, dst_dev, action, ctx);
err = br_fdb_replay_one(br, nb, fdb, action, ctx);
if (err)
break;
}
......
......@@ -777,8 +777,8 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
bool swdev_notify);
void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid, bool offloaded);
int br_fdb_replay(const struct net_device *br_dev, const struct net_device *dev,
const void *ctx, bool adding, struct notifier_block *nb);
int br_fdb_replay(const struct net_device *br_dev, const void *ctx, bool adding,
struct notifier_block *nb);
/* br_forward.c */
enum br_pkt_type {
......
......@@ -127,7 +127,6 @@ br_switchdev_fdb_notify(struct net_bridge *br,
const struct net_bridge_fdb_entry *fdb, int type)
{
const struct net_bridge_port *dst = READ_ONCE(fdb->dst);
struct net_device *dev = dst ? dst->dev : br->dev;
struct switchdev_notifier_fdb_info info = {
.addr = fdb->key.addr.addr,
.vid = fdb->key.vlan_id,
......@@ -135,6 +134,7 @@ br_switchdev_fdb_notify(struct net_bridge *br,
.is_local = test_bit(BR_FDB_LOCAL, &fdb->flags),
.offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags),
};
struct net_device *dev = info.is_local ? br->dev : dst->dev;
switch (type) {
case RTM_DELNEIGH:
......@@ -287,13 +287,7 @@ static int nbp_switchdev_sync_objs(struct net_bridge_port *p, const void *ctx,
if (err && err != -EOPNOTSUPP)
return err;
/* Forwarding and termination FDB entries on the port */
err = br_fdb_replay(br_dev, dev, ctx, true, atomic_nb);
if (err && err != -EOPNOTSUPP)
return err;
/* Termination FDB entries on the bridge itself */
err = br_fdb_replay(br_dev, br_dev, ctx, true, atomic_nb);
err = br_fdb_replay(br_dev, ctx, true, atomic_nb);
if (err && err != -EOPNOTSUPP)
return err;
......@@ -312,11 +306,7 @@ static void nbp_switchdev_unsync_objs(struct net_bridge_port *p,
br_mdb_replay(br_dev, dev, ctx, false, blocking_nb, NULL);
/* Forwarding and termination FDB entries on the port */
br_fdb_replay(br_dev, dev, ctx, false, atomic_nb);
/* Termination FDB entries on the bridge itself */
br_fdb_replay(br_dev, br_dev, ctx, false, atomic_nb);
br_fdb_replay(br_dev, ctx, false, atomic_nb);
}
/* Let the bridge know that this port is offloaded, so that it can assign a
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment