diff options
author | DENG Qingfang <dqfext@gmail.com> | 2021-02-22 13:38:11 +0800 |
---|---|---|
committer | Hauke Mehrtens <hauke@hauke-m.de> | 2021-02-23 21:10:56 +0100 |
commit | 920eaab1d8179035d0ae1047e75cf9a50da6a6eb (patch) | |
tree | 14c29956bb33e682f304c643247aa023dd7ec211 /target/linux/generic/pending-5.10 | |
parent | 90b1524f75023ad0f441e82773ca9e9b5d513e1a (diff) | |
download | upstream-920eaab1d8179035d0ae1047e75cf9a50da6a6eb.tar.gz upstream-920eaab1d8179035d0ae1047e75cf9a50da6a6eb.tar.bz2 upstream-920eaab1d8179035d0ae1047e75cf9a50da6a6eb.zip |
kernel: DSA roaming fix for Marvell mv88e6xxx
Marvell mv88e6xxx switch series cannot perform MAC learning from
CPU-injected (FROM_CPU) DSA frames, which results in 2 issues.
- excessive flooding, due to the fact that DSA treats those addresses
as unknown
- the risk of stale routes, which can lead to temporary packet loss
Backport those patch series from netdev mailing list, which solve these
issues by adding and clearing static entries to the switch's FDB.
Add a hack patch to set default VID to 1 in port_fdb_{add,del}. Otherwise
the static entries will be added to the switch's private FDB if VLAN
filtering disabled, which will not work.
The switch may generate an "ATU violation" warning when a client moves
from the CPU port to a switch port because the static ATU entry added by
DSA core still points to the CPU port. DSA core will then clear the static
entry so it is not fatal. Disable the warning so it will not confuse users.
Link: https://lore.kernel.org/netdev/20210106095136.224739-1-olteanv@gmail.com/
Link: https://lore.kernel.org/netdev/20210116012515.3152-1-tobias@waldekranz.com/
Ref: https://gitlab.nic.cz/turris/turris-build/-/issues/165
Signed-off-by: DENG Qingfang <dqfext@gmail.com>
Diffstat (limited to 'target/linux/generic/pending-5.10')
7 files changed, 360 insertions, 0 deletions
diff --git a/target/linux/generic/pending-5.10/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch b/target/linux/generic/pending-5.10/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch new file mode 100644 index 0000000000..081d002c7e --- /dev/null +++ b/target/linux/generic/pending-5.10/762-net-bridge-switchdev-Refactor-br_switchdev_fdb_notif.patch @@ -0,0 +1,75 @@ +From 46fe6cecb296d850c1ee2b333e57093ac4b733f3 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz <tobias@waldekranz.com> +Date: Sat, 16 Jan 2021 02:25:09 +0100 +Subject: [PATCH] net: bridge: switchdev: Refactor br_switchdev_fdb_notify + +Instead of having to add more and more arguments to +br_switchdev_fdb_call_notifiers, get rid of it and build the info +struct directly in br_switchdev_fdb_notify. + +Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> +Reviewed-by: Vladimir Oltean <olteanv@gmail.com> +--- + net/bridge/br_switchdev.c | 41 +++++++++++---------------------------- + 1 file changed, 11 insertions(+), 30 deletions(-) + +--- a/net/bridge/br_switchdev.c ++++ b/net/bridge/br_switchdev.c +@@ -102,46 +102,27 @@ int br_switchdev_set_port_flag(struct ne + return 0; + } + +-static void +-br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac, +- u16 vid, struct net_device *dev, +- bool added_by_user, bool offloaded) +-{ +- struct switchdev_notifier_fdb_info info; +- unsigned long notifier_type; +- +- info.addr = mac; +- info.vid = vid; +- info.added_by_user = added_by_user; +- info.offloaded = offloaded; +- notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE; +- call_switchdev_notifiers(notifier_type, dev, &info.info, NULL); +-} +- + void + br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) + { ++ struct switchdev_notifier_fdb_info info = { ++ .addr = fdb->key.addr.addr, ++ .vid = fdb->key.vlan_id, ++ .added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags), ++ .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), ++ }; ++ + if (!fdb->dst) + return; + + switch (type) { + case RTM_DELNEIGH: +- br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr, +- fdb->key.vlan_id, +- fdb->dst->dev, +- test_bit(BR_FDB_ADDED_BY_USER, +- &fdb->flags), +- test_bit(BR_FDB_OFFLOADED, +- &fdb->flags)); ++ call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE, ++ fdb->dst->dev, &info.info, NULL); + break; + case RTM_NEWNEIGH: +- br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr, +- fdb->key.vlan_id, +- fdb->dst->dev, +- test_bit(BR_FDB_ADDED_BY_USER, +- &fdb->flags), +- test_bit(BR_FDB_OFFLOADED, +- &fdb->flags)); ++ call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE, ++ fdb->dst->dev, &info.info, NULL); + break; + } + } diff --git a/target/linux/generic/pending-5.10/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch b/target/linux/generic/pending-5.10/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch new file mode 100644 index 0000000000..41374c88df --- /dev/null +++ b/target/linux/generic/pending-5.10/763-net-bridge-switchdev-Include-local-flag-in-FDB-notif.patch @@ -0,0 +1,42 @@ +From ec5be4f79026282925ae383caa431a8d41e3456a Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz <tobias@waldekranz.com> +Date: Sat, 16 Jan 2021 02:25:10 +0100 +Subject: [PATCH] net: bridge: switchdev: Include local flag in FDB + notifications + +Some switchdev drivers, notably DSA, ignore all dynamically learned +address notifications (!added_by_user) as these are autonomously added +by the switch. Previously, such a notification was indistinguishable +from a local address notification. Include a local bit in the +notification so that the two classes can be discriminated. + +This allows DSA-like devices to add local addresses to the hardware +FDB (with the CPU as the destination), thereby avoiding flows towards +the CPU being flooded by the switch as unknown unicast. + +Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> +--- + include/net/switchdev.h | 1 + + net/bridge/br_switchdev.c | 1 + + 2 files changed, 2 insertions(+) + +--- a/include/net/switchdev.h ++++ b/include/net/switchdev.h +@@ -224,6 +224,7 @@ struct switchdev_notifier_fdb_info { + const unsigned char *addr; + u16 vid; + u8 added_by_user:1, ++ local:1, + offloaded:1; + }; + +--- a/net/bridge/br_switchdev.c ++++ b/net/bridge/br_switchdev.c +@@ -109,6 +109,7 @@ br_switchdev_fdb_notify(const struct net + .addr = fdb->key.addr.addr, + .vid = fdb->key.vlan_id, + .added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags), ++ .local = test_bit(BR_FDB_LOCAL, &fdb->flags), + .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), + }; + diff --git a/target/linux/generic/pending-5.10/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch b/target/linux/generic/pending-5.10/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch new file mode 100644 index 0000000000..2317989fa5 --- /dev/null +++ b/target/linux/generic/pending-5.10/764-net-bridge-switchdev-Send-FDB-notifications-for-host.patch @@ -0,0 +1,94 @@ +From 2e50fd9322047253c327550b4485cf8761035a8c Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz <tobias@waldekranz.com> +Date: Sat, 16 Jan 2021 02:25:11 +0100 +Subject: [PATCH] net: bridge: switchdev: Send FDB notifications for host + addresses + +Treat addresses added to the bridge itself in the same way as regular +ports and send out a notification so that drivers may sync it down to +the hardware FDB. + +Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> +--- + net/bridge/br_fdb.c | 4 ++-- + net/bridge/br_private.h | 7 ++++--- + net/bridge/br_switchdev.c | 11 +++++------ + 3 files changed, 11 insertions(+), 11 deletions(-) + +--- a/net/bridge/br_fdb.c ++++ b/net/bridge/br_fdb.c +@@ -602,7 +602,7 @@ void br_fdb_update(struct net_bridge *br + /* fastpath: update of existing entry */ + if (unlikely(source != fdb->dst && + !test_bit(BR_FDB_STICKY, &fdb->flags))) { +- br_switchdev_fdb_notify(fdb, RTM_DELNEIGH); ++ br_switchdev_fdb_notify(br, fdb, RTM_DELNEIGH); + fdb->dst = source; + fdb_modified = true; + /* Take over HW learned entry */ +@@ -735,7 +735,7 @@ static void fdb_notify(struct net_bridge + int err = -ENOBUFS; + + if (swdev_notify) +- br_switchdev_fdb_notify(fdb, type); ++ br_switchdev_fdb_notify(br, fdb, type); + + skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC); + if (skb == NULL) +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1527,8 +1527,8 @@ bool nbp_switchdev_allowed_egress(const + int br_switchdev_set_port_flag(struct net_bridge_port *p, + unsigned long flags, + unsigned long mask); +-void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, +- int type); ++void br_switchdev_fdb_notify(struct net_bridge *br, ++ const struct net_bridge_fdb_entry *fdb, int type); + int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, + struct netlink_ext_ack *extack); + int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid); +@@ -1574,7 +1574,8 @@ static inline int br_switchdev_port_vlan + } + + static inline void +-br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) ++br_switchdev_fdb_notify(struct net_bridge *br, ++ const struct net_bridge_fdb_entry *fdb, int type) + { + } + +--- a/net/bridge/br_switchdev.c ++++ b/net/bridge/br_switchdev.c +@@ -103,7 +103,8 @@ int br_switchdev_set_port_flag(struct ne + } + + void +-br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) ++br_switchdev_fdb_notify(struct net_bridge *br, ++ const struct net_bridge_fdb_entry *fdb, int type) + { + struct switchdev_notifier_fdb_info info = { + .addr = fdb->key.addr.addr, +@@ -112,18 +113,16 @@ br_switchdev_fdb_notify(const struct net + .local = test_bit(BR_FDB_LOCAL, &fdb->flags), + .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags), + }; +- +- if (!fdb->dst) +- return; ++ struct net_device *dev = fdb->dst ? fdb->dst->dev : br->dev; + + switch (type) { + case RTM_DELNEIGH: + call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE, +- fdb->dst->dev, &info.info, NULL); ++ dev, &info.info, NULL); + break; + case RTM_NEWNEIGH: + call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE, +- fdb->dst->dev, &info.info, NULL); ++ dev, &info.info, NULL); + break; + } + } diff --git a/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch b/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch new file mode 100644 index 0000000000..9246d1fa40 --- /dev/null +++ b/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch @@ -0,0 +1,36 @@ +From dd082716b43a3684b2f473ae5d1e76d1c076d86d Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz <tobias@waldekranz.com> +Date: Sat, 16 Jan 2021 02:25:12 +0100 +Subject: [PATCH] net: dsa: Include local addresses in assisted CPU port + learning + +Add local addresses (i.e. the ports' MAC addresses) to the hardware +FDB when assisted CPU port learning is enabled. + +NOTE: The bridge's own MAC address is also "local". If that address is +not shared with any port, the bridge's MAC is not be added by this +functionality - but the following commit takes care of that case. + +Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> +--- + net/dsa/slave.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2144,10 +2144,12 @@ static int dsa_slave_switchdev_event(str + fdb_info = ptr; + + if (dsa_slave_dev_check(dev)) { +- if (!fdb_info->added_by_user) +- return NOTIFY_OK; +- + dp = dsa_slave_to_port(dev); ++ ++ if (fdb_info->local && dp->ds->assisted_learning_on_cpu_port) ++ dp = dp->cpu_dp; ++ else if (!fdb_info->added_by_user) ++ return NOTIFY_OK; + } else { + /* Snoop addresses learnt on foreign interfaces + * bridged with us, for switches that don't diff --git a/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch b/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch new file mode 100644 index 0000000000..77f0dca252 --- /dev/null +++ b/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch @@ -0,0 +1,30 @@ +From 0663ebde114a6fb2c28c622ba5212b302d4d2581 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz <tobias@waldekranz.com> +Date: Sat, 16 Jan 2021 02:25:13 +0100 +Subject: [PATCH] net: dsa: Include bridge addresses in assisted CPU port + learning + +Now that notifications are sent out for addresses added to the bridge +itself, extend DSA to include those addresses in the hardware FDB when +assisted CPU port learning is enabled. + +Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> +--- + net/dsa/slave.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2158,7 +2158,11 @@ static int dsa_slave_switchdev_event(str + struct net_device *br_dev; + struct dsa_slave_priv *p; + +- br_dev = netdev_master_upper_dev_get_rcu(dev); ++ if (netif_is_bridge_master(dev)) ++ br_dev = dev; ++ else ++ br_dev = netdev_master_upper_dev_get_rcu(dev); ++ + if (!br_dev) + return NOTIFY_DONE; + diff --git a/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch b/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch new file mode 100644 index 0000000000..39271108ec --- /dev/null +++ b/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch @@ -0,0 +1,56 @@ +From 81e39fd78db82fb51b05fff309b9c521f1a0bc5a Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz <tobias@waldekranz.com> +Date: Sat, 16 Jan 2021 02:25:14 +0100 +Subject: [PATCH] net: dsa: Sync static FDB entries on foreign interfaces to + hardware + +Reuse the "assisted_learning_on_cpu_port" functionality to always add +entries for user-configured entries on foreign interfaces, even if +assisted_learning_on_cpu_port is not enabled. E.g. in this situation: + + br0 + / \ +swp0 dummy0 + +$ bridge fdb add 02:00:de:ad:00:01 dev dummy0 vlan 1 master + +Results in DSA adding an entry in the hardware FDB, pointing this +address towards the CPU port. + +The same is true for entries added to the bridge itself, e.g: + +$ bridge fdb add 02:00:de:ad:00:01 dev br0 vlan 1 self + +Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> +--- + net/dsa/slave.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -2151,9 +2151,12 @@ static int dsa_slave_switchdev_event(str + else if (!fdb_info->added_by_user) + return NOTIFY_OK; + } else { +- /* Snoop addresses learnt on foreign interfaces +- * bridged with us, for switches that don't +- * automatically learn SA from CPU-injected traffic ++ /* Snoop addresses added to foreign interfaces ++ * bridged with us, or the bridge ++ * itself. Dynamically learned addresses can ++ * also be added for switches that don't ++ * automatically learn SA from CPU-injected ++ * traffic. + */ + struct net_device *br_dev; + struct dsa_slave_priv *p; +@@ -2175,7 +2178,8 @@ static int dsa_slave_switchdev_event(str + + dp = p->dp->cpu_dp; + +- if (!dp->ds->assisted_learning_on_cpu_port) ++ if (!fdb_info->added_by_user && ++ !dp->ds->assisted_learning_on_cpu_port) + return NOTIFY_DONE; + } + diff --git a/target/linux/generic/pending-5.10/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-5.10/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch new file mode 100644 index 0000000000..5b8d058247 --- /dev/null +++ b/target/linux/generic/pending-5.10/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch @@ -0,0 +1,27 @@ +From: Tobias Waldekranz <tobias@waldekranz.com> +Subject: [RFC net-next 7/7] net: dsa: mv88e6xxx: Request assisted learning on CPU port +Date: Sat, 16 Jan 2021 02:25:15 +0100 +Archived-At: <https://lore.kernel.org/netdev/20210116012515.3152-8-tobias@waldekranz.com/> + +While the hardware is capable of performing learning on the CPU port, +it requires alot of additions to the bridge's forwarding path in order +to handle multi-destination traffic correctly. + +Until that is in place, opt for the next best thing and let DSA sync +the relevant addresses down to the hardware FDB. + +Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> +--- + drivers/net/dsa/mv88e6xxx/chip.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5405,6 +5405,7 @@ static int mv88e6xxx_register_switch(str + ds->ops = &mv88e6xxx_switch_ops; + ds->ageing_time_min = chip->info->age_time_coeff; + ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; ++ ds->assisted_learning_on_cpu_port = true; + + dev_set_drvdata(dev, ds); + |