mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 01:11:14 +00:00
127 lines
5.7 KiB
Diff
127 lines
5.7 KiB
Diff
|
From 90dc8fd36078a536671adae884d0b929cce6480a Mon Sep 17 00:00:00 2001
|
||
|
From: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||
|
Date: Wed, 6 Jan 2021 11:51:30 +0200
|
||
|
Subject: [PATCH] net: bridge: notify switchdev of disappearance of old FDB
|
||
|
entry upon migration
|
||
|
|
||
|
Currently the bridge emits atomic switchdev notifications for
|
||
|
dynamically learnt FDB entries. Monitoring these notifications works
|
||
|
wonders for switchdev drivers that want to keep their hardware FDB in
|
||
|
sync with the bridge's FDB.
|
||
|
|
||
|
For example station A wants to talk to station B in the diagram below,
|
||
|
and we are concerned with the behavior of the bridge on the DUT device:
|
||
|
|
||
|
DUT
|
||
|
+-------------------------------------+
|
||
|
| br0 |
|
||
|
| +------+ +------+ +------+ +------+ |
|
||
|
| | | | | | | | | |
|
||
|
| | swp0 | | swp1 | | swp2 | | eth0 | |
|
||
|
+-------------------------------------+
|
||
|
| | |
|
||
|
Station A | |
|
||
|
| |
|
||
|
+--+------+--+ +--+------+--+
|
||
|
| | | | | | | |
|
||
|
| | swp0 | | | | swp0 | |
|
||
|
Another | +------+ | | +------+ | Another
|
||
|
switch | br0 | | br0 | switch
|
||
|
| +------+ | | +------+ |
|
||
|
| | | | | | | |
|
||
|
| | swp1 | | | | swp1 | |
|
||
|
+--+------+--+ +--+------+--+
|
||
|
|
|
||
|
Station B
|
||
|
|
||
|
Interfaces swp0, swp1, swp2 are handled by a switchdev driver that has
|
||
|
the following property: frames injected from its control interface bypass
|
||
|
the internal address analyzer logic, and therefore, this hardware does
|
||
|
not learn from the source address of packets transmitted by the network
|
||
|
stack through it. So, since bridging between eth0 (where Station B is
|
||
|
attached) and swp0 (where Station A is attached) is done in software,
|
||
|
the switchdev hardware will never learn the source address of Station B.
|
||
|
So the traffic towards that destination will be treated as unknown, i.e.
|
||
|
flooded.
|
||
|
|
||
|
This is where the bridge notifications come in handy. When br0 on the
|
||
|
DUT sees frames with Station B's MAC address on eth0, the switchdev
|
||
|
driver gets these notifications and can install a rule to send frames
|
||
|
towards Station B's address that are incoming from swp0, swp1, swp2,
|
||
|
only towards the control interface. This is all switchdev driver private
|
||
|
business, which the notification makes possible.
|
||
|
|
||
|
All is fine until someone unplugs Station B's cable and moves it to the
|
||
|
other switch:
|
||
|
|
||
|
DUT
|
||
|
+-------------------------------------+
|
||
|
| br0 |
|
||
|
| +------+ +------+ +------+ +------+ |
|
||
|
| | | | | | | | | |
|
||
|
| | swp0 | | swp1 | | swp2 | | eth0 | |
|
||
|
+-------------------------------------+
|
||
|
| | |
|
||
|
Station A | |
|
||
|
| |
|
||
|
+--+------+--+ +--+------+--+
|
||
|
| | | | | | | |
|
||
|
| | swp0 | | | | swp0 | |
|
||
|
Another | +------+ | | +------+ | Another
|
||
|
switch | br0 | | br0 | switch
|
||
|
| +------+ | | +------+ |
|
||
|
| | | | | | | |
|
||
|
| | swp1 | | | | swp1 | |
|
||
|
+--+------+--+ +--+------+--+
|
||
|
|
|
||
|
Station B
|
||
|
|
||
|
Luckily for the use cases we care about, Station B is noisy enough that
|
||
|
the DUT hears it (on swp1 this time). swp1 receives the frames and
|
||
|
delivers them to the bridge, who enters the unlikely path in br_fdb_update
|
||
|
of updating an existing entry. It moves the entry in the software bridge
|
||
|
to swp1 and emits an addition notification towards that.
|
||
|
|
||
|
As far as the switchdev driver is concerned, all that it needs to ensure
|
||
|
is that traffic between Station A and Station B is not forever broken.
|
||
|
If it does nothing, then the stale rule to send frames for Station B
|
||
|
towards the control interface remains in place. But Station B is no
|
||
|
longer reachable via the control interface, but via a port that can
|
||
|
offload the bridge port learning attribute. It's just that the port is
|
||
|
prevented from learning this address, since the rule overrides FDB
|
||
|
updates. So the rule needs to go. The question is via what mechanism.
|
||
|
|
||
|
It sure would be possible for this switchdev driver to keep track of all
|
||
|
addresses which are sent to the control interface, and then also listen
|
||
|
for bridge notifier events on its own ports, searching for the ones that
|
||
|
have a MAC address which was previously sent to the control interface.
|
||
|
But this is cumbersome and inefficient. Instead, with one small change,
|
||
|
the bridge could notify of the address deletion from the old port, in a
|
||
|
symmetrical manner with how it did for the insertion. Then the switchdev
|
||
|
driver would not be required to monitor learn/forget events for its own
|
||
|
ports. It could just delete the rule towards the control interface upon
|
||
|
bridge entry migration. This would make hardware address learning be
|
||
|
possible again. Then it would take a few more packets until the hardware
|
||
|
and software FDB would be in sync again.
|
||
|
|
||
|
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
|
||
|
Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com>
|
||
|
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
|
||
|
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||
|
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||
|
---
|
||
|
net/bridge/br_fdb.c | 1 +
|
||
|
1 file changed, 1 insertion(+)
|
||
|
|
||
|
--- a/net/bridge/br_fdb.c
|
||
|
+++ b/net/bridge/br_fdb.c
|
||
|
@@ -602,6 +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);
|
||
|
fdb->dst = source;
|
||
|
fdb_modified = true;
|
||
|
/* Take over HW learned entry */
|