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.

Merge branch 'add-support-for-mdb-offload-failure-notification'

Joseph Huang says:

====================
Add support for mdb offload failure notification

Currently the bridge does not provide real-time feedback to user space
on whether or not an attempt to offload an mdb entry was successful.

This patch set adds support to notify user space about failed offload
attempts, and is controlled by a new knob mdb_offload_fail_notification.

A break-down of the patches in the series:

Patch 1 adds offload failed flag to indicate that the offload attempt
has failed. The flag is reflected in netlink mdb entry flags.

Patch 2 adds the new bridge bool option mdb_offload_fail_notification.

Patch 3 notifies user space when the result is known, controlled by
mdb_offload_fail_notification setting.
====================

Link: https://patch.msgid.link/20250411150323.1117797-1-Joseph.Huang@garmin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+68 -18
+6 -4
include/uapi/linux/if_bridge.h
··· 699 699 #define MDB_TEMPORARY 0 700 700 #define MDB_PERMANENT 1 701 701 __u8 state; 702 - #define MDB_FLAGS_OFFLOAD (1 << 0) 703 - #define MDB_FLAGS_FAST_LEAVE (1 << 1) 704 - #define MDB_FLAGS_STAR_EXCL (1 << 2) 705 - #define MDB_FLAGS_BLOCKED (1 << 3) 702 + #define MDB_FLAGS_OFFLOAD (1 << 0) 703 + #define MDB_FLAGS_FAST_LEAVE (1 << 1) 704 + #define MDB_FLAGS_STAR_EXCL (1 << 2) 705 + #define MDB_FLAGS_BLOCKED (1 << 3) 706 + #define MDB_FLAGS_OFFLOAD_FAILED (1 << 4) 706 707 __u8 flags; 707 708 __u16 vid; 708 709 struct { ··· 831 830 BR_BOOLOPT_NO_LL_LEARN, 832 831 BR_BOOLOPT_MCAST_VLAN_SNOOPING, 833 832 BR_BOOLOPT_MST_ENABLE, 833 + BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION, 834 834 BR_BOOLOPT_MAX 835 835 }; 836 836
+5
net/bridge/br.c
··· 284 284 case BR_BOOLOPT_MST_ENABLE: 285 285 err = br_mst_set_enabled(br, on, extack); 286 286 break; 287 + case BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION: 288 + br_opt_toggle(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION, on); 289 + break; 287 290 default: 288 291 /* shouldn't be called with unsupported options */ 289 292 WARN_ON(1); ··· 305 302 return br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED); 306 303 case BR_BOOLOPT_MST_ENABLE: 307 304 return br_opt_get(br, BROPT_MST_ENABLED); 305 + case BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION: 306 + return br_opt_get(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION); 308 307 default: 309 308 /* shouldn't be called with unsupported options */ 310 309 WARN_ON(1);
+23 -5
net/bridge/br_mdb.c
··· 144 144 e->flags |= MDB_FLAGS_STAR_EXCL; 145 145 if (flags & MDB_PG_FLAGS_BLOCKED) 146 146 e->flags |= MDB_FLAGS_BLOCKED; 147 + if (flags & MDB_PG_FLAGS_OFFLOAD_FAILED) 148 + e->flags |= MDB_FLAGS_OFFLOAD_FAILED; 147 149 } 148 150 149 151 static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip, ··· 519 517 rtnl_mdb_nlmsg_pg_size(pg); 520 518 } 521 519 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) 520 + static void __br_mdb_notify(struct net_device *dev, 521 + struct net_bridge_mdb_entry *mp, 522 + struct net_bridge_port_group *pg, 523 + int type, bool notify_switchdev) 526 524 { 527 525 struct net *net = dev_net(dev); 528 526 struct sk_buff *skb; 529 527 int err = -ENOBUFS; 530 528 531 - br_switchdev_mdb_notify(dev, mp, pg, type); 529 + if (notify_switchdev) 530 + br_switchdev_mdb_notify(dev, mp, pg, type); 532 531 533 532 skb = nlmsg_new(rtnl_mdb_nlmsg_size(pg), GFP_ATOMIC); 534 533 if (!skb) ··· 545 542 return; 546 543 errout: 547 544 rtnl_set_sk_err(net, RTNLGRP_MDB, err); 545 + } 546 + 547 + void br_mdb_notify(struct net_device *dev, 548 + struct net_bridge_mdb_entry *mp, 549 + struct net_bridge_port_group *pg, 550 + int type) 551 + { 552 + __br_mdb_notify(dev, mp, pg, type, true); 553 + } 554 + 555 + void br_mdb_flag_change_notify(struct net_device *dev, 556 + struct net_bridge_mdb_entry *mp, 557 + struct net_bridge_port_group *pg) 558 + { 559 + __br_mdb_notify(dev, mp, pg, RTM_NEWMDB, false); 548 560 } 549 561 550 562 static int nlmsg_populate_rtr_fill(struct sk_buff *skb,
+25 -5
net/bridge/br_private.h
··· 306 306 u16 vlan_id; 307 307 }; 308 308 309 - #define MDB_PG_FLAGS_PERMANENT BIT(0) 310 - #define MDB_PG_FLAGS_OFFLOAD BIT(1) 311 - #define MDB_PG_FLAGS_FAST_LEAVE BIT(2) 312 - #define MDB_PG_FLAGS_STAR_EXCL BIT(3) 313 - #define MDB_PG_FLAGS_BLOCKED BIT(4) 309 + #define MDB_PG_FLAGS_PERMANENT BIT(0) 310 + #define MDB_PG_FLAGS_OFFLOAD BIT(1) 311 + #define MDB_PG_FLAGS_FAST_LEAVE BIT(2) 312 + #define MDB_PG_FLAGS_STAR_EXCL BIT(3) 313 + #define MDB_PG_FLAGS_BLOCKED BIT(4) 314 + #define MDB_PG_FLAGS_OFFLOAD_FAILED BIT(5) 314 315 315 316 #define PG_SRC_ENT_LIMIT 32 316 317 ··· 484 483 BROPT_VLAN_BRIDGE_BINDING, 485 484 BROPT_MCAST_VLAN_SNOOPING_ENABLED, 486 485 BROPT_MST_ENABLED, 486 + BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION, 487 487 }; 488 488 489 489 struct net_bridge { ··· 1004 1002 void br_mdb_hash_fini(struct net_bridge *br); 1005 1003 void br_mdb_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp, 1006 1004 struct net_bridge_port_group *pg, int type); 1005 + void br_mdb_flag_change_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp, 1006 + struct net_bridge_port_group *pg); 1007 1007 void br_rtr_notify(struct net_device *dev, struct net_bridge_mcast_port *pmctx, 1008 1008 int type); 1009 1009 void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, ··· 1345 1341 BROPT_MCAST_VLAN_SNOOPING_ENABLED); 1346 1342 1347 1343 return !!(vlan_snooping_enabled == br_multicast_ctx_is_vlan(brmctx)); 1344 + } 1345 + 1346 + static inline void 1347 + br_multicast_set_pg_offload_flags(struct net_bridge_port_group *p, 1348 + bool offloaded) 1349 + { 1350 + p->flags &= ~(MDB_PG_FLAGS_OFFLOAD | MDB_PG_FLAGS_OFFLOAD_FAILED); 1351 + p->flags |= (offloaded ? MDB_PG_FLAGS_OFFLOAD : 1352 + MDB_PG_FLAGS_OFFLOAD_FAILED); 1353 + } 1354 + 1355 + static inline bool 1356 + br_mdb_should_notify(const struct net_bridge *br, u8 changed_flags) 1357 + { 1358 + return br_opt_get(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION) && 1359 + (changed_flags & MDB_PG_FLAGS_OFFLOAD_FAILED); 1348 1360 } 1349 1361 #else 1350 1362 static inline int br_multicast_rcv(struct net_bridge_mcast **brmctx,
+9 -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 - if (err) 509 - goto err; 509 + if (err == -EOPNOTSUPP) 510 + goto out_free; 510 511 511 512 spin_lock_bh(&br->multicast_lock); 512 513 mp = br_mdb_ip_get(br, &data->ip); ··· 517 516 pp = &p->next) { 518 517 if (p->key.port != port) 519 518 continue; 520 - p->flags |= MDB_PG_FLAGS_OFFLOAD; 519 + 520 + old_flags = p->flags; 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); 521 524 } 522 525 out: 523 526 spin_unlock_bh(&br->multicast_lock); 524 - err: 527 + out_free: 525 528 kfree(priv); 526 529 } 527 530