In a non-LACP balance-slb bond, bond_check_admissibility() drops all
multicast (and broadcast) on members other than the active one.  When an
upstream switch snoops IGMP/MLD and forwards a group to a single member,
that member may not be the bond's active one, so the group is dropped and
a receiver behind the bond loses the stream.

other_config:all-members-active already lets such traffic through, but it
also admits broadcast, which a flooding switch then duplicates.  For the
snooped-multicast case broadcast admission is not wanted.

Add other_config:multicast-all-members-active, which admits multicast but
not broadcast on secondary members of a balance-slb bond.  It takes
priority over all-members-active: when both are set, broadcast is dropped.
Off by default.

Signed-off-by: Sola Zhang <[email protected]>
---
RFC notes (not part of the commit):

I would like to discuss whether adding this as a separate knob is
acceptable.

A production XenServer deployment loses a snooped multicast stream to a VM
behind a balance-slb bond: the upstream switch snoops IGMP and forwards the
group on only one bond member, which need not be OVS's active member, so
bond_check_admissibility() drops it before the mcast-snooping lookup.

other_config:all-members-active (1b53826d6c74, RHBZ 1720935) already lets
such traffic through, but it also admits broadcast, which a flooding switch
delivers on every member and thus duplicates.  Since RHBZ 1720935 itself
relies on admitting broadcast (ARP), I did not want to change
all-members-active, so this adds a separate, higher-priority
'multicast-all-members-active' that admits multicast only.

Does adding this as a separate knob look acceptable?

 NEWS                 |  3 +++
 ofproto/bond.c       | 21 +++++++++++++++++++--
 ofproto/bond.h       |  3 +++
 vswitchd/bridge.c    |  4 ++++
 vswitchd/vswitch.xml | 17 +++++++++++++++++
 5 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index de1a030ad..577e725e4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 Post-v4.0.0
 --------------------
+   - New configuration knob 'other_config:multicast-all-members-active' for
+     balance-slb bonds, admitting multicast but not broadcast on non-active
+     members.
 
 
 v4.0.0 - 17 Aug 2026
diff --git a/ofproto/bond.c b/ofproto/bond.c
index ef481a360..2311424f3 100644
--- a/ofproto/bond.c
+++ b/ofproto/bond.c
@@ -127,6 +127,10 @@ struct bond {
                                    Applicable only for Balance TCP mode. */
     bool all_members_active;    /* Accept multicast packets on secondary
                                    members of a non-LACP Balance SLB bond. */
+    bool multicast_all_members_active; /* Accept multicast but not broadcast on
+                                          secondary members of a Balance SLB
+                                          bond.  Takes priority over
+                                          all_members_active. */
     char *primary;              /* Name of the primary member. */
 
     /* SLB specific bonding info. */
@@ -503,6 +507,8 @@ bond_reconfigure(struct bond *bond, const struct 
bond_settings *s)
 
     bond->all_members_active = (bond->balance == BM_SLB)
                                ? s->all_members_active : false;
+    bond->multicast_all_members_active =
+        (bond->balance == BM_SLB) ? s->multicast_all_members_active : false;
 
     if (bond->balance != BM_AB) {
         if (!bond->recirc_id) {
@@ -931,9 +937,18 @@ bond_check_admissibility(struct bond *bond, const void 
*member_,
         break;
     }
 
-    /* Drop all multicast packets on inactive members. */
+    /* Drop broadcast/multicast packets on inactive members.
+     *
+     * 'multicast_all_members_active' admits multicast but not broadcast,
+     * and takes priority over 'all_members_active' (which admits both). */
     if (eth_addr_is_multicast(eth_dst)) {
-        if (bond->active_member != member && !bond->all_members_active) {
+        bool admit;
+        if (bond->multicast_all_members_active) {
+            admit = !eth_addr_is_broadcast(eth_dst);
+        } else {
+            admit = bond->all_members_active;
+        }
+        if (bond->active_member != member && !admit) {
             goto out;
         }
     }
@@ -1567,6 +1582,8 @@ bond_print_details(struct ds *ds, const struct bond *bond)
     if (bond->balance == BM_SLB) {
         ds_put_format(ds, "all members active: %s\n",
                       bond->all_members_active ? "true" : "false");
+        ds_put_format(ds, "multicast all members active: %s\n",
+                      bond->multicast_all_members_active ? "true" : "false");
     }
 
     ds_put_format(ds, "updelay: %d ms\n", bond->updelay);
diff --git a/ofproto/bond.h b/ofproto/bond.h
index 3aa5c640d..f3e47f58c 100644
--- a/ofproto/bond.h
+++ b/ofproto/bond.h
@@ -65,6 +65,9 @@ struct bond_settings {
     bool all_members_active;    /* Accept multicast packets on secondary
                                    interface. Only applicable for non-LACP
                                    BALANCE SLB bond mode. */
+    bool multicast_all_members_active; /* Like all_members_active but admits
+                                          multicast only, not broadcast. Takes
+                                          priority over all_members_active. */
 };
 
 /* Program startup. */
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index c00abd295..9fcf5da3e 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -4755,6 +4755,10 @@ port_configure_bond(struct port *port, struct 
bond_settings *s)
     /* all_members_active is disabled by default. */
     s->all_members_active = smap_get_bool(&port->cfg->other_config,
                                           "all-members-active", false);
+    /* multicast_all_members_active is disabled by default. */
+    s->multicast_all_members_active =
+        smap_get_bool(&port->cfg->other_config,
+                      "multicast-all-members-active", false);
 }
 
 /* Returns true if 'port' is synthetic, that is, if we constructed it locally
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 4eec70fe4..57216cffa 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -2259,6 +2259,23 @@
         </p>
       </column>
 
+      <column name="other_config" key="multicast-all-members-active"
+              type='{"type": "boolean"}'>
+        <p>
+          Enable/Disable delivery of multicast (but not broadcast) packets on
+          secondary interface of a balance-slb bond.  Relevant only when
+          <ref column="lacp"/> is <code>off</code>.
+        </p>
+        <p>
+          This is like <code>all-members-active</code> but admits only
+          multicast; broadcast is still dropped on secondary members.  It is
+          useful when an upstream switch snoops IGMP/MLD and forwards a group
+          to a single member, which may not be the active one.  It takes
+          priority over <code>all-members-active</code>: when both are set,
+          broadcast is dropped.  Disabled by default.
+        </p>
+      </column>
+
       <group title="Link Failure Detection">
         <p>
           An important part of link bonding is detecting that links are down so
-- 
2.51.0.windows.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to