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

net: bridge: mcast: Notify on mdb offload failure

Notify user space on mdb offload failure if
mdb_offload_fail_notification is enabled.

Signed-off-by: Joseph Huang <Joseph.Huang@garmin.com>
Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/20250411150323.1117797-4-Joseph.Huang@garmin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Joseph Huang and committed by
Jakub Kicinski
c428d43d 9fbe1e3e

+34 -5
+21 -5
net/bridge/br_mdb.c
··· 519 519 rtnl_mdb_nlmsg_pg_size(pg); 520 520 } 521 521 522 - void br_mdb_notify(struct net_device *dev, 523 - struct net_bridge_mdb_entry *mp, 524 - struct net_bridge_port_group *pg, 525 - int type) 522 + static void __br_mdb_notify(struct net_device *dev, 523 + struct net_bridge_mdb_entry *mp, 524 + struct net_bridge_port_group *pg, 525 + int type, bool notify_switchdev) 526 526 { 527 527 struct net *net = dev_net(dev); 528 528 struct sk_buff *skb; 529 529 int err = -ENOBUFS; 530 530 531 - br_switchdev_mdb_notify(dev, mp, pg, type); 531 + if (notify_switchdev) 532 + br_switchdev_mdb_notify(dev, mp, pg, type); 532 533 533 534 skb = nlmsg_new(rtnl_mdb_nlmsg_size(pg), GFP_ATOMIC); 534 535 if (!skb) ··· 545 544 return; 546 545 errout: 547 546 rtnl_set_sk_err(net, RTNLGRP_MDB, err); 547 + } 548 + 549 + void br_mdb_notify(struct net_device *dev, 550 + struct net_bridge_mdb_entry *mp, 551 + struct net_bridge_port_group *pg, 552 + int type) 553 + { 554 + __br_mdb_notify(dev, mp, pg, type, true); 555 + } 556 + 557 + void br_mdb_flag_change_notify(struct net_device *dev, 558 + struct net_bridge_mdb_entry *mp, 559 + struct net_bridge_port_group *pg) 560 + { 561 + __br_mdb_notify(dev, mp, pg, RTM_NEWMDB, false); 548 562 } 549 563 550 564 static int nlmsg_populate_rtr_fill(struct sk_buff *skb,
+9
net/bridge/br_private.h
··· 1004 1004 void br_mdb_hash_fini(struct net_bridge *br); 1005 1005 void br_mdb_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp, 1006 1006 struct net_bridge_port_group *pg, int type); 1007 + void br_mdb_flag_change_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp, 1008 + struct net_bridge_port_group *pg); 1007 1009 void br_rtr_notify(struct net_device *dev, struct net_bridge_mcast_port *pmctx, 1008 1010 int type); 1009 1011 void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, ··· 1354 1352 p->flags &= ~(MDB_PG_FLAGS_OFFLOAD | MDB_PG_FLAGS_OFFLOAD_FAILED); 1355 1353 p->flags |= (offloaded ? MDB_PG_FLAGS_OFFLOAD : 1356 1354 MDB_PG_FLAGS_OFFLOAD_FAILED); 1355 + } 1356 + 1357 + static inline bool 1358 + br_mdb_should_notify(const struct net_bridge *br, u8 changed_flags) 1359 + { 1360 + return br_opt_get(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION) && 1361 + (changed_flags & MDB_PG_FLAGS_OFFLOAD_FAILED); 1357 1362 } 1358 1363 #else 1359 1364 static inline int br_multicast_rcv(struct net_bridge_mcast **brmctx,
+4
net/bridge/br_switchdev.c
··· 504 504 struct net_bridge_mdb_entry *mp; 505 505 struct net_bridge_port *port = data->port; 506 506 struct net_bridge *br = port->br; 507 + u8 old_flags; 507 508 508 509 if (err == -EOPNOTSUPP) 509 510 goto out_free; ··· 518 517 if (p->key.port != port) 519 518 continue; 520 519 520 + old_flags = p->flags; 521 521 br_multicast_set_pg_offload_flags(p, !err); 522 + if (br_mdb_should_notify(br, old_flags ^ p->flags)) 523 + br_mdb_flag_change_notify(br->dev, mp, p); 522 524 } 523 525 out: 524 526 spin_unlock_bh(&br->multicast_lock);