19395ac42c49a76c3d1d0f2949fc5b80e965482e
[openwrt/staging/jow.git] / package / kernel / qca-nss-dp / patches / 0010-switchdev-fix-FDB-roaming.patch
1 From d16102cad769f430144ca8094d928762b445e9b0 Mon Sep 17 00:00:00 2001
2 From: Robert Marko <robimarko@gmail.com>
3 Date: Fri, 18 Mar 2022 22:02:01 +0100
4 Subject: [PATCH] switchdev: fix FDB roaming
5
6 Try and solve the roaming issue by trying to replicate what NSS bridge
7 module is doing, but by utilizing switchdev FDB notifiers instead of
8 adding new notifiers to the bridge code.
9
10 We register a new non-blocking switchdev notifier and simply wait for
11 notification, and then process the SWITCHDEV_FDB_DEL_TO_DEVICE
12 notifications.
13
14 Those tell us that a certain FDB entry should be removed, then a VSI ID
15 is fetched for the physical PPE port and using that VSI ID and the
16 notification provided MAC adress existing FDB entry gets removed.
17
18 Signed-off-by: Robert Marko <robimarko@gmail.com>
19 ---
20 nss_dp_switchdev.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++
21 1 file changed, 61 insertions(+)
22
23 --- a/nss_dp_switchdev.c
24 +++ b/nss_dp_switchdev.c
25 @@ -24,6 +24,8 @@
26 #include "nss_dp_dev.h"
27 #include "fal/fal_stp.h"
28 #include "fal/fal_ctrlpkt.h"
29 +#include "fal/fal_fdb.h"
30 +#include "ref/ref_vsi.h"
31
32 #define NSS_DP_SWITCH_ID 0
33 #define NSS_DP_SW_ETHTYPE_PID 0 /* PPE ethtype profile ID for slow protocols */
34 @@ -348,10 +350,64 @@ static int nss_dp_switchdev_event(struct
35 return NOTIFY_DONE;
36 }
37
38 +static int nss_dp_switchdev_fdb_del_event(struct net_device *netdev,
39 + struct switchdev_notifier_fdb_info *fdb_info)
40 +{
41 + struct nss_dp_dev *dp_priv = (struct nss_dp_dev *)netdev_priv(netdev);
42 + fal_fdb_entry_t entry;
43 + a_uint32_t vsi_id;
44 + sw_error_t rv;
45 +
46 + netdev_dbg(netdev, "FDB DEL %pM port %d\n", fdb_info->addr, dp_priv->macid);
47 +
48 + rv = ppe_port_vsi_get(NSS_DP_SWITCH_ID, dp_priv->macid, &vsi_id);
49 + if (rv) {
50 + netdev_err(netdev, "cannot get VSI ID for port %d\n", dp_priv->macid);
51 + return notifier_from_errno(rv);
52 + }
53 +
54 + memset(&entry, 0, sizeof(entry));
55 + memcpy(&entry.addr, fdb_info->addr, ETH_ALEN);
56 + entry.fid = vsi_id;
57 +
58 + rv = fal_fdb_entry_del_bymac(NSS_DP_SWITCH_ID, &entry);
59 + if (rv) {
60 + netdev_err(netdev, "FDB entry delete failed with MAC %pM and fid %d\n",
61 + &entry.addr, entry.fid);
62 + return notifier_from_errno(rv);
63 + }
64 +
65 + return notifier_from_errno(rv);
66 +}
67 +
68 +static int nss_dp_fdb_switchdev_event(struct notifier_block *nb,
69 + unsigned long event, void *ptr)
70 +{
71 + struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
72 +
73 + /*
74 + * Handle switchdev event only for physical devices
75 + */
76 + if (!nss_dp_is_phy_dev(dev)) {
77 + return NOTIFY_DONE;
78 + }
79 +
80 + switch (event) {
81 + case SWITCHDEV_FDB_DEL_TO_DEVICE:
82 + return nss_dp_switchdev_fdb_del_event(dev, ptr);
83 + }
84 +
85 + return NOTIFY_DONE;
86 +}
87 +
88 static struct notifier_block nss_dp_switchdev_notifier = {
89 .notifier_call = nss_dp_switchdev_event,
90 };
91
92 +static struct notifier_block nss_dp_switchdev_fdb_notifier = {
93 + .notifier_call = nss_dp_fdb_switchdev_event,
94 +};
95 +
96 static bool switch_init_done;
97
98 /*
99 @@ -366,6 +422,11 @@ void nss_dp_switchdev_setup(struct net_d
100 return;
101 }
102
103 + err = register_switchdev_notifier(&nss_dp_switchdev_fdb_notifier);
104 + if (err) {
105 + netdev_dbg(dev, "%px:Failed to register switchdev FDB notifier\n", dev);
106 + }
107 +
108 err = register_switchdev_blocking_notifier(&nss_dp_switchdev_notifier);
109 if (err) {
110 netdev_dbg(dev, "%px:Failed to register switchdev notifier\n", dev);