When chassis-mirroring-enabled is set, controller will not enforce
tunneling for localnet-attached switches. This may be useful when the
network used to deliver tunnel packets doesn't have MTU headway to
redirect all packets originally sent through localnet port.
Signed-off-by: Ihar Hrachyshka <ihrac...@redhat.com>
---
controller/physical.c | 12 ++++++--
ovn-nb.xml | 11 ++++++++
ovn-sb.xml | 11 ++++++++
tests/ovn.at | 66 ++++++++++++++++++++++++++++++++++++++-----
4 files changed, 90 insertions(+), 10 deletions(-)
diff --git a/controller/physical.c b/controller/physical.c
index 02b771f3b..df5fe8cb3 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -1257,6 +1257,9 @@ consider_port_binding(struct ovsdb_idl_index
*sbrec_port_binding_by_name,
}
}
+ bool mirroring_enabled = smap_get_bool(
+ &binding->options, "chassis-mirroring-enabled", true);
+
bool is_ha_remote = false;
const struct chassis_tunnel *tun = NULL;
const struct sbrec_port_binding *localnet_port =
@@ -1266,7 +1269,8 @@ consider_port_binding(struct ovsdb_idl_index
*sbrec_port_binding_by_name,
is_remote = true;
/* Enforce tunneling while we clone packets to additional chassis b/c
* otherwise upstream switch won't flood the packet to both chassis.
*/
- if (localnet_port && !binding->additional_chassis) {
+ if (localnet_port &&
+ (!binding->additional_chassis || !mirroring_enabled)) {
ofport = u16_to_ofp(simap_get(patch_ofports,
localnet_port->logical_port));
if (!ofport) {
@@ -1316,8 +1320,10 @@ consider_port_binding(struct ovsdb_idl_index
*sbrec_port_binding_by_name,
}
/* Clone packets to additional chassis if needed. */
- additional_tuns = get_additional_tunnels(binding, chassis,
- chassis_tunnels);
+ if (mirroring_enabled) {
+ additional_tuns = get_additional_tunnels(binding, chassis,
+ chassis_tunnels);
+ }
if (!is_remote) {
/* Packets that arrive from a vif can belong to a VM or
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 3fd6c5140..c3ca7ba36 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1022,6 +1022,17 @@
additional chassis that are allowed to bind the same port.
</column>
+ <column name="options" key="chassis-mirroring-enabled">
+ When multiple chassis are set for the port, and the logical switch is
+ connected to an external network through a <code>localnet</code>
+ port, tunneling is enforced for the port to guarantee delivery of
+ packets directed to the port to all its locations. This has MTU
+ implications because the network used for tunneling must have headway
+ for additional tunnel headers attached to packets. If the network is
+ not capable to deliver packets with additional tunnel headers, then
+ tunneling enforcement can be disabled using this option.
+ </column>
+
<column name="options" key="activation-strategy">
If set and used with <ref column="requested-additional-chassis"/>,
specifies an activation strategy for the additional chassis. By
diff --git a/ovn-sb.xml b/ovn-sb.xml
index e8f91f351..dc276916a 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -3285,6 +3285,17 @@ tcp.flags = RST;
chassis that are allowed to bind the same port.
</column>
+ <column name="options" key="chassis-mirroring-enabled">
+ When multiple chassis are set for the port, and the logical switch is
+ connected to an external network through a <code>localnet</code>
+ port, tunneling is enforced for the port to guarantee delivery of
+ packets directed to the port to all its locations. This has MTU
+ implications because the network used for tunneling must have headway
+ for additional tunnel headers attached to packets. If the network is
+ not capable to deliver packets with additional tunnel headers, then
+ tunneling enforcement can be disabled using this option.
+ </column>
+
<column name="options" key="activation-strategy">
If used with multiple chassis set in <ref
column="requested-chassis"/>,
specifies an activation strategy for all additional chassis. By
diff --git a/tests/ovn.at b/tests/ovn.at
index c8992608e..760a4fd58 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -14227,10 +14227,12 @@ check ovn-nbctl lsp-add ls0 first
check ovn-nbctl lsp-add ls0 second
check ovn-nbctl lsp-add ls0 third
check ovn-nbctl lsp-add ls0 migrator
+check ovn-nbctl lsp-add ls0 migrator-no-cloning
check ovn-nbctl lsp-set-addresses first "00:00:00:00:00:01 10.0.0.1"
check ovn-nbctl lsp-set-addresses second "00:00:00:00:00:02 10.0.0.2"
check ovn-nbctl lsp-set-addresses third "00:00:00:00:00:03 10.0.0.3"
check ovn-nbctl lsp-set-addresses migrator "00:00:00:00:00:ff 10.0.0.100"
+check ovn-nbctl lsp-set-addresses migrator-no-cloning "00:00:00:00:01:ff
10.0.1.100"
check ovn-nbctl lsp-add ls0 public
check ovn-nbctl lsp-set-type public localnet
@@ -14242,6 +14244,9 @@ check ovn-nbctl lsp-set-options public network_name=phys
# chassis locations. Connectivity will be checked for resources located at hv1
# (First) and hv2 (Second) as well as for hv3 (Third) that does not take part
# in port migration.
+#
+# Also, check that a port with chassis-mirroring-enabled=false doesn't clone
+# packets through an enforced tunnel; instead localnet port still used
check ovn-nbctl lsp-set-options first requested-chassis=hv1
check ovn-nbctl lsp-set-options second requested-chassis=hv2
check ovn-nbctl lsp-set-options third requested-chassis=hv3
@@ -14265,6 +14270,10 @@ for hv in hv1 hv2; do
set Interface migrator external-ids:iface-id=migrator \
options:tx_pcap=$hv/migrator-tx.pcap \
options:rxq_pcap=$hv/migrator-rx.pcap
+ as $hv check ovs-vsctl -- add-port br-int migrator-no-cloning -- \
+ set Interface migrator-no-cloning
external-ids:iface-id=migrator-no-cloning \
+ options:tx_pcap=$hv/migrator-no-cloning-tx.pcap \
+ options:rxq_pcap=$hv/migrator-no-cloning-rx.pcap
done
send_arp() {
@@ -14298,8 +14307,12 @@ reset_env() {
reset_pcap_file hv3 third hv3/third
reset_pcap_file hv1 migrator hv1/migrator
reset_pcap_file hv2 migrator hv2/migrator
+ reset_pcap_file hv1 migrator-no-cloning hv1/migrator-no-cloning
+ reset_pcap_file hv2 migrator-no-cloning hv2/migrator-no-cloning
- for port in hv1/migrator hv2/migrator hv1/first hv2/second hv3/third; do
+ for port in hv1/migrator hv2/migrator \
+ hv1/migrator-no-cloning hv2/migrator-no-cloning \
+ hv1/first hv2/second hv3/third; do
: > $port.expected
done
}
@@ -14309,12 +14322,15 @@ check_packets() {
# attachment, hence using CONTAIN instead of strict matching
OVN_CHECK_PACKETS_CONTAIN([hv1/migrator-tx.pcap], [hv1/migrator.expected])
OVN_CHECK_PACKETS_CONTAIN([hv2/migrator-tx.pcap], [hv2/migrator.expected])
+ OVN_CHECK_PACKETS_CONTAIN([hv1/migrator-no-cloning-tx.pcap],
[hv1/migrator-no-cloning.expected])
+ OVN_CHECK_PACKETS_CONTAIN([hv2/migrator-no-cloning-tx.pcap],
[hv2/migrator-no-cloning.expected])
OVN_CHECK_PACKETS_CONTAIN([hv1/first-tx.pcap], [hv1/first.expected])
OVN_CHECK_PACKETS_CONTAIN([hv2/second-tx.pcap], [hv2/second.expected])
OVN_CHECK_PACKETS_CONTAIN([hv3/third-tx.pcap], [hv3/third.expected])
}
migrator_tpa=$(ip_to_hex 10 0 0 100)
+nocloning_tpa=$(ip_to_hex 10 0 1 100)
first_spa=$(ip_to_hex 10 0 0 1)
second_spa=$(ip_to_hex 10 0 0 2)
third_spa=$(ip_to_hex 10 0 0 3)
@@ -14336,7 +14352,8 @@ wait_column "" Port_Binding
requested_additional_chassis logical_port=migrator
wait_for_ports_up
# advertise location of ports through localnet port
-send_garp hv1 migrator 0000000000ff ffffffffffff $migrator_spa $migrator_tpa
+send_garp hv1 migrator 0000000000ff ffffffffffff $migrator_tpa $migrator_tpa
+send_garp hv1 migrator-no-cloning 0000000001ff ffffffffffff $nocloning_tpa
$nocloning_tpa
send_garp hv1 first 000000000001 ffffffffffff $first_spa $first_tpa
send_garp hv2 second 000000000002 ffffffffffff $second_spa $second_tpa
send_garp hv3 third 000000000003 ffffffffffff $third_spa $third_tpa
@@ -14404,13 +14421,19 @@ request=$(send_arp hv2 migrator 0000000000ff
ffffffffffff $migrator_tpa $first_s
check_packets
reset_env
-# Start port migration hv1 -> hv2: both hypervisors are now bound
+# Start ports migration hv1 -> hv2: both hypervisors are now bound
check ovn-nbctl lsp-set-options migrator requested-chassis=hv1,hv2
+check ovn-nbctl lsp-set-options migrator-no-cloning requested-chassis=hv1,hv2 \
+
chassis-mirroring-enabled=false
wait_for_ports_up
-wait_column "$hv1_uuid" Port_Binding chassis logical_port=migrator
-wait_column "$hv1_uuid" Port_Binding requested_chassis logical_port=migrator
-wait_column "$hv2_uuid" Port_Binding additional_chassis logical_port=migrator
-wait_column "$hv2_uuid" Port_Binding requested_additional_chassis
logical_port=migrator
+for port in migrator migrator-no-cloning; do
+ wait_column "$hv1_uuid" Port_Binding chassis logical_port=$port
+ wait_column "$hv1_uuid" Port_Binding requested_chassis logical_port=$port
+ wait_column "$hv2_uuid" Port_Binding additional_chassis logical_port=$port
+ wait_column "$hv2_uuid" Port_Binding requested_additional_chassis
logical_port=$port
+done
+
+send_garp hv1 migrator-no-cloning 0000000001ff ffffffffffff $nocloning_tpa
$nocloning_tpa
# check that...
# unicast from First arrives to hv1:Migrator
@@ -14419,11 +14442,20 @@ request=$(send_arp hv1 first 000000000001
0000000000ff $first_spa $migrator_tpa)
echo $request >> hv1/migrator.expected
echo $request >> hv2/migrator.expected
+# unicast from First arrives to hv1:Migrator-no-cloning
+# unicast from First doesn't arrive to hv2:Migrator-no-cloning
+request=$(send_arp hv1 first 000000000001 0000000001ff $first_spa
$nocloning_tpa)
+echo $request >> hv1/migrator-no-cloning.expected
+
# mcast from First arrives to hv1:Migrator
# mcast from First arrives to hv2:Migrator
+# mcast from First arrives to hv1:Migrator-no-cloning
+# mcast from First arrives to hv2:Migrator-no-cloning
request=$(send_arp hv1 first 000000000001 ffffffffffff $first_spa
$migrator_tpa)
echo $request >> hv1/migrator.expected
echo $request >> hv2/migrator.expected
+echo $request >> hv1/migrator-no-cloning.expected
+echo $request >> hv2/migrator-no-cloning.expected
echo $request >> hv3/third.expected
echo $request >> hv2/second.expected
@@ -14433,11 +14465,20 @@ request=$(send_arp hv2 second 000000000002 0000000000ff $second_spa $migrator_tp
echo $request >> hv1/migrator.expected
echo $request >> hv2/migrator.expected
+# unicast from Second doesn't arrive to hv1:Migrator-no-cloning
+# unicast from Second arrives to hv2:Migrator-no-cloning
+request=$(send_arp hv2 second 000000000002 0000000001ff $second_spa
$nocloning_tpa)
+echo $request >> hv2/migrator-no-cloning.expected
+
# mcast from Second arrives to hv1:Migrator
# mcast from Second arrives to hv2:Migrator
+# mcast from Second arrives to hv1:Migrator-no-cloning
+# mcast from Second arrives to hv2:Migrator-no-cloning
request=$(send_arp hv2 second 000000000002 ffffffffffff $second_spa
$migrator_tpa)
echo $request >> hv1/migrator.expected
echo $request >> hv2/migrator.expected
+echo $request >> hv1/migrator-no-cloning.expected
+echo $request >> hv2/migrator-no-cloning.expected
echo $request >> hv3/third.expected
echo $request >> hv1/first.expected
@@ -14447,11 +14488,20 @@ request=$(send_arp hv3 third 000000000003 0000000000ff $third_spa $migrator_tpa)
echo $request >> hv1/migrator.expected
echo $request >> hv2/migrator.expected
+# unicast from Third arrives to hv1:Migrator-no-cloning
+# unicast from Third doesn't arrive to hv2:Migrator-no-cloning
+request=$(send_arp hv3 third 000000000003 0000000001ff $third_spa
$nocloning_tpa)
+echo $request >> hv1/migrator-no-cloning.expected
+
# mcast from Third arrives to hv1:Migrator
# mcast from Third arrives to hv2:Migrator
+# mcast from Third arrives to hv1:Migrator-no-cloning
+# mcast from Third arrives to hv2:Migrator-no-cloning
request=$(send_arp hv3 third 000000000003 ffffffffffff $third_spa
$migrator_tpa)
echo $request >> hv1/migrator.expected
echo $request >> hv2/migrator.expected
+echo $request >> hv1/migrator-no-cloning.expected
+echo $request >> hv2/migrator-no-cloning.expected
echo $request >> hv1/first.expected
echo $request >> hv2/second.expected
@@ -14476,12 +14526,14 @@ request=$(send_arp hv1 migrator 0000000000ff ffffffffffff $migrator_tpa $first_s
echo $request >> hv1/first.expected
echo $request >> hv2/second.expected
echo $request >> hv3/third.expected
+echo $request >> hv1/migrator-no-cloning.expected
# mcast from hv2:Migrator arrives to First, Second, and Third
request=$(send_arp hv2 migrator 0000000000ff ffffffffffff $migrator_tpa
$first_spa)
echo $request >> hv1/first.expected
echo $request >> hv2/second.expected
echo $request >> hv3/third.expected
+echo $request >> hv1/migrator-no-cloning.expected
check_packets