| Message ID | 20250522195952.29265-6-linus.luessing@c0d3.blue |
|---|---|
| State | New |
| Headers | show |
| Series | net: bridge: propagate safe mcast snooping to switchdev + DSA | expand |
Hi Linus, kernel test robot noticed the following build warnings: [auto build test WARNING on net/main] [also build test WARNING on linus/master v6.15-rc7 next-20250522] [cannot apply to net-next/main horms-ipvs/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Linus-L-ssing/net-bridge-mcast-explicitly-track-active-state/20250523-040914 base: net/main patch link: https://lore.kernel.org/r/20250522195952.29265-6-linus.luessing%40c0d3.blue patch subject: [PATCH net-next 5/5] net: dsa: forward bridge/switchdev mcast active notification config: i386-randconfig-001-20250523 (https://download.01.org/0day-ci/archive/20250523/202505231706.fkxIDjje-lkp@intel.com/config) compiler: clang version 20.1.2 (https://github.com/llvm/llvm-project 58df0ef89dd64126512e4ee27b4ac3fd8ddf6247) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250523/202505231706.fkxIDjje-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202505231706.fkxIDjje-lkp@intel.com/ All warnings (new ones prefixed by >>): >> net/dsa/user.c:661:3: warning: label followed by a declaration is a C23 extension [-Wc23-extensions] 661 | const bool *handled = ctx; | ^ net/dsa/user.c:3770:3: warning: label followed by a declaration is a C23 extension [-Wc23-extensions] 3770 | struct switchdev_notifier_port_attr_info *item = ptr; | ^ net/dsa/user.c:3813:3: warning: label followed by a declaration is a C23 extension [-Wc23-extensions] 3813 | struct switchdev_notifier_port_attr_info *item = ptr; | ^ 3 warnings generated. vim +661 net/dsa/user.c 598 599 static int dsa_user_port_attr_set(struct net_device *dev, const void *ctx, 600 const struct switchdev_attr *attr, 601 struct netlink_ext_ack *extack) 602 { 603 struct dsa_port *dp = dsa_user_to_port(dev); 604 int ret; 605 606 if (ctx && ctx != dp && attr->id != SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE) 607 return 0; 608 609 switch (attr->id) { 610 case SWITCHDEV_ATTR_ID_PORT_STP_STATE: 611 if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev)) 612 return -EOPNOTSUPP; 613 614 ret = dsa_port_set_state(dp, attr->u.stp_state, true); 615 break; 616 case SWITCHDEV_ATTR_ID_PORT_MST_STATE: 617 if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev)) 618 return -EOPNOTSUPP; 619 620 ret = dsa_port_set_mst_state(dp, &attr->u.mst_state, extack); 621 break; 622 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: 623 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 624 return -EOPNOTSUPP; 625 626 ret = dsa_port_vlan_filtering(dp, attr->u.vlan_filtering, 627 extack); 628 break; 629 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: 630 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 631 return -EOPNOTSUPP; 632 633 ret = dsa_port_ageing_time(dp, attr->u.ageing_time); 634 break; 635 case SWITCHDEV_ATTR_ID_BRIDGE_MST: 636 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 637 return -EOPNOTSUPP; 638 639 ret = dsa_port_mst_enable(dp, attr->u.mst, extack); 640 break; 641 case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: 642 if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev)) 643 return -EOPNOTSUPP; 644 645 ret = dsa_port_pre_bridge_flags(dp, attr->u.brport_flags, 646 extack); 647 break; 648 case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: 649 if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev)) 650 return -EOPNOTSUPP; 651 652 ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, extack); 653 break; 654 case SWITCHDEV_ATTR_ID_VLAN_MSTI: 655 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 656 return -EOPNOTSUPP; 657 658 ret = dsa_port_vlan_msti(dp, &attr->u.vlan_msti); 659 break; 660 case SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE: > 661 const bool *handled = ctx; 662 663 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 664 return -EOPNOTSUPP; 665 666 ret = dsa_port_bridge_mdb_active(dp, attr->u.mc_active, extack, 667 *handled); 668 break; 669 default: 670 ret = -EOPNOTSUPP; 671 break; 672 } 673 674 return ret; 675 } 676
Hi Linus, kernel test robot noticed the following build errors: [auto build test ERROR on net/main] [also build test ERROR on linus/master v6.15-rc7 next-20250523] [cannot apply to net-next/main horms-ipvs/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Linus-L-ssing/net-bridge-mcast-explicitly-track-active-state/20250523-040914 base: net/main patch link: https://lore.kernel.org/r/20250522195952.29265-6-linus.luessing%40c0d3.blue patch subject: [PATCH net-next 5/5] net: dsa: forward bridge/switchdev mcast active notification config: s390-randconfig-001-20250523 (https://download.01.org/0day-ci/archive/20250523/202505231753.V7E84RiN-lkp@intel.com/config) compiler: s390-linux-gcc (GCC) 8.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250523/202505231753.V7E84RiN-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202505231753.V7E84RiN-lkp@intel.com/ All errors (new ones prefixed by >>): net/dsa/user.c: In function 'dsa_user_port_attr_set': >> net/dsa/user.c:661:3: error: a label can only be part of a statement and a declaration is not a statement const bool *handled = ctx; ^~~~~ net/dsa/user.c: In function 'dsa_user_switchdev_event': net/dsa/user.c:3770:3: error: a label can only be part of a statement and a declaration is not a statement struct switchdev_notifier_port_attr_info *item = ptr; ^~~~~~ net/dsa/user.c: In function 'dsa_user_switchdev_blocking_event': net/dsa/user.c:3813:3: error: a label can only be part of a statement and a declaration is not a statement struct switchdev_notifier_port_attr_info *item = ptr; ^~~~~~ vim +661 net/dsa/user.c 598 599 static int dsa_user_port_attr_set(struct net_device *dev, const void *ctx, 600 const struct switchdev_attr *attr, 601 struct netlink_ext_ack *extack) 602 { 603 struct dsa_port *dp = dsa_user_to_port(dev); 604 int ret; 605 606 if (ctx && ctx != dp && attr->id != SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE) 607 return 0; 608 609 switch (attr->id) { 610 case SWITCHDEV_ATTR_ID_PORT_STP_STATE: 611 if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev)) 612 return -EOPNOTSUPP; 613 614 ret = dsa_port_set_state(dp, attr->u.stp_state, true); 615 break; 616 case SWITCHDEV_ATTR_ID_PORT_MST_STATE: 617 if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev)) 618 return -EOPNOTSUPP; 619 620 ret = dsa_port_set_mst_state(dp, &attr->u.mst_state, extack); 621 break; 622 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: 623 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 624 return -EOPNOTSUPP; 625 626 ret = dsa_port_vlan_filtering(dp, attr->u.vlan_filtering, 627 extack); 628 break; 629 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: 630 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 631 return -EOPNOTSUPP; 632 633 ret = dsa_port_ageing_time(dp, attr->u.ageing_time); 634 break; 635 case SWITCHDEV_ATTR_ID_BRIDGE_MST: 636 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 637 return -EOPNOTSUPP; 638 639 ret = dsa_port_mst_enable(dp, attr->u.mst, extack); 640 break; 641 case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: 642 if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev)) 643 return -EOPNOTSUPP; 644 645 ret = dsa_port_pre_bridge_flags(dp, attr->u.brport_flags, 646 extack); 647 break; 648 case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: 649 if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev)) 650 return -EOPNOTSUPP; 651 652 ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, extack); 653 break; 654 case SWITCHDEV_ATTR_ID_VLAN_MSTI: 655 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 656 return -EOPNOTSUPP; 657 658 ret = dsa_port_vlan_msti(dp, &attr->u.vlan_msti); 659 break; 660 case SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE: > 661 const bool *handled = ctx; 662 663 if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) 664 return -EOPNOTSUPP; 665 666 ret = dsa_port_bridge_mdb_active(dp, attr->u.mc_active, extack, 667 *handled); 668 break; 669 default: 670 ret = -EOPNOTSUPP; 671 break; 672 } 673 674 return ret; 675 } 676
diff --git a/Documentation/networking/dsa/dsa.rst b/Documentation/networking/dsa/dsa.rst index 7b2e69cd7ef0..0b0be619be04 100644 --- a/Documentation/networking/dsa/dsa.rst +++ b/Documentation/networking/dsa/dsa.rst @@ -1025,6 +1025,15 @@ Bridge VLAN filtering the specified MAC address from the specified VLAN ID if it was mapped into this port forwarding database. +- ``port_mdb_active``: bridge layer function invoked when the bridge starts (or + stops) to actively apply multicast snooping to multicast payload, i.e. when + multicast snooping is enabled and a multicast querier is present on the link + for a particular protocol family (or not). A switch should (by default) ensure: + To flood multicast packets for the given protocol family if multicast snooping + is inactive - to avoid multicast (and consequently also IPv6 unicast, which + depends on multicast for NDP) packet loss. And should (by default) avoid + forwarding to an active port if there is no listener or multicast router on it. + Link aggregation ---------------- diff --git a/include/net/dsa.h b/include/net/dsa.h index a0a9481c52c2..edc0e6821ba2 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -1080,6 +1080,11 @@ struct dsa_switch_ops { int (*port_mdb_del)(struct dsa_switch *ds, int port, const struct switchdev_obj_port_mdb *mdb, struct dsa_db db); + int (*port_mdb_active)(struct dsa_switch *ds, int port, + const struct switchdev_mc_active mc_active, + struct netlink_ext_ack *extack, + bool handled); + /* * RXNFC */ diff --git a/net/dsa/port.c b/net/dsa/port.c index 5c9d1798e830..a1e692d9122e 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -1290,6 +1290,25 @@ int dsa_port_bridge_host_mdb_del(const struct dsa_port *dp, return dsa_port_host_mdb_del(dp, mdb, db); } +int dsa_port_bridge_mdb_active(const struct dsa_port *dp, + const struct switchdev_mc_active mc_active, + struct netlink_ext_ack *extack, + bool handled) +{ + struct dsa_switch *ds = dp->ds; + struct dsa_notifier_mdb_active_info info = { + .dp = dp, + .mc_active = mc_active, + .extack = extack, + .handled = handled, + }; + + if (!ds->ops->port_mdb_active) + return -EOPNOTSUPP; + + return dsa_port_notify(dp, DSA_NOTIFIER_MDB_ACTIVE, &info); +} + int dsa_port_vlan_add(struct dsa_port *dp, const struct switchdev_obj_port_vlan *vlan, struct netlink_ext_ack *extack) diff --git a/net/dsa/port.h b/net/dsa/port.h index 6bc3291573c0..0e92815e7de2 100644 --- a/net/dsa/port.h +++ b/net/dsa/port.h @@ -75,6 +75,9 @@ int dsa_port_bridge_host_mdb_add(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb); int dsa_port_bridge_host_mdb_del(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb); +int dsa_port_bridge_mdb_active(const struct dsa_port *dp, + const struct switchdev_mc_active mc_active, + struct netlink_ext_ack *extack, bool handled); int dsa_port_pre_bridge_flags(const struct dsa_port *dp, struct switchdev_brport_flags flags, struct netlink_ext_ack *extack); diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 3d2feeea897b..5b30dfe4bebd 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -652,6 +652,16 @@ static int dsa_switch_host_mdb_del(struct dsa_switch *ds, return err; } +static int dsa_switch_mdb_active(struct dsa_switch *ds, + struct dsa_notifier_mdb_active_info *info) +{ + if (!ds->ops->port_mdb_active) + return -EOPNOTSUPP; + + return ds->ops->port_mdb_active(ds, info->dp->index, info->mc_active, + info->extack, info->handled); +} + /* Port VLANs match on the targeted port and on all DSA ports */ static bool dsa_port_vlan_match(struct dsa_port *dp, struct dsa_notifier_vlan_info *info) @@ -1026,6 +1036,9 @@ static int dsa_switch_event(struct notifier_block *nb, case DSA_NOTIFIER_HOST_MDB_DEL: err = dsa_switch_host_mdb_del(ds, info); break; + case DSA_NOTIFIER_MDB_ACTIVE: + err = dsa_switch_mdb_active(ds, info); + break; case DSA_NOTIFIER_VLAN_ADD: err = dsa_switch_vlan_add(ds, info); break; diff --git a/net/dsa/switch.h b/net/dsa/switch.h index be0a2749cd97..69a5004e48c8 100644 --- a/net/dsa/switch.h +++ b/net/dsa/switch.h @@ -24,6 +24,7 @@ enum { DSA_NOTIFIER_MDB_DEL, DSA_NOTIFIER_HOST_MDB_ADD, DSA_NOTIFIER_HOST_MDB_DEL, + DSA_NOTIFIER_MDB_ACTIVE, DSA_NOTIFIER_VLAN_ADD, DSA_NOTIFIER_VLAN_DEL, DSA_NOTIFIER_HOST_VLAN_ADD, @@ -66,13 +67,21 @@ struct dsa_notifier_lag_fdb_info { struct dsa_db db; }; -/* DSA_NOTIFIER_MDB_* */ +/* DSA_NOTIFIER_MDB_{ADD,DEL} */ struct dsa_notifier_mdb_info { const struct dsa_port *dp; const struct switchdev_obj_port_mdb *mdb; struct dsa_db db; }; +/* DSA_NOTIFIER_MDB_ACTIVE */ +struct dsa_notifier_mdb_active_info { + const struct dsa_port *dp; + const struct switchdev_mc_active mc_active; + struct netlink_ext_ack *extack; + int handled; +}; + /* DSA_NOTIFIER_LAG_* */ struct dsa_notifier_lag_info { const struct dsa_port *dp; diff --git a/net/dsa/user.c b/net/dsa/user.c index 804dc7dac4f2..231b92d6e7b9 100644 --- a/net/dsa/user.c +++ b/net/dsa/user.c @@ -603,7 +603,7 @@ static int dsa_user_port_attr_set(struct net_device *dev, const void *ctx, struct dsa_port *dp = dsa_user_to_port(dev); int ret; - if (ctx && ctx != dp) + if (ctx && ctx != dp && attr->id != SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE) return 0; switch (attr->id) { @@ -657,6 +657,15 @@ static int dsa_user_port_attr_set(struct net_device *dev, const void *ctx, ret = dsa_port_vlan_msti(dp, &attr->u.vlan_msti); break; + case SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE: + const bool *handled = ctx; + + if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) + return -EOPNOTSUPP; + + ret = dsa_port_bridge_mdb_active(dp, attr->u.mc_active, extack, + *handled); + break; default: ret = -EOPNOTSUPP; break; @@ -3758,6 +3767,11 @@ static int dsa_user_switchdev_event(struct notifier_block *unused, switch (event) { case SWITCHDEV_PORT_ATTR_SET: + struct switchdev_notifier_port_attr_info *item = ptr; + + if (item && item->attr->id == SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE) + item->info.ctx = &item->handled; + err = switchdev_handle_port_attr_set(dev, ptr, dsa_user_dev_check, dsa_user_port_attr_set); @@ -3796,6 +3810,11 @@ static int dsa_user_switchdev_blocking_event(struct notifier_block *unused, dsa_user_port_obj_del); return notifier_from_errno(err); case SWITCHDEV_PORT_ATTR_SET: + struct switchdev_notifier_port_attr_info *item = ptr; + + if (item && item->attr->id == SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE) + item->info.ctx = &item->handled; + err = switchdev_handle_port_attr_set(dev, ptr, dsa_user_dev_check, dsa_user_port_attr_set);
Add a new "port_mdb_active()" handler to the DSA API. This allows DSA drivers to receive the multicast active notification from the bridge. So that switch drivers can act on it accordingly, especially to avoid packetloss. The switchdev notifier "handled" attribute is propagated, too, so that a DSA based switch driver can decide whether it wants to act on the event for each port individually or only on the first one, on behalf of all others. Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue> --- Documentation/networking/dsa/dsa.rst | 9 +++++++++ include/net/dsa.h | 5 +++++ net/dsa/port.c | 19 +++++++++++++++++++ net/dsa/port.h | 3 +++ net/dsa/switch.c | 13 +++++++++++++ net/dsa/switch.h | 11 ++++++++++- net/dsa/user.c | 21 ++++++++++++++++++++- 7 files changed, 79 insertions(+), 2 deletions(-)