Skip to content

Commit 6bdba2b

Browse files
committed
net: dsa: flush learned FDB on user port bulk delete
Implement ndo_fdb_del_bulk for DSA so that a bulk RTM_DELNEIGH with NTF_SELF can flush a switch's learned FDB. This is required by user space applications implementing MRP (802.1Q). Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Luke Howard <lukeh@padl.com>
1 parent 464d1e2 commit 6bdba2b

3 files changed

Lines changed: 45 additions & 0 deletions

File tree

net/dsa/port.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,23 @@ static int dsa_port_vlan_fast_age(const struct dsa_port *dp, u16 vid)
8181
return err;
8282
}
8383

84+
/* Flush this port's dynamically learned FDB entries, optionally scoped to a
85+
* VLAN. Honours an MVRP/MMRP "new" declaration (IEEE 802.1Q 11.2.5): after a
86+
* topology change the stale learned entries for the port (and VID) are removed
87+
* so traffic re-learns/floods to the new topology. Falls back to flushing every
88+
* VLAN when the switch has no VLAN-scoped fast age.
89+
*/
90+
int dsa_port_flush_dynamic_fdb(struct dsa_port *dp, u16 vid)
91+
{
92+
struct dsa_switch *ds = dp->ds;
93+
94+
if (vid && ds->ops->port_vlan_fast_age)
95+
return dsa_port_vlan_fast_age(dp, vid);
96+
97+
dsa_port_fast_age(dp);
98+
return 0;
99+
}
100+
84101
static int dsa_port_msti_fast_age(const struct dsa_port *dp, u16 msti)
85102
{
86103
DECLARE_BITMAP(vids, VLAN_N_VID) = { 0 };

net/dsa/port.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ bool dsa_port_supports_hwtstamp(struct dsa_port *dp);
1919
void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp,
2020
const struct dsa_device_ops *tag_ops);
2121
int dsa_port_set_state(struct dsa_port *dp, u8 state, bool do_fast_age);
22+
int dsa_port_flush_dynamic_fdb(struct dsa_port *dp, u16 vid);
2223
int dsa_port_set_mst_state(struct dsa_port *dp,
2324
const struct switchdev_mst_state *state,
2425
struct netlink_ext_ack *extack);

net/dsa/user.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,32 @@ dsa_user_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
575575
return err;
576576
}
577577

578+
static const struct nla_policy dsa_user_fdb_del_bulk_policy[NDA_MAX + 1] = {
579+
[NDA_VLAN] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
580+
[NDA_IFINDEX] = NLA_POLICY_MIN(NLA_S32, 1),
581+
[NDA_NDM_STATE_MASK] = { .type = NLA_U16 },
582+
[NDA_NDM_FLAGS_MASK] = { .type = NLA_U8 },
583+
};
584+
585+
static int dsa_user_fdb_del_bulk(struct nlmsghdr *nlh, struct net_device *dev,
586+
struct netlink_ext_ack *extack)
587+
{
588+
struct dsa_port *dp = dsa_user_to_port(dev);
589+
struct nlattr *tb[NDA_MAX + 1];
590+
u16 vid = 0;
591+
int err;
592+
593+
err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX,
594+
dsa_user_fdb_del_bulk_policy, extack);
595+
if (err)
596+
return err;
597+
598+
if (tb[NDA_VLAN])
599+
vid = nla_get_u16(tb[NDA_VLAN]);
600+
601+
return dsa_port_flush_dynamic_fdb(dp, vid);
602+
}
603+
578604
static int dsa_user_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
579605
{
580606
struct dsa_user_priv *p = netdev_priv(dev);
@@ -2704,6 +2730,7 @@ static const struct net_device_ops dsa_user_netdev_ops = {
27042730
.ndo_set_rx_mode = dsa_user_set_rx_mode,
27052731
.ndo_set_mac_address = dsa_user_set_mac_address,
27062732
.ndo_fdb_dump = dsa_user_fdb_dump,
2733+
.ndo_fdb_del_bulk = dsa_user_fdb_del_bulk,
27072734
.ndo_eth_ioctl = dsa_user_ioctl,
27082735
.ndo_get_iflink = dsa_user_get_iflink,
27092736
#ifdef CONFIG_NET_POLL_CONTROLLER

0 commit comments

Comments
 (0)