]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: bridge: switchdev: include local flag in FDB notifications
authorVladimir Oltean <vladimir.oltean@nxp.com>
Wed, 14 Apr 2021 16:52:56 +0000 (19:52 +0300)
committerDavid S. Miller <davem@davemloft.net>
Fri, 16 Apr 2021 22:15:45 +0000 (15:15 -0700)
As explained in bugfix commit 6ab4c3117aec ("net: bridge: don't notify
switchdev for local FDB addresses") as well as in this discussion:
https://lore.kernel.org/netdev/20210117193009.io3nungdwuzmo5f7@skbuf/

the switchdev notifiers for FDB entries managed to have a zero-day bug,
which was that drivers would not know what to do with local FDB entries,
because they were not told that they are local. The bug fix was to
simply not notify them of those addresses.

Let us now add the 'is_local' bit to bridge FDB entries, and make all
drivers ignore these entries by their own choice.

Co-developed-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/ti/am65-cpsw-switchdev.c
drivers/net/ethernet/ti/cpsw_switchdev.c
include/net/switchdev.h
net/bridge/br_switchdev.c
net/dsa/slave.c

index 5250d51d783c9174b4b39a5cd44d6cc58d89705d..05de37c3b64c7fd775adf94be055c83bfe1da25c 100644 (file)
@@ -2098,7 +2098,7 @@ static void dpaa2_switch_event_work(struct work_struct *work)
 
        switch (switchdev_work->event) {
        case SWITCHDEV_FDB_ADD_TO_DEVICE:
-               if (!fdb_info->added_by_user)
+               if (!fdb_info->added_by_user || fdb_info->is_local)
                        break;
                if (is_unicast_ether_addr(fdb_info->addr))
                        err = dpaa2_switch_port_fdb_add_uc(netdev_priv(dev),
@@ -2113,7 +2113,7 @@ static void dpaa2_switch_event_work(struct work_struct *work)
                                         &fdb_info->info, NULL);
                break;
        case SWITCHDEV_FDB_DEL_TO_DEVICE:
-               if (!fdb_info->added_by_user)
+               if (!fdb_info->added_by_user || fdb_info->is_local)
                        break;
                if (is_unicast_ether_addr(fdb_info->addr))
                        dpaa2_switch_port_fdb_del_uc(netdev_priv(dev), fdb_info->addr);
index 49e052273f305cd6867458cdb3e3aea3577d3b46..cb564890a3dc2b3c3f619625a5870a49be8c1eed 100644 (file)
@@ -798,7 +798,7 @@ static void prestera_fdb_event_work(struct work_struct *work)
        switch (swdev_work->event) {
        case SWITCHDEV_FDB_ADD_TO_DEVICE:
                fdb_info = &swdev_work->fdb_info;
-               if (!fdb_info->added_by_user)
+               if (!fdb_info->added_by_user || fdb_info->is_local)
                        break;
 
                err = prestera_port_fdb_set(port, fdb_info, true);
index c1f05c17557de10f004eee12163c2448ef55faf3..eeccd586e781a0ebbfa04d4ec0193e21fb0cdddb 100644 (file)
@@ -2916,7 +2916,8 @@ mlxsw_sp_switchdev_bridge_nve_fdb_event(struct mlxsw_sp_switchdev_event_work *
                return;
 
        if (switchdev_work->event == SWITCHDEV_FDB_ADD_TO_DEVICE &&
-           !switchdev_work->fdb_info.added_by_user)
+           (!switchdev_work->fdb_info.added_by_user ||
+            switchdev_work->fdb_info.is_local))
                return;
 
        if (!netif_running(dev))
@@ -2971,7 +2972,7 @@ static void mlxsw_sp_switchdev_bridge_fdb_event_work(struct work_struct *work)
        switch (switchdev_work->event) {
        case SWITCHDEV_FDB_ADD_TO_DEVICE:
                fdb_info = &switchdev_work->fdb_info;
-               if (!fdb_info->added_by_user)
+               if (!fdb_info->added_by_user || fdb_info->is_local)
                        break;
                err = mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, true);
                if (err)
index 3473d296b2e2e70ddb788d7f2173f1b5c521cb12..a46633606cae06327eaa823bdcbfc5b969093116 100644 (file)
@@ -2736,7 +2736,7 @@ static void rocker_switchdev_event_work(struct work_struct *work)
        switch (switchdev_work->event) {
        case SWITCHDEV_FDB_ADD_TO_DEVICE:
                fdb_info = &switchdev_work->fdb_info;
-               if (!fdb_info->added_by_user)
+               if (!fdb_info->added_by_user || fdb_info->is_local)
                        break;
                err = rocker_world_port_fdb_add(rocker_port, fdb_info);
                if (err) {
@@ -2747,7 +2747,7 @@ static void rocker_switchdev_event_work(struct work_struct *work)
                break;
        case SWITCHDEV_FDB_DEL_TO_DEVICE:
                fdb_info = &switchdev_work->fdb_info;
-               if (!fdb_info->added_by_user)
+               if (!fdb_info->added_by_user || fdb_info->is_local)
                        break;
                err = rocker_world_port_fdb_del(rocker_port, fdb_info);
                if (err)
index d93ffd8a08b0bd0aa008a301672afafa680d1969..23cfb91e9c4d4d1d7ffd17c05da28e4705b50a6c 100644 (file)
@@ -385,7 +385,7 @@ static void am65_cpsw_switchdev_event_work(struct work_struct *work)
                           fdb->addr, fdb->vid, fdb->added_by_user,
                           fdb->offloaded, port_id);
 
-               if (!fdb->added_by_user)
+               if (!fdb->added_by_user || fdb->is_local)
                        break;
                if (memcmp(port->slave.mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
                        port_id = HOST_PORT_NUM;
@@ -401,7 +401,7 @@ static void am65_cpsw_switchdev_event_work(struct work_struct *work)
                           fdb->addr, fdb->vid, fdb->added_by_user,
                           fdb->offloaded, port_id);
 
-               if (!fdb->added_by_user)
+               if (!fdb->added_by_user || fdb->is_local)
                        break;
                if (memcmp(port->slave.mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
                        port_id = HOST_PORT_NUM;
index a72bb570756fd073eae0d6286d43b3504ebe84cc..05a64fb7a04f21f271ac32d1bc8d7b13351babd6 100644 (file)
@@ -395,7 +395,7 @@ static void cpsw_switchdev_event_work(struct work_struct *work)
                        fdb->addr, fdb->vid, fdb->added_by_user,
                        fdb->offloaded, port);
 
-               if (!fdb->added_by_user)
+               if (!fdb->added_by_user || fdb->is_local)
                        break;
                if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
                        port = HOST_PORT_NUM;
@@ -411,7 +411,7 @@ static void cpsw_switchdev_event_work(struct work_struct *work)
                        fdb->addr, fdb->vid, fdb->added_by_user,
                        fdb->offloaded, port);
 
-               if (!fdb->added_by_user)
+               if (!fdb->added_by_user || fdb->is_local)
                        break;
                if (memcmp(priv->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
                        port = HOST_PORT_NUM;
index 8c32181771362a98bed070dd770f253af4fd4add..f1a5a9a3634d96633d582491f802ddfb34d5f72f 100644 (file)
@@ -209,6 +209,7 @@ struct switchdev_notifier_fdb_info {
        const unsigned char *addr;
        u16 vid;
        u8 added_by_user:1,
+          is_local:1,
           offloaded:1;
 };
 
index c390f84adea2c5c0fb8f5d4cfdccea6fe177a911..a5e601e41cb9dbd1475ce017f03b5b13995819cd 100644 (file)
@@ -114,13 +114,12 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
                .addr = fdb->key.addr.addr,
                .vid = fdb->key.vlan_id,
                .added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags),
+               .is_local = test_bit(BR_FDB_LOCAL, &fdb->flags),
                .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags),
        };
 
        if (!fdb->dst)
                return;
-       if (test_bit(BR_FDB_LOCAL, &fdb->flags))
-               return;
 
        switch (type) {
        case RTM_DELNEIGH:
index 9300cb66e500c25892a4378fc688e790ba4e6f44..3ae67202fda2ff45a069d0255d321f98072936bb 100644 (file)
@@ -2329,7 +2329,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
                fdb_info = ptr;
 
                if (dsa_slave_dev_check(dev)) {
-                       if (!fdb_info->added_by_user)
+                       if (!fdb_info->added_by_user || fdb_info->is_local)
                                return NOTIFY_OK;
 
                        dp = dsa_slave_to_port(dev);