Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: dsa: mv88e6xxx: Verify after ATU Load ops

ATU Load operations could fail silently if there's not enough space
on the device to hold the new entry. When this happens, the symptom
depends on the unknown flood settings. If unknown multicast flood is
disabled, the multicast packets are dropped when the ATU table is
full. If unknown multicast flood is enabled, the multicast packets
will be flooded to all ports. Either way, IGMP snooping is broken
when the ATU Load operation fails silently.

Do a Read-After-Write verification after each fdb/mdb add operation
to make sure that the operation was really successful, and return
-ENOSPC otherwise.

Fixes: defb05b9b9b4 ("net: dsa: mv88e6xxx: Add support for fdb_add, fdb_del, and fdb_getnext")
Signed-off-by: Joseph Huang <Joseph.Huang@garmin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20250306172306.3859214-1-Joseph.Huang@garmin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Joseph Huang and committed by
Jakub Kicinski
dc5340c3 d749d901

+48 -11
+48 -11
drivers/net/dsa/mv88e6xxx/chip.c
··· 2208 2208 return err; 2209 2209 } 2210 2210 2211 - static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, 2212 - const unsigned char *addr, u16 vid, 2213 - u8 state) 2211 + static int mv88e6xxx_port_db_get(struct mv88e6xxx_chip *chip, 2212 + const unsigned char *addr, u16 vid, 2213 + u16 *fid, struct mv88e6xxx_atu_entry *entry) 2214 2214 { 2215 - struct mv88e6xxx_atu_entry entry; 2216 2215 struct mv88e6xxx_vtu_entry vlan; 2217 - u16 fid; 2218 2216 int err; 2219 2217 2220 2218 /* Ports have two private address databases: one for when the port is ··· 2223 2225 * VLAN ID into the port's database used for VLAN-unaware bridging. 2224 2226 */ 2225 2227 if (vid == 0) { 2226 - fid = MV88E6XXX_FID_BRIDGED; 2228 + *fid = MV88E6XXX_FID_BRIDGED; 2227 2229 } else { 2228 2230 err = mv88e6xxx_vtu_get(chip, vid, &vlan); 2229 2231 if (err) ··· 2233 2235 if (!vlan.valid) 2234 2236 return -EOPNOTSUPP; 2235 2237 2236 - fid = vlan.fid; 2238 + *fid = vlan.fid; 2237 2239 } 2238 2240 2239 - entry.state = 0; 2240 - ether_addr_copy(entry.mac, addr); 2241 - eth_addr_dec(entry.mac); 2241 + entry->state = 0; 2242 + ether_addr_copy(entry->mac, addr); 2243 + eth_addr_dec(entry->mac); 2242 2244 2243 - err = mv88e6xxx_g1_atu_getnext(chip, fid, &entry); 2245 + return mv88e6xxx_g1_atu_getnext(chip, *fid, entry); 2246 + } 2247 + 2248 + static bool mv88e6xxx_port_db_find(struct mv88e6xxx_chip *chip, 2249 + const unsigned char *addr, u16 vid) 2250 + { 2251 + struct mv88e6xxx_atu_entry entry; 2252 + u16 fid; 2253 + int err; 2254 + 2255 + err = mv88e6xxx_port_db_get(chip, addr, vid, &fid, &entry); 2256 + if (err) 2257 + return false; 2258 + 2259 + return entry.state && ether_addr_equal(entry.mac, addr); 2260 + } 2261 + 2262 + static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, 2263 + const unsigned char *addr, u16 vid, 2264 + u8 state) 2265 + { 2266 + struct mv88e6xxx_atu_entry entry; 2267 + u16 fid; 2268 + int err; 2269 + 2270 + err = mv88e6xxx_port_db_get(chip, addr, vid, &fid, &entry); 2244 2271 if (err) 2245 2272 return err; 2246 2273 ··· 2869 2846 mv88e6xxx_reg_lock(chip); 2870 2847 err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, 2871 2848 MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); 2849 + if (err) 2850 + goto out; 2851 + 2852 + if (!mv88e6xxx_port_db_find(chip, addr, vid)) 2853 + err = -ENOSPC; 2854 + 2855 + out: 2872 2856 mv88e6xxx_reg_unlock(chip); 2873 2857 2874 2858 return err; ··· 6644 6614 mv88e6xxx_reg_lock(chip); 6645 6615 err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, 6646 6616 MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC); 6617 + if (err) 6618 + goto out; 6619 + 6620 + if (!mv88e6xxx_port_db_find(chip, mdb->addr, mdb->vid)) 6621 + err = -ENOSPC; 6622 + 6623 + out: 6647 6624 mv88e6xxx_reg_unlock(chip); 6648 6625 6649 6626 return err;