ovn-ic typically interconnects zones by attaching LRPs to a transit
switch. On that switch, remote LRPs appear as remote LSPs, so OVN floods
IP multicast to them via _MC_flood_l2. Multicast to real LSPs on the
transit switch is still desired, but flooding toward remote LRPs is
useless (they drop it) and scales poorly.

Add LSP options:is_router so CMS can mark those remote LRP-backed ports.
Omit them from _MC_flood_l2 like type=router.

Assisted-by: Claude Opus 5, Cursor
Signed-off-by: Han Zhou <[email protected]>
---
 Documentation/ref/ovn-logical-flows.7.rst |  9 ++--
 NEWS                                      |  3 ++
 lib/mcast-group-index.h                   |  3 +-
 northd/en-multicast.c                     |  5 +-
 northd/northd.h                           | 11 ++++
 ovn-nb.xml                                | 14 +++++
 tests/ovn-northd.at                       | 65 +++++++++++++++++++++++
 7 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/Documentation/ref/ovn-logical-flows.7.rst 
b/Documentation/ref/ovn-logical-flows.7.rst
index 0ec69e39ee71..735e26ffd6f8 100644
--- a/Documentation/ref/ovn-logical-flows.7.rst
+++ b/Documentation/ref/ovn-logical-flows.7.rst
@@ -1460,7 +1460,8 @@ This table implements switching behavior.  It contains 
these logical flows:
 - Priority-90 flows for each IPv4 address/VIP/NAT address owned by a router
   port connected to the switch. These flows match GARP packets for the specific
   IP addresses. Matched packets are forwarded to the ``MC_FLOOD_L2`` multicast
-  group which contains all non-router logical ports.
+  group which contains all non-router logical ports (excluding ports of type
+  ``router`` and ports with ``options:is_router=true``).
 
 - Priority-90 flows for transit switches that forward registered IP multicast
   traffic to their corresponding multicast group , which ``ovn-northd`` creates
@@ -1475,7 +1476,8 @@ This table implements switching behavior.  It contains 
these logical flows:
 
 - A priority-85 flow that forwards all IP multicast traffic destined to
   224.0.0.X to the ``MC_FLOOD_L2`` multicast group, which ``ovn-northd``
-  populates with all non-router logical ports.
+  populates with all non-router logical ports (excluding ports of type
+  ``router`` and ports with ``options:is_router=true``).
 
 - A priority-85 flow that forwards all IP multicast traffic destined to 
reserved
   multicast IPv6 addresses (RFC 4291, 2.7.1, e.g., Solicited-Node multicast) to
@@ -1503,7 +1505,8 @@ This table implements switching behavior.  It contains 
these logical flows:
 
 - Priority-75 flows for each port connected to a logical router matching self
   originated ARP request/RARP request/ND packets.  These packets are flooded to
-  the ``MC_FLOOD_L2`` which contains all non-router logical ports.
+  the ``MC_FLOOD_L2`` which contains all non-router logical ports (excluding
+  ports of type ``router`` and ports with ``options:is_router=true``).
 
 - A priority-72 flow that outputs all ND NA (Neighbor Advertisement), ND RS
   (Router Solicitation) and ND RA (Router Advertisement) packets with an
diff --git a/NEWS b/NEWS
index 44f117807af5..4d466251b397 100644
--- a/NEWS
+++ b/NEWS
@@ -94,6 +94,9 @@ Post v26.03.0
    - Added a new "ovn-debug lflow-pipeline-oftable-start-list" command that
      prints the starting OpenFlow table number of the logical ingress and
      egress pipelines.
+   - northd: Add Logical_Switch_Port option "is_router" to mark an LSP as
+     representing a logical router port when type is not "router" (e.g. IC
+     remote LSPs).  Currently used to omit such ports from _MC_flood_l2.
 
 OVN v26.03.0 - xxx xx xxxx
 --------------------------
diff --git a/lib/mcast-group-index.h b/lib/mcast-group-index.h
index 9664a94dd675..122ab65a5902 100644
--- a/lib/mcast-group-index.h
+++ b/lib/mcast-group-index.h
@@ -43,7 +43,8 @@ enum ovn_mcast_tunnel_keys {
                                           */
     OVN_MCAST_FLOOD_L2_TUNNEL_KEY,       /* Logical switch broadcast domain
                                           * excluding ports towards logical
-                                          * routers.
+                                          * routers (type=router or
+                                          * options:is_router=true).
                                           */
     OVN_MIN_IP_MULTICAST,
     OVN_MAX_IP_MULTICAST = OVN_MAX_MULTICAST,
diff --git a/northd/en-multicast.c b/northd/en-multicast.c
index 5148d88408ae..049afb3fcc38 100644
--- a/northd/en-multicast.c
+++ b/northd/en-multicast.c
@@ -233,7 +233,10 @@ build_mcast_groups(struct multicast_igmp_data *data,
         if (lsp_is_enabled(op->nbsp) && lsp_can_receive_multicast(op->nbsp)) {
             ovn_multicast_add(&data->mcast_groups, &mc_flood, op);
 
-            if (!lsp_is_router(op->nbsp)) {
+            /* Omit type=router ports and ports with options:is_router=true
+             * from MC_FLOOD_L2 (same treatment as real router ports).
+             */
+            if (!lsp_is_router_for_mcast(op->nbsp)) {
                 ovn_multicast_add(&data->mcast_groups, &mc_flood_l2, op);
             }
 
diff --git a/northd/northd.h b/northd/northd.h
index d27f519d6e33..9385015f7a13 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -1155,6 +1155,17 @@ lsp_can_learn_mac(const struct nbrec_logical_switch_port 
*nbsp)
     return smap_get_bool(&nbsp->options, "lsp_learn_fdb", true);
 }
 
+/* True for type=router ports, and for ports marked options:is_router=true
+ * (LSP represents an LRP even if type is not "router").  Currently used to
+ * omit such ports from MC_FLOOD_L2.
+ */
+static inline bool
+lsp_is_router_for_mcast(const struct nbrec_logical_switch_port *nbsp)
+{
+    return lsp_is_router(nbsp)
+           || smap_get_bool(&nbsp->options, "is_router", false);
+}
+
 const char *lrp_find_member_ip(const struct ovn_port *op, const char *ip_s);
 
 /* This function returns true if 'op' is a gateway router port.
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 8a9d19fa9214..43568ea7c911 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1795,6 +1795,20 @@
         </column>
       </group>
 
+      <group title="Options for ports representing routers">
+        <column name="options" key="is_router"
+                type='{"type": "boolean"}'>
+          If set to <code>true</code>, indicate that this logical switch port
+          represents a logical router port, even when
+          <ref column="type"/> is not <code>router</code>.  CMS may set this
+          on ports such as <code>remote</code> LSPs that back LRPs in another
+          OVN interconnection zone.  OVN may use this hint wherever router
+          ports are handled specially; for example, such ports are omitted
+          from the <code>_MC_flood_l2</code> multicast group so IP multicast
+          is not flooded toward them.  Default: <code>false</code>.
+        </column>
+      </group>
+
     </group>
 
     <group title="Containers">
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index d3d9de3b3ce5..54c0eeae1990 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -8745,6 +8745,71 @@ OVN_CLEANUP_NORTHD
 AT_CLEANUP
 ])
 
+OVN_FOR_EACH_NORTHD_NO_HV([
+AT_SETUP([LSP options:is_router excludes from MC_FLOOD_L2])
+ovn_start
+
+check ovn-nbctl ls-add ls1
+check ovn-nbctl lsp-add ls1 vif1
+check ovn-nbctl lsp-set-addresses vif1 "00:00:00:00:00:01 10.0.0.1"
+check ovn-nbctl lsp-add ls1 remote1
+check ovn-nbctl lsp-set-type remote1 remote
+check ovn-nbctl lsp-set-addresses remote1 "00:00:00:00:00:02"
+check ovn-nbctl lr-add lr1
+check ovn-nbctl lrp-add lr1 lr1-ls1 00:00:00:00:00:03 10.0.0.254/24
+check ovn-nbctl lsp-add ls1 ls1-lr1
+check ovn-nbctl lsp-set-type ls1-lr1 router
+check ovn-nbctl lsp-set-addresses ls1-lr1 router
+check ovn-nbctl lsp-set-options ls1-lr1 router-port=lr1-ls1
+check ovn-nbctl --wait=sb sync
+
+vif1_uuid=$(fetch_column Port_Binding _uuid logical_port=vif1)
+remote1_uuid=$(fetch_column Port_Binding _uuid logical_port=remote1)
+lr1_uuid=$(fetch_column Port_Binding _uuid logical_port=ls1-lr1)
+
+dnl type=router is never in _MC_flood_l2.
+AT_CHECK([ovn-sbctl --bare --columns=ports find Multicast_Group \
+          name=_MC_flood_l2 | grep -c "$lr1_uuid"], [1], [dnl
+0
+])
+
+dnl remote LSP is in _MC_flood_l2 by default (looks like a normal L2 port).
+AT_CHECK([ovn-sbctl --bare --columns=ports find Multicast_Group \
+          name=_MC_flood_l2 | grep -c "$remote1_uuid"], [0], [dnl
+1
+])
+AT_CHECK([ovn-sbctl --bare --columns=ports find Multicast_Group \
+          name=_MC_flood_l2 | grep -c "$vif1_uuid"], [0], [dnl
+1
+])
+
+dnl Mark remote LSP as router-facing: omit from _MC_flood_l2.
+check ovn-nbctl --wait=sb set Logical_Switch_Port remote1 
options:is_router=true
+AT_CHECK([ovn-sbctl --bare --columns=ports find Multicast_Group \
+          name=_MC_flood_l2 | grep -c "$remote1_uuid"], [1], [dnl
+0
+])
+AT_CHECK([ovn-sbctl --bare --columns=ports find Multicast_Group \
+          name=_MC_flood_l2 | grep -c "$vif1_uuid"], [0], [dnl
+1
+])
+
+dnl Still a member of _MC_flood (ARP/ND flood domain).
+AT_CHECK([ovn-sbctl --bare --columns=ports find Multicast_Group \
+          name=_MC_flood | grep -c "$remote1_uuid"], [0], [dnl
+1
+])
+
+dnl Clearing the option restores _MC_flood_l2 membership.
+check ovn-nbctl --wait=sb remove Logical_Switch_Port remote1 options is_router
+AT_CHECK([ovn-sbctl --bare --columns=ports find Multicast_Group \
+          name=_MC_flood_l2 | grep -c "$remote1_uuid"], [0], [dnl
+1
+])
+
+AT_CLEANUP
+])
+
 OVN_FOR_EACH_NORTHD_NO_HV_PARALLELIZATION([
 AT_SETUP([ACLs after lb])
 AT_KEYWORDS([acl])
-- 
2.38.1

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

Reply via email to