Hans J. Schultz
2023-Mar-18 14:10 UTC
[Bridge] [PATCH v2 net-next 0/6] ATU and FDB synchronization on locked ports
This patch set makes it possible to have synchronized dynamic ATU and FDB entries on locked ports. As locked ports are not able to automatically learn, they depend on userspace added entries, where userspace can add static or dynamic entries. The lifetime of static entries are completely dependent on userspace intervention, and thus not of interest here. We are only concerned with dynamic entries, which can be added with a command like: bridge fdb replace ADDR dev <DEV> master dynamic We choose only to support this feature on locked ports, as it involves utilizing the CPU to handle ATU related switchcore events (typically interrupts) and thus can result in significant performance loss if exposed to heavy traffic. On locked ports it is important for userspace to know when an authorized station has become silent, hence not breaking the communication of a station that has been authorized based on the MAC-Authentication Bypass (MAB) scheme. Thus if the station keeps being active after authorization, it will continue to have an open port as long as it is active. Only after a silent period will it have to be reauthorized. As the ageing process in the ATU is dependent on incoming traffic to the switchcore port, it is necessary for the ATU to signal that an entry has aged out, so that the FDB can be updated at the correct time. This patch set includes a solution for the Marvell mv88e6xxx driver, where for this driver we use the Hold-At-One feature so that an age-out violation interrupt occurs when a station has been silent for the system-set age time. The age out violation interrupt allows the switchcore driver to remove both the ATU and the FDB entry at the same time. It is up to the maintainers of other switchcore drivers to implement the feature for their specific driver. LOG: V2: Ensure the port is locked when using the feature as we must ensure that learning is enabled at all times for the interrupts to occur. This was missed in the previous version. Instead of ignoring unsupported flags, ensure that drivers are only called when supporting the feature. As 'dynamic' flag is legacy, all drivers support it at least by their previous handling. Hans J. Schultz (6): net: bridge: add dynamic flag to switchdev notifier net: dsa: propagate flags down towards drivers drivers: net: dsa: add fdb entry flags incoming to switchcore drivers net: bridge: ensure FDB offloaded flag is handled as needed net: dsa: mv88e6xxx: implementation of dynamic ATU entries selftests: forwarding: add dynamic FDB test drivers/net/dsa/b53/b53_common.c | 4 +- drivers/net/dsa/b53/b53_priv.h | 4 +- drivers/net/dsa/hirschmann/hellcreek.c | 4 +- drivers/net/dsa/lan9303-core.c | 4 +- drivers/net/dsa/lantiq_gswip.c | 4 +- drivers/net/dsa/microchip/ksz_common.c | 6 +- drivers/net/dsa/mt7530.c | 4 +- drivers/net/dsa/mv88e6xxx/chip.c | 20 ++++-- drivers/net/dsa/mv88e6xxx/chip.h | 9 ++- drivers/net/dsa/mv88e6xxx/global1_atu.c | 21 +++++++ drivers/net/dsa/mv88e6xxx/port.c | 6 +- drivers/net/dsa/mv88e6xxx/switchdev.c | 61 +++++++++++++++++++ drivers/net/dsa/mv88e6xxx/switchdev.h | 5 ++ drivers/net/dsa/mv88e6xxx/trace.h | 5 ++ drivers/net/dsa/ocelot/felix.c | 4 +- drivers/net/dsa/qca/qca8k-common.c | 4 +- drivers/net/dsa/qca/qca8k.h | 4 +- drivers/net/dsa/rzn1_a5psw.c | 4 +- drivers/net/dsa/sja1105/sja1105_main.c | 11 ++-- include/net/dsa.h | 9 ++- include/net/switchdev.h | 1 + net/bridge/br_fdb.c | 5 +- net/bridge/br_switchdev.c | 1 + net/dsa/dsa.c | 6 ++ net/dsa/port.c | 28 +++++---- net/dsa/port.h | 8 +-- net/dsa/slave.c | 20 ++++-- net/dsa/switch.c | 26 +++++--- net/dsa/switch.h | 1 + .../net/forwarding/bridge_locked_port.sh | 36 +++++++++++ 30 files changed, 258 insertions(+), 67 deletions(-) -- 2.34.1
Hans J. Schultz
2023-Mar-18 14:10 UTC
[Bridge] [PATCH v2 net-next 1/6] net: bridge: add dynamic flag to switchdev notifier
To be able to add dynamic FDB entries to drivers from userspace, the dynamic flag must be added when sending RTM_NEWNEIGH events down. Signed-off-by: Hans J. Schultz <netdev at kapio-technology.com> --- include/net/switchdev.h | 1 + net/bridge/br_switchdev.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index ca0312b78294..aaf918d4ba67 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -249,6 +249,7 @@ struct switchdev_notifier_fdb_info { u8 added_by_user:1, is_local:1, locked:1, + is_dyn:1, offloaded:1; }; diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index de18e9c1d7a7..9707d3fdb396 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -134,6 +134,7 @@ static void br_switchdev_fdb_populate(struct net_bridge *br, 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->is_dyn = !test_bit(BR_FDB_STATIC, &fdb->flags); item->locked = false; item->info.dev = (!p || item->is_local) ? br->dev : p->dev; item->info.ctx = ctx; -- 2.34.1
Hans J. Schultz
2023-Mar-18 14:10 UTC
[Bridge] [PATCH v2 net-next 2/6] net: dsa: propagate flags down towards drivers
Dynamic FDB flag needs to be propagated through the DSA layer to be added to drivers. Use a u16 for fdb flags for future use, so that other flags can also be sent the same way without having to change function interfaces. If we have unsupported flags in the new flags, we do not do unnecessary work and so we return at once. This ensures that the drivers are not called with unsupported flags, so that the drivers do not need to check the new flags. As the dynamic flag is a legacy flag, all drivers support it by default at least as they have done hitherto. Ensure that the dynamic FDB flag is only set when added from userspace, as the feature it supports is to be handled from userspace. Signed-off-by: Hans J. Schultz <netdev at kapio-technology.com> --- include/net/dsa.h | 5 +++++ net/dsa/dsa.c | 6 ++++++ net/dsa/port.c | 28 ++++++++++++++++------------ net/dsa/port.h | 8 ++++---- net/dsa/slave.c | 20 ++++++++++++++++---- net/dsa/switch.c | 18 ++++++++++++------ net/dsa/switch.h | 1 + 7 files changed, 60 insertions(+), 26 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index a15f17a38eca..9e98c4fe1520 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -437,6 +437,9 @@ struct dsa_switch { */ u32 fdb_isolation:1; + /* Supported fdb flags going from the bridge to drivers */ + u16 supported_fdb_flags; + /* Listener for switch fabric events */ struct notifier_block nb; @@ -818,6 +821,8 @@ static inline bool dsa_port_tree_same(const struct dsa_port *a, return a->ds->dst == b->ds->dst; } +#define DSA_FDB_FLAG_DYNAMIC BIT(0) + typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid, bool is_static, void *data); struct dsa_switch_ops { diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index e5f156940c67..c07a2e225ae5 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -626,6 +626,12 @@ static int dsa_switch_setup(struct dsa_switch *ds) ds->configure_vlan_while_not_filtering = true; + /* Since dynamic FDB entries are legacy, all switch drivers should + * support the flag at least by just installing a static entry and + * letting the bridge age it. + */ + ds->supported_fdb_flags = DSA_FDB_FLAG_DYNAMIC; + err = ds->ops->setup(ds); if (err < 0) goto unregister_notifier; diff --git a/net/dsa/port.c b/net/dsa/port.c index 67ad1adec2a2..9a7c1265546d 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -976,12 +976,13 @@ int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu) } int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, - u16 vid) + u16 vid, u16 flags) { struct dsa_notifier_fdb_info info = { .dp = dp, .addr = addr, .vid = vid, + .flags = flags, .db = { .type = DSA_DB_BRIDGE, .bridge = *dp->bridge, @@ -999,12 +1000,13 @@ int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, } int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, - u16 vid) + u16 vid, u16 flags) { struct dsa_notifier_fdb_info info = { .dp = dp, .addr = addr, .vid = vid, + .flags = flags, .db = { .type = DSA_DB_BRIDGE, .bridge = *dp->bridge, @@ -1019,12 +1021,13 @@ int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, static int dsa_port_host_fdb_add(struct dsa_port *dp, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct dsa_notifier_fdb_info info = { .dp = dp, .addr = addr, .vid = vid, + .flags = flags, .db = db, }; @@ -1042,11 +1045,11 @@ int dsa_port_standalone_host_fdb_add(struct dsa_port *dp, .dp = dp, }; - return dsa_port_host_fdb_add(dp, addr, vid, db); + return dsa_port_host_fdb_add(dp, addr, vid, 0, db); } -int dsa_port_bridge_host_fdb_add(struct dsa_port *dp, - const unsigned char *addr, u16 vid) +int dsa_port_bridge_host_fdb_add(struct dsa_port *dp, const unsigned char *addr, + u16 vid, u16 flags) { struct net_device *master = dsa_port_to_master(dp); struct dsa_db db = { @@ -1065,17 +1068,18 @@ int dsa_port_bridge_host_fdb_add(struct dsa_port *dp, return err; } - return dsa_port_host_fdb_add(dp, addr, vid, db); + return dsa_port_host_fdb_add(dp, addr, vid, flags, db); } static int dsa_port_host_fdb_del(struct dsa_port *dp, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct dsa_notifier_fdb_info info = { .dp = dp, .addr = addr, .vid = vid, + .flags = flags, .db = db, }; @@ -1093,11 +1097,11 @@ int dsa_port_standalone_host_fdb_del(struct dsa_port *dp, .dp = dp, }; - return dsa_port_host_fdb_del(dp, addr, vid, db); + return dsa_port_host_fdb_del(dp, addr, vid, 0, db); } -int dsa_port_bridge_host_fdb_del(struct dsa_port *dp, - const unsigned char *addr, u16 vid) +int dsa_port_bridge_host_fdb_del(struct dsa_port *dp, const unsigned char *addr, + u16 vid, u16 flags) { struct net_device *master = dsa_port_to_master(dp); struct dsa_db db = { @@ -1112,7 +1116,7 @@ int dsa_port_bridge_host_fdb_del(struct dsa_port *dp, return err; } - return dsa_port_host_fdb_del(dp, addr, vid, db); + return dsa_port_host_fdb_del(dp, addr, vid, flags, db); } int dsa_port_lag_fdb_add(struct dsa_port *dp, const unsigned char *addr, diff --git a/net/dsa/port.h b/net/dsa/port.h index 9c218660d223..88a9dfed3bce 100644 --- a/net/dsa/port.h +++ b/net/dsa/port.h @@ -47,17 +47,17 @@ int dsa_port_vlan_msti(struct dsa_port *dp, const struct switchdev_vlan_msti *msti); int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu); int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, - u16 vid); + u16 vid, u16 flags); int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, - u16 vid); + u16 vid, u16 flags); int dsa_port_standalone_host_fdb_add(struct dsa_port *dp, const unsigned char *addr, u16 vid); int dsa_port_standalone_host_fdb_del(struct dsa_port *dp, const unsigned char *addr, u16 vid); int dsa_port_bridge_host_fdb_add(struct dsa_port *dp, const unsigned char *addr, - u16 vid); + u16 vid, u16 flags); int dsa_port_bridge_host_fdb_del(struct dsa_port *dp, const unsigned char *addr, - u16 vid); + u16 vid, u16 flags); int dsa_port_lag_fdb_add(struct dsa_port *dp, const unsigned char *addr, u16 vid); int dsa_port_lag_fdb_del(struct dsa_port *dp, const unsigned char *addr, diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 6957971c2db2..20d2d1c000ea 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -39,6 +39,7 @@ struct dsa_switchdev_event_work { */ unsigned char addr[ETH_ALEN]; u16 vid; + u16 fdb_flags; bool host_addr; }; @@ -3331,6 +3332,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) container_of(work, struct dsa_switchdev_event_work, work); const unsigned char *addr = switchdev_work->addr; struct net_device *dev = switchdev_work->dev; + u16 flags = switchdev_work->fdb_flags; u16 vid = switchdev_work->vid; struct dsa_switch *ds; struct dsa_port *dp; @@ -3342,11 +3344,12 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) switch (switchdev_work->event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: if (switchdev_work->host_addr) - err = dsa_port_bridge_host_fdb_add(dp, addr, vid); + err = dsa_port_bridge_host_fdb_add(dp, addr, + vid, flags); else if (dp->lag) err = dsa_port_lag_fdb_add(dp, addr, vid); else - err = dsa_port_fdb_add(dp, addr, vid); + err = dsa_port_fdb_add(dp, addr, vid, flags); if (err) { dev_err(ds->dev, "port %d failed to add %pM vid %d to fdb: %d\n", @@ -3358,11 +3361,12 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) case SWITCHDEV_FDB_DEL_TO_DEVICE: if (switchdev_work->host_addr) - err = dsa_port_bridge_host_fdb_del(dp, addr, vid); + err = dsa_port_bridge_host_fdb_del(dp, addr, + vid, flags); else if (dp->lag) err = dsa_port_lag_fdb_del(dp, addr, vid); else - err = dsa_port_fdb_del(dp, addr, vid); + err = dsa_port_fdb_del(dp, addr, vid, flags); if (err) { dev_err(ds->dev, "port %d failed to delete %pM vid %d from fdb: %d\n", @@ -3400,6 +3404,7 @@ static int dsa_slave_fdb_event(struct net_device *dev, struct dsa_port *dp = dsa_slave_to_port(dev); bool host_addr = fdb_info->is_local; struct dsa_switch *ds = dp->ds; + u16 flags = 0; if (ctx && ctx != dp) return 0; @@ -3437,6 +3442,12 @@ static int dsa_slave_fdb_event(struct net_device *dev, return -EOPNOTSUPP; } + if (fdb_info->is_dyn && fdb_info->added_by_user) + flags |= DSA_FDB_FLAG_DYNAMIC; + + if (flags & ~ds->supported_fdb_flags) + return 0; + switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); if (!switchdev_work) return -ENOMEM; @@ -3454,6 +3465,7 @@ static int dsa_slave_fdb_event(struct net_device *dev, ether_addr_copy(switchdev_work->addr, fdb_info->addr); switchdev_work->vid = fdb_info->vid; switchdev_work->host_addr = host_addr; + switchdev_work->fdb_flags = flags; dsa_schedule_work(&switchdev_work->work); diff --git a/net/dsa/switch.c b/net/dsa/switch.c index d5bc4bb7310d..0f5626a425b6 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -239,7 +239,7 @@ static int dsa_port_do_mdb_del(struct dsa_port *dp, } static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, - u16 vid, struct dsa_db db) + u16 vid, u16 flags, struct dsa_db db) { struct dsa_switch *ds = dp->ds; struct dsa_mac_addr *a; @@ -283,7 +283,7 @@ static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, } static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr, - u16 vid, struct dsa_db db) + u16 vid, u16 flags, struct dsa_db db) { struct dsa_switch *ds = dp->ds; struct dsa_mac_addr *a; @@ -410,7 +410,9 @@ static int dsa_switch_host_fdb_add(struct dsa_switch *ds, info->db); } else { err = dsa_port_do_fdb_add(dp, info->addr, - info->vid, info->db); + info->vid, + info->flags, + info->db); } if (err) break; @@ -438,7 +440,9 @@ static int dsa_switch_host_fdb_del(struct dsa_switch *ds, info->db); } else { err = dsa_port_do_fdb_del(dp, info->addr, - info->vid, info->db); + info->vid, + info->flags, + info->db); } if (err) break; @@ -457,7 +461,8 @@ static int dsa_switch_fdb_add(struct dsa_switch *ds, if (!ds->ops->port_fdb_add) return -EOPNOTSUPP; - return dsa_port_do_fdb_add(dp, info->addr, info->vid, info->db); + return dsa_port_do_fdb_add(dp, info->addr, info->vid, + info->flags, info->db); } static int dsa_switch_fdb_del(struct dsa_switch *ds, @@ -469,7 +474,8 @@ static int dsa_switch_fdb_del(struct dsa_switch *ds, if (!ds->ops->port_fdb_del) return -EOPNOTSUPP; - return dsa_port_do_fdb_del(dp, info->addr, info->vid, info->db); + return dsa_port_do_fdb_del(dp, info->addr, info->vid, + info->flags, info->db); } static int dsa_switch_lag_fdb_add(struct dsa_switch *ds, diff --git a/net/dsa/switch.h b/net/dsa/switch.h index 15e67b95eb6e..2c3bf4020158 100644 --- a/net/dsa/switch.h +++ b/net/dsa/switch.h @@ -55,6 +55,7 @@ struct dsa_notifier_fdb_info { const struct dsa_port *dp; const unsigned char *addr; u16 vid; + u16 flags; struct dsa_db db; }; -- 2.34.1
Hans J. Schultz
2023-Mar-18 14:10 UTC
[Bridge] [PATCH v2 net-next 3/6] drivers: net: dsa: add fdb entry flags incoming to switchcore drivers
Drivers are only called with supported fdb flags set. Signed-off-by: Hans J. Schultz <netdev at kapio-technology.com> --- drivers/net/dsa/b53/b53_common.c | 4 ++-- drivers/net/dsa/b53/b53_priv.h | 4 ++-- drivers/net/dsa/hirschmann/hellcreek.c | 4 ++-- drivers/net/dsa/lan9303-core.c | 4 ++-- drivers/net/dsa/lantiq_gswip.c | 4 ++-- drivers/net/dsa/microchip/ksz_common.c | 6 +++--- drivers/net/dsa/mt7530.c | 4 ++-- drivers/net/dsa/mv88e6xxx/chip.c | 4 ++-- drivers/net/dsa/ocelot/felix.c | 4 ++-- drivers/net/dsa/qca/qca8k-common.c | 4 ++-- drivers/net/dsa/qca/qca8k.h | 4 ++-- drivers/net/dsa/rzn1_a5psw.c | 4 ++-- drivers/net/dsa/sja1105/sja1105_main.c | 11 ++++++----- include/net/dsa.h | 4 ++-- net/dsa/switch.c | 8 ++++---- 15 files changed, 37 insertions(+), 36 deletions(-) diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 59cdfc51ce06..f4bb0fed8913 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1684,7 +1684,7 @@ static int b53_arl_op(struct b53_device *dev, int op, int port, int b53_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct b53_device *priv = ds->priv; int ret; @@ -1705,7 +1705,7 @@ EXPORT_SYMBOL(b53_fdb_add); int b53_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct b53_device *priv = ds->priv; int ret; diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index 795cbffd5c2b..5479340a0b00 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -362,10 +362,10 @@ int b53_vlan_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan); int b53_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db); + u16 flags, struct dsa_db db); int b53_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db); + u16 flags, struct dsa_db db); int b53_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb, void *data); int b53_mdb_add(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index 595a548bb0a8..2b25203c5f58 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -839,7 +839,7 @@ static int hellcreek_fdb_get(struct hellcreek *hellcreek, static int hellcreek_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct hellcreek_fdb_entry entry = { 0 }; struct hellcreek *hellcreek = ds->priv; @@ -885,7 +885,7 @@ static int hellcreek_fdb_add(struct dsa_switch *ds, int port, static int hellcreek_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct hellcreek_fdb_entry entry = { 0 }; struct hellcreek *hellcreek = ds->priv; diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index cbe831875347..e4f830a4f143 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -1183,7 +1183,7 @@ static void lan9303_port_fast_age(struct dsa_switch *ds, int port) static int lan9303_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct lan9303 *chip = ds->priv; @@ -1196,7 +1196,7 @@ static int lan9303_port_fdb_add(struct dsa_switch *ds, int port, static int lan9303_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct lan9303 *chip = ds->priv; diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 05ecaa007ab1..65fcc57ad1b6 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -1399,14 +1399,14 @@ static int gswip_port_fdb(struct dsa_switch *ds, int port, static int gswip_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { return gswip_port_fdb(ds, port, addr, vid, true); } static int gswip_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { return gswip_port_fdb(ds, port, addr, vid, false); } diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 729b36eeb2c4..0bc6cc36e11f 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -2390,7 +2390,7 @@ static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) static int ksz_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct ksz_device *dev = ds->priv; @@ -2401,8 +2401,8 @@ static int ksz_port_fdb_add(struct dsa_switch *ds, int port, } static int ksz_port_fdb_del(struct dsa_switch *ds, int port, - const unsigned char *addr, - u16 vid, struct dsa_db db) + const unsigned char *addr, u16 vid, + u16 flags, struct dsa_db db) { struct ksz_device *dev = ds->priv; diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 3a15015bc409..0b6eae2de0c1 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -1374,7 +1374,7 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port, static int mt7530_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct mt7530_priv *priv = ds->priv; int ret; @@ -1391,7 +1391,7 @@ mt7530_port_fdb_add(struct dsa_switch *ds, int port, static int mt7530_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct mt7530_priv *priv = ds->priv; int ret; diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 0a5d6c7bb128..6848fa0e5979 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2724,7 +2724,7 @@ static int mv88e6xxx_vlan_msti_set(struct dsa_switch *ds, static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct mv88e6xxx_chip *chip = ds->priv; int err; @@ -2739,7 +2739,7 @@ static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct mv88e6xxx_chip *chip = ds->priv; int err; diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index d4cc9e60f369..65cf02e3e515 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -782,7 +782,7 @@ static int felix_fdb_dump(struct dsa_switch *ds, int port, static int felix_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct net_device *bridge_dev = felix_classify_db(db); struct dsa_port *dp = dsa_to_port(ds, port); @@ -803,7 +803,7 @@ static int felix_fdb_add(struct dsa_switch *ds, int port, static int felix_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct net_device *bridge_dev = felix_classify_db(db); struct dsa_port *dp = dsa_to_port(ds, port); diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c index 96773e432558..fd6e215a4054 100644 --- a/drivers/net/dsa/qca/qca8k-common.c +++ b/drivers/net/dsa/qca/qca8k-common.c @@ -758,7 +758,7 @@ int qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr, int qca8k_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; u16 port_mask = BIT(port); @@ -768,7 +768,7 @@ int qca8k_port_fdb_add(struct dsa_switch *ds, int port, int qca8k_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; u16 port_mask = BIT(port); diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h index 7996975d29d3..d175f15eb239 100644 --- a/drivers/net/dsa/qca/qca8k.h +++ b/drivers/net/dsa/qca/qca8k.h @@ -473,10 +473,10 @@ int qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr, u16 port_mask, u16 vid); int qca8k_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db); + u16 flags, struct dsa_db db); int qca8k_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db); + u16 flags, struct dsa_db db); int qca8k_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb, void *data); diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index 919027cf2012..5f0f6c08bd53 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -396,7 +396,7 @@ static int a5psw_lk_execute_lookup(struct a5psw *a5psw, union lk_data *lk_data, static int a5psw_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct a5psw *a5psw = ds->priv; union lk_data lk_data = {0}; @@ -447,7 +447,7 @@ static int a5psw_port_fdb_add(struct dsa_switch *ds, int port, static int a5psw_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct a5psw *a5psw = ds->priv; union lk_data lk_data = {0}; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index b70dcf32a26d..e4592af21ba3 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1802,7 +1802,7 @@ int sja1105pqrs_fdb_del(struct dsa_switch *ds, int port, static int sja1105_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct sja1105_private *priv = ds->priv; @@ -1824,7 +1824,7 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port, static int sja1105_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db) + u16 flags, struct dsa_db db) { struct sja1105_private *priv = ds->priv; @@ -1930,7 +1930,8 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port) u64_to_ether_addr(l2_lookup.macaddr, macaddr); - rc = sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid, db); + rc = sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid, + 0, db); if (rc) { dev_err(ds->dev, "Failed to delete FDB entry %pM vid %lld: %pe\n", @@ -1944,14 +1945,14 @@ static int sja1105_mdb_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) { - return sja1105_fdb_add(ds, port, mdb->addr, mdb->vid, db); + return sja1105_fdb_add(ds, port, mdb->addr, mdb->vid, 0, db); } static int sja1105_mdb_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) { - return sja1105_fdb_del(ds, port, mdb->addr, mdb->vid, db); + return sja1105_fdb_del(ds, port, mdb->addr, mdb->vid, 0, db); } /* Common function for unicast and broadcast flood configuration. diff --git a/include/net/dsa.h b/include/net/dsa.h index 9e98c4fe1520..3b2bd41c2af5 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -1050,10 +1050,10 @@ struct dsa_switch_ops { */ int (*port_fdb_add)(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db); + u16 flags, struct dsa_db db); int (*port_fdb_del)(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, - struct dsa_db db); + u16 flags, struct dsa_db db); int (*port_fdb_dump)(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb, void *data); int (*lag_fdb_add)(struct dsa_switch *ds, struct dsa_lag lag, diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 0f5626a425b6..1d7d01a1b2a3 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -248,7 +248,7 @@ static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, /* No need to bother with refcounting for user ports */ if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) - return ds->ops->port_fdb_add(ds, port, addr, vid, db); + return ds->ops->port_fdb_add(ds, port, addr, vid, flags, db); mutex_lock(&dp->addr_lists_lock); @@ -264,7 +264,7 @@ static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr, goto out; } - err = ds->ops->port_fdb_add(ds, port, addr, vid, db); + err = ds->ops->port_fdb_add(ds, port, addr, vid, flags, db); if (err) { kfree(a); goto out; @@ -292,7 +292,7 @@ static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr, /* No need to bother with refcounting for user ports */ if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) - return ds->ops->port_fdb_del(ds, port, addr, vid, db); + return ds->ops->port_fdb_del(ds, port, addr, vid, flags, db); mutex_lock(&dp->addr_lists_lock); @@ -305,7 +305,7 @@ static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr, if (!refcount_dec_and_test(&a->refcount)) goto out; - err = ds->ops->port_fdb_del(ds, port, addr, vid, db); + err = ds->ops->port_fdb_del(ds, port, addr, vid, flags, db); if (err) { refcount_set(&a->refcount, 1); goto out; -- 2.34.1
Hans J. Schultz
2023-Mar-18 14:10 UTC
[Bridge] [PATCH v2 net-next 4/6] net: bridge: ensure FDB offloaded flag is handled as needed
Since user added entries in the bridge FDB will get the BR_FDB_OFFLOADED flag set, we do not want the bridge to age those entries and we want the entries to be deleted in the bridge upon an SWITCHDEV_FDB_DEL_TO_BRIDGE event. Signed-off-by: Hans J. Schultz <netdev at kapio-technology.com> --- net/bridge/br_fdb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index e69a872bfc1d..b0c23a72bc76 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -537,6 +537,7 @@ void br_fdb_cleanup(struct work_struct *work) unsigned long this_timer = f->updated + delay; if (test_bit(BR_FDB_STATIC, &f->flags) || + test_bit(BR_FDB_OFFLOADED, &f->flags) || test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &f->flags)) { if (test_bit(BR_FDB_NOTIFY, &f->flags)) { if (time_after(this_timer, now)) @@ -1465,7 +1466,9 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p, spin_lock_bh(&br->hash_lock); fdb = br_fdb_find(br, addr, vid); - if (fdb && test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags)) + if (fdb && + (test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags) || + test_bit(BR_FDB_OFFLOADED, &fdb->flags))) fdb_delete(br, fdb, swdev_notify); else err = -ENOENT; -- 2.34.1
Hans J. Schultz
2023-Mar-18 14:10 UTC
[Bridge] [PATCH v2 net-next 5/6] net: dsa: mv88e6xxx: implementation of dynamic ATU entries
For 802.1X or MAB security authed hosts we want to have these hosts authed by adding dynamic FDB entries, so that if an authed host goes silent for a time period it's FDB entry will be removed and it must reauth when wanting to communicate again. In the mv88e6xxx offloaded case, we can use the HoldAt1 feature, that gives an age out interrupt when the FDB entry is about to age out, so that userspace can be notified of the entry being deleted with the help of an SWITCHDEV_FDB_DEL_TO_BRIDGE event. When adding a dynamic entry the bridge must be informed that the driver takes care of the ageing be sending an SWITCHDEV_FDB_OFFLOADED event, telling the bridge that this added FDB entry will be handled by the driver. With this implementation, trace events for age out interrupts are also added. note: A special case arises with the age out interrupt, as the entry state/spid (source port id) value read from the registers will be zero. Thus we need to extract the source port from the port vector instead. Signed-off-by: Hans J. Schultz <netdev at kapio-technology.com> --- drivers/net/dsa/mv88e6xxx/chip.c | 16 ++++++- drivers/net/dsa/mv88e6xxx/chip.h | 9 +++- drivers/net/dsa/mv88e6xxx/global1_atu.c | 21 +++++++++ drivers/net/dsa/mv88e6xxx/port.c | 6 ++- drivers/net/dsa/mv88e6xxx/switchdev.c | 61 +++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/switchdev.h | 5 ++ drivers/net/dsa/mv88e6xxx/trace.h | 5 ++ 7 files changed, 119 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 6848fa0e5979..843ed02da9a2 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -42,6 +42,7 @@ #include "ptp.h" #include "serdes.h" #include "smi.h" +#include "switchdev.h" static void assert_reg_lock(struct mv88e6xxx_chip *chip) { @@ -2726,14 +2727,23 @@ static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, u16 flags, struct dsa_db db) { + bool is_dynamic = !!(flags & DSA_FDB_FLAG_DYNAMIC); struct mv88e6xxx_chip *chip = ds->priv; + u8 state; int err; + is_dynamic &= chip->ports[port].locked; + state = MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC; + if (is_dynamic) + state = MV88E6XXX_G1_ATU_DATA_STATE_UC_AGE_7_NEWEST; + mv88e6xxx_reg_lock(chip); - err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, - MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); + err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, state); mv88e6xxx_reg_unlock(chip); + if (is_dynamic && !err) + mv88e6xxx_set_fdb_offloaded(ds, port, addr, vid); + return err; } @@ -6679,6 +6689,8 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port, err = mv88e6xxx_port_set_lock(chip, port, locked); if (err) goto out; + + mv88e6xxx_port_set_locked(chip, port, locked); } out: mv88e6xxx_reg_unlock(chip); diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index da6e1339f809..bf61eb54c091 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -281,8 +281,9 @@ struct mv88e6xxx_port { char serdes_irq_name[64]; struct devlink_region *region; - /* MacAuth Bypass control flag */ + /* Locked and MacAuth Bypass control flags */ bool mab; + bool locked; }; enum mv88e6xxx_region_id { @@ -795,6 +796,12 @@ static inline bool mv88e6xxx_is_invalid_port(struct mv88e6xxx_chip *chip, int po return (chip->info->invalid_port_mask & BIT(port)) != 0; } +static inline void mv88e6xxx_port_set_locked(struct mv88e6xxx_chip *chip, + int port, bool locked) +{ + chip->ports[port].locked = locked; +} + static inline void mv88e6xxx_port_set_mab(struct mv88e6xxx_chip *chip, int port, bool mab) { diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c index ce3b3690c3c0..c95f8cffba41 100644 --- a/drivers/net/dsa/mv88e6xxx/global1_atu.c +++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c @@ -432,6 +432,27 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) spid = entry.state; + if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) { + unsigned long port = 0; + unsigned long portvec = entry.portvec; + + port = find_first_bit(&portvec, MV88E6XXX_MAX_PVT_PORTS); + if (port >= MV88E6XXX_MAX_PVT_PORTS) { + dev_err(chip->dev, + "ATU err: mac: %pM. Port not in portvec: %x\n", + entry.mac, entry.portvec); + goto out; + } + + spid = port; + trace_mv88e6xxx_atu_age_out_violation(chip->dev, spid, + entry.portvec, entry.mac, + fid); + + err = mv88e6xxx_handle_age_out_violation(chip, spid, + &entry, fid); + } + if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) { trace_mv88e6xxx_atu_member_violation(chip->dev, spid, entry.portvec, entry.mac, diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index f79cf716c541..5225971b9a33 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -1255,7 +1255,11 @@ int mv88e6xxx_port_set_lock(struct mv88e6xxx_chip *chip, int port, reg &= ~MV88E6XXX_PORT_ASSOC_VECTOR_LOCKED_PORT; if (locked) - reg |= MV88E6XXX_PORT_ASSOC_VECTOR_LOCKED_PORT; + reg |= MV88E6XXX_PORT_ASSOC_VECTOR_LOCKED_PORT | + MV88E6XXX_PORT_ASSOC_VECTOR_REFRESH_LOCKED | + MV88E6XXX_PORT_ASSOC_VECTOR_IGNORE_WRONG | + MV88E6XXX_PORT_ASSOC_VECTOR_INT_AGE_OUT | + MV88E6XXX_PORT_ASSOC_VECTOR_HOLD_AT_1; return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR, reg); } diff --git a/drivers/net/dsa/mv88e6xxx/switchdev.c b/drivers/net/dsa/mv88e6xxx/switchdev.c index 4c346a884fb2..76f7f8cc1835 100644 --- a/drivers/net/dsa/mv88e6xxx/switchdev.c +++ b/drivers/net/dsa/mv88e6xxx/switchdev.c @@ -12,6 +12,25 @@ #include "global1.h" #include "switchdev.h" +void mv88e6xxx_set_fdb_offloaded(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid) +{ + struct switchdev_notifier_fdb_info info = { + .addr = addr, + .vid = vid, + .offloaded = true, + }; + struct net_device *brport; + struct dsa_port *dp; + + dp = dsa_to_port(ds, port); + brport = dsa_port_to_bridge_port(dp); + + if (brport) + call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, + brport, &info.info, NULL); +} + struct mv88e6xxx_fid_search_ctx { u16 fid_search; u16 vid_found; @@ -81,3 +100,45 @@ int mv88e6xxx_handle_miss_violation(struct mv88e6xxx_chip *chip, int port, return err; } + +int mv88e6xxx_handle_age_out_violation(struct mv88e6xxx_chip *chip, int port, + struct mv88e6xxx_atu_entry *entry, + u16 fid) +{ + struct switchdev_notifier_fdb_info info = { + .addr = entry->mac, + }; + struct net_device *brport; + struct dsa_port *dp; + u16 vid; + int err; + + err = mv88e6xxx_find_vid(chip, fid, &vid); + if (err) + return err; + + info.vid = vid; + entry->portvec &= ~BIT(port); + entry->state = MV88E6XXX_G1_ATU_DATA_STATE_UC_UNUSED; + entry->trunk = false; + + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_g1_atu_loadpurge(chip, fid, entry); + mv88e6xxx_reg_unlock(chip); + if (err) + return err; + + dp = dsa_to_port(chip->ds, port); + + rtnl_lock(); + brport = dsa_port_to_bridge_port(dp); + if (!brport) { + rtnl_unlock(); + return -ENODEV; + } + err = call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, + brport, &info.info, NULL); + rtnl_unlock(); + + return err; +} diff --git a/drivers/net/dsa/mv88e6xxx/switchdev.h b/drivers/net/dsa/mv88e6xxx/switchdev.h index 62214f9d62b0..5af6ac6a490a 100644 --- a/drivers/net/dsa/mv88e6xxx/switchdev.h +++ b/drivers/net/dsa/mv88e6xxx/switchdev.h @@ -12,8 +12,13 @@ #include "chip.h" +void mv88e6xxx_set_fdb_offloaded(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid); int mv88e6xxx_handle_miss_violation(struct mv88e6xxx_chip *chip, int port, struct mv88e6xxx_atu_entry *entry, u16 fid); +int mv88e6xxx_handle_age_out_violation(struct mv88e6xxx_chip *chip, int port, + struct mv88e6xxx_atu_entry *entry, + u16 fid); #endif /* _MV88E6XXX_SWITCHDEV_H_ */ diff --git a/drivers/net/dsa/mv88e6xxx/trace.h b/drivers/net/dsa/mv88e6xxx/trace.h index f59ca04768e7..c6b32abf68a5 100644 --- a/drivers/net/dsa/mv88e6xxx/trace.h +++ b/drivers/net/dsa/mv88e6xxx/trace.h @@ -40,6 +40,11 @@ DECLARE_EVENT_CLASS(mv88e6xxx_atu_violation, __entry->addr, __entry->fid) ); +DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_age_out_violation, + TP_PROTO(const struct device *dev, int spid, u16 portvec, + const unsigned char *addr, u16 fid), + TP_ARGS(dev, spid, portvec, addr, fid)); + DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_member_violation, TP_PROTO(const struct device *dev, int spid, u16 portvec, const unsigned char *addr, u16 fid), -- 2.34.1
Hans J. Schultz
2023-Mar-18 14:10 UTC
[Bridge] [PATCH v2 net-next 6/6] selftests: forwarding: add dynamic FDB test
Test FDB ageing of user entry created by bridge fdb replace ADDR dev <DEV> master dynamic Use LOW_AGEING_TIME variable in forwarding.config to set a low ageing time. Beware, DSA might not accept the ageing time you want. Check the age_time_coeff value for your driver. Signed-off-by: Hans J. Schultz <netdev at kapio-technology.com> --- .../net/forwarding/bridge_locked_port.sh | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tools/testing/selftests/net/forwarding/bridge_locked_port.sh b/tools/testing/selftests/net/forwarding/bridge_locked_port.sh index dc92d32464f6..dbc7017fd45d 100755 --- a/tools/testing/selftests/net/forwarding/bridge_locked_port.sh +++ b/tools/testing/selftests/net/forwarding/bridge_locked_port.sh @@ -14,6 +14,7 @@ ALL_TESTS=" NUM_NETIFS=4 CHECK_TC="no" source lib.sh +source tc_common.sh h1_create() { @@ -319,6 +320,41 @@ locked_port_mab_flush() log_test "Locked port MAB FDB flush" } +# Test of dynamic FDB entries. +locked_port_dyn_fdb() +{ + local mac=00:01:02:03:04:05 + local ageing_time + + RET=0 + ageing_time=$(bridge_ageing_time_get br0) + tc qdisc add dev $swp2 clsact + ip link set dev br0 type bridge ageing_time $LOW_AGEING_TIME + bridge link set dev $swp1 learning on locked on + + bridge fdb replace $mac dev $swp1 master dynamic + tc filter add dev $swp2 egress protocol ip pref 1 handle 1 flower \ + dst_ip 192.0.2.2 ip_proto udp dst_port 12345 action pass + + $MZ $swp1 -c 1 -p 128 -t udp "sp=54321,dp=12345" \ + -a $mac -b `mac_get $h2` -A 192.0.2.1 -B 192.0.2.2 -q + tc_check_packets "dev $swp2 egress" 1 1 + check_err $? "Packet not seen on egress after adding dynamic FDB" + + sleep $((LOW_AGEING_TIME / 100 + 10)) + + $MZ $swp1 -c 1 -p 128 -t udp "sp=54321,dp=12345" \ + -a $mac -b `mac_get $h2` -A 192.0.2.1 -B 192.0.2.2 -q + tc_check_packets "dev $swp2 egress" 1 1 + check_fail $? "Dynamic FDB entry did not age out" + + ip link set dev br0 type bridge ageing_time $ageing_time + bridge link set dev $swp1 learning off locked off + tc qdisc del dev $swp2 clsact + + log_test "Locked port dyn FDB" +} + trap cleanup EXIT setup_prepare -- 2.34.1