ovn-ic typically interconnects zones by attaching LRPs to a transit
switch. On that switch, remote LRPs appear as LSPs of type "remote", so
OVN treats them as regular L2 ports and 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 Logical_Switch_Port options:is_router so the CMS can mark a
type=remote port as representing a logical router port. lsp_is_router()
now returns true for such ports, so they are handled like type=router
ports; in particular they are omitted from _MC_flood_l2. The option is
ignored for any other port type.

Assisted-by: Claude Opus 5, Cursor
Signed-off-by: Han Zhou <[email protected]>
---

Notes:
    v2:
    - Extend lsp_is_router() for type=remote + options:is_router instead of
      adding a multicast-specific helper (Dumitru).
    - Add missing OVN_CLEANUP_NORTHD in the new test.

 Documentation/ref/ovn-logical-flows.7.rst | 10 ++-
 NEWS                                      |  4 ++
 lib/mcast-group-index.h                   |  4 +-
 northd/northd.h                           |  6 +-
 ovn-nb.xml                                | 14 +++++
 tests/ovn-northd.at                       | 74 +++++++++++++++++++++++
 6 files changed, 107 insertions(+), 5 deletions(-)

diff --git a/Documentation/ref/ovn-logical-flows.7.rst 
b/Documentation/ref/ovn-logical-flows.7.rst
index 1a9168ac8686..97305ea06fef 100644
--- a/Documentation/ref/ovn-logical-flows.7.rst
+++ b/Documentation/ref/ovn-logical-flows.7.rst
@@ -1470,7 +1470,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 ``remote`` 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
@@ -1485,7 +1486,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 ``remote`` 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
@@ -1513,7 +1515,9 @@ 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 ``remote`` 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 40a1b9867be5..81fbdf1e9d31 100644
--- a/NEWS
+++ b/NEWS
@@ -120,6 +120,10 @@ OVN v26.09.0 - xxx xx xxxx
      filter the routes learned through the port by route tag.  This supersedes
      "ic-route-filter-tag", which is now deprecated and is ignored when
      "ic-route-learn-tag-rules" is set.
+   - Add Logical_Switch_Port option "is_router" for type=remote ports that
+     represent a logical router port (e.g. ovn-ic transit switch LSPs).
+     Such ports are treated like type=router, including omission 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..ae88b4900eb0 100644
--- a/lib/mcast-group-index.h
+++ b/lib/mcast-group-index.h
@@ -43,7 +43,9 @@ enum ovn_mcast_tunnel_keys {
                                           */
     OVN_MCAST_FLOOD_L2_TUNNEL_KEY,       /* Logical switch broadcast domain
                                           * excluding ports towards logical
-                                          * routers.
+                                          * routers (type=router, or
+                                          * type=remote with
+                                          * options:is_router=true).
                                           */
     OVN_MIN_IP_MULTICAST,
     OVN_MAX_IP_MULTICAST = OVN_MAX_MULTICAST,
diff --git a/northd/northd.h b/northd/northd.h
index 2e3a9e00dad7..9a74a4abce3c 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -1143,7 +1143,11 @@ lsp_is_enabled(const struct nbrec_logical_switch_port 
*lsp)
 static inline bool
 lsp_is_router(const struct nbrec_logical_switch_port *nbsp)
 {
-    return !strcmp(nbsp->type, "router");
+    /* type=router, or a type=remote LSP that CMS marked as representing a
+     * remote LRP (e.g. ovn-ic transit switch ports). */
+    return !strcmp(nbsp->type, "router")
+           || (!strcmp(nbsp->type, "remote")
+               && smap_get_bool(&nbsp->options, "is_router", false));
 }
 
 static inline bool
diff --git a/ovn-nb.xml b/ovn-nb.xml
index c741a3b3279c..57b81d4b44b8 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1777,6 +1777,20 @@
         </column>
       </group>
 
+      <group title="Options for remote ports representing routers">
+        <column name="options" key="is_router"
+                type='{"type": "boolean"}'>
+          If set to <code>true</code> on a port whose <ref column="type"/> is
+          <code>remote</code>, treat the port as a router port (equivalent to
+          <code>type=router</code>).  CMS may set this on
+          <code>remote</code> LSPs that back LRPs in another OVN
+          interconnection zone.  Such ports are omitted from the
+          <code>_MC_flood_l2</code> multicast group so IP multicast is not
+          flooded toward them.  Ignored unless <ref column="type"/> is
+          <code>remote</code>.  Default: <code>false</code>.
+        </column>
+      </group>
+
     </group>
 
     <group title="Containers">
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index d19978a62a1d..74c75a190298 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -8792,6 +8792,80 @@ OVN_CLEANUP_NORTHD
 AT_CLEANUP
 ])
 
+OVN_FOR_EACH_NORTHD_NO_HV([
+AT_SETUP([LSP type=remote 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
+])
+
+dnl The option is ignored unless type is remote.
+check ovn-nbctl lsp-set-type remote1 ""
+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"], [0], [dnl
+1
+])
+
+OVN_CLEANUP_NORTHD
+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