[ovs-dev] [PATCH v2 3/3] ovn: Send GARP for router port IPs of a router port connected to bridged logical switch
nusiddiq at redhat.com
nusiddiq at redhat.com
Fri Jun 14 12:36:32 UTC 2019
From: Numan Siddique <nusiddiq at redhat.com>
This patch handles sending GARPs for
- router port IPs of a distributed router port
- router port IPs of a router port which belongs to gateway router
(with the option - redirect-chassis set in Logical_Router.options)
Signed-off-by: Numan Siddique <nusiddiq at redhat.com>
---
ovn/northd/ovn-northd.c | 44 ++++++++++++++++----
tests/ovn.at | 89 +++++++++++++++++++++++++++++++----------
2 files changed, 105 insertions(+), 28 deletions(-)
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 26ad3583a..63b97b727 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1983,9 +1983,23 @@ get_nat_addresses(const struct ovn_port *op, size_t *n)
}
} else {
/* Centralized NAT rule, either on gateway router or distributed
- * router. */
- ds_put_format(&c_addresses, " %s", nat->external_ip);
- central_ip_address = true;
+ * router.
+ * Check if external_ip is same as router ip. If so, then there
+ * is no need to add this to the nat_addresses. The router IPs
+ * will be added separately. */
+ bool is_router_ip = false;
+ for (size_t j = 0; j < op->lrp_networks.n_ipv4_addrs; j++) {
+ if (!strcmp(nat->external_ip,
+ op->lrp_networks.ipv4_addrs[j].addr_s)) {
+ is_router_ip = true;
+ break;
+ }
+ }
+
+ if (!is_router_ip) {
+ ds_put_format(&c_addresses, " %s", nat->external_ip);
+ central_ip_address = true;
+ }
}
}
@@ -2526,13 +2540,26 @@ ovn_port_update_sbrec(struct northd_context *ctx,
* - op->peer has 'reside-on-gateway-chassis' set and the
* the logical router datapath has distributed router port.
*
+ * - op->peer is distributed gateway router port.
+ *
+ * - op->peer's router is a gateway router and op has a localnet
+ * port.
+ *
* Note: Port_Binding.nat_addresses column is also used for
* sending the GARPs for the router port IPs.
* */
+ bool add_router_port_garp = false;
if (op->peer && op->peer->nbrp && op->peer->od->l3dgw_port &&
op->peer->od->l3redirect_port &&
- smap_get_bool(&op->peer->nbrp->options,
- "reside-on-redirect-chassis", false)) {
+ (smap_get_bool(&op->peer->nbrp->options,
+ "reside-on-redirect-chassis", false) ||
+ op->peer == op->peer->od->l3dgw_port)) {
+ add_router_port_garp = true;
+ } else if (chassis && op->od->localnet_port) {
+ add_router_port_garp = true;
+ }
+
+ if (add_router_port_garp) {
struct ds garp_info = DS_EMPTY_INITIALIZER;
ds_put_format(&garp_info, "%s", op->peer->lrp_networks.ea_s);
for (size_t i = 0; i < op->peer->lrp_networks.n_ipv4_addrs;
@@ -2540,8 +2567,11 @@ ovn_port_update_sbrec(struct northd_context *ctx,
ds_put_format(&garp_info, " %s",
op->peer->lrp_networks.ipv4_addrs[i].addr_s);
}
- ds_put_format(&garp_info, " is_chassis_resident(%s)",
- op->peer->od->l3redirect_port->json_key);
+
+ if (op->peer->od->l3redirect_port) {
+ ds_put_format(&garp_info, " is_chassis_resident(%s)",
+ op->peer->od->l3redirect_port->json_key);
+ }
n_nats++;
nats = xrealloc(nats, (n_nats * sizeof *nats));
diff --git a/tests/ovn.at b/tests/ovn.at
index ea627e128..2e266d94a 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -6730,6 +6730,9 @@ AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
+# Wait until the patch ports are created in hv1 to connect br-int to br-eth0
+OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-vsctl show | \
+grep "Port patch-br-int-to-ln_port" | wc -l`])
# Wait for packet to be received.
OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
@@ -6737,10 +6740,11 @@ trim_zeros() {
sed 's/\(00\)\{1,\}$//'
}
$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
-expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
+expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
echo $expected > expout
+expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
+echo $expected >> expout
AT_CHECK([sort packets], [0], [expout])
-cat packets
OVN_CLEANUP([hv1])
@@ -6786,7 +6790,15 @@ AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
+# Wait until the patch ports are created to connect br-int to br-eth0
+OVS_WAIT_UNTIL([test 1 = `ovs-vsctl show | \
+grep "Port patch-br-int-to-ln_port" | wc -l`])
+ovn-sbctl list port_binding lrp0-rp
+echo "*****"
+ovn-nbctl list logical_switch_port lrp0-rp
+ovn-nbctl list logical_router_port lrp0
+ovn-nbctl show
# Wait for packet to be received.
OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
trim_zeros() {
@@ -6800,7 +6812,6 @@ echo $expected >> expout
expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80003000000000000c0a80003"
echo $expected >> expout
AT_CHECK([sort packets], [0], [expout])
-cat packets
OVN_CLEANUP([hv1])
@@ -8564,7 +8575,8 @@ grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
dst_ip=`ip_to_hex 172 16 1 3`
expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
echo $expected > ext1-vif1.expected
-
+ exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
+ echo $exp_gw_ip_garp >> ext1-vif1.expected
as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
if test $backup_vswitchd_dead != 1; then
@@ -8580,7 +8592,10 @@ grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
$PYTHON "$top_srcdir/utilities/ovs-pcap.in" $active_gw/br-phys_n1-tx.pcap > packets
- AT_CHECK([grep $expected packets | sort], [0], [expout])
+ cat packets | grep $expected > exp
+ cat packets | grep $exp_gw_ip_garp >> exp
+ AT_CHECK([cat exp], [0], [expout])
+ rm -f expout
if test $backup_vswitchd_dead != 1; then
# Check for backup gw only if vswitchd is alive
$PYTHON "$top_srcdir/utilities/ovs-pcap.in" $backup_gw/br-phys_n1-tx.pcap > packets
@@ -8812,6 +8827,8 @@ grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
dst_ip=`ip_to_hex 172 16 1 3`
expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
echo $expected > ext1-vif1.expected
+ exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
+ echo $exp_gw_ip_garp >> ext1-vif1.expected
as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
@@ -8820,11 +8837,12 @@ grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
# Resend packet from foo1 to outside1
as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
- sleep 1
-
OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
$PYTHON "$top_srcdir/utilities/ovs-pcap.in" $active_gw/br-phys_n1-tx.pcap > packets
- AT_CHECK([grep $expected packets | sort], [0], [expout])
+ cat packets | grep $expected > exp
+ cat packets | grep $exp_gw_ip_garp >> exp
+ AT_CHECK([cat exp], [0], [expout])
+
$PYTHON "$top_srcdir/utilities/ovs-pcap.in" $backup_gw/br-phys_n1-tx.pcap > packets
AT_CHECK([grep $expected packets | sort], [0], [])
}
@@ -9062,13 +9080,17 @@ OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
# Now add bridge-mappings on hv2, which should make everything work
as hv2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 2
+# Wait until the patch ports are created in hv2 to connect br-int to br-phys
+OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
+grep "Port patch-br-int-to-ln-alice" | wc -l`])
# ARP for router IP address from outside1
test_arp 3 1 f00000010204 $outside_ip $rtr_ip 000002010203
+# hv3-vif1.expected should also have the gw router port garp packet.
+exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
+echo $exp_gw_ip_garp >> hv3-vif1.expected
+
# Now check the packets actually received against the ones expected.
OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
@@ -9224,7 +9246,7 @@ ovn_attach n1 br-phys 192.168.0.3
AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
-AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
+AT_CHECK([ovn-nbctl --wait=hv lsp-set-options ln_port network_name=physnet1])
# Allow some time for ovn-northd and ovn-controller to catch up.
# XXX This should be more systematic.
@@ -9237,6 +9259,10 @@ OVN_CHECK_PACKETS([hv1/snoopvif-tx.pcap], [packets])
# Add bridge-mapping on hv2
AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
+# Wait until the patch ports are created in hv2 to connect br-int to br-phys
+OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
+grep "Port patch-br-int-to-ln_port" | wc -l`])
+
# Wait for packets to be received.
OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
trim_zeros() {
@@ -9277,6 +9303,10 @@ ovs-vsctl -- add-port br-int hv3-vif2 -- \
# Add bridge-mapping on hv3
AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
+# Wait until the patch ports are created in hv3 to connect br-int to br-phys
+OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-vsctl show | \
+grep "Port patch-br-int-to-ln_port" | wc -l`])
+
# Re-add nat-addresses option
ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
@@ -9287,12 +9317,14 @@ trim_zeros() {
}
$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
-expected="fffffffffffff0000000000308060001080006040001f00000000003c0a80003000000000000c0a80003"
-echo $expected >> expout
-expected="fffffffffffff0000000000408060001080006040001f00000000004c0a80004000000000000c0a80004"
-echo $expected >> expout
-AT_CHECK([sort packets], [0], [expout])
-sort packets | cat
+garp_1="fffffffffffff0000000000308060001080006040001f00000000003c0a80003000000000000c0a80003"
+echo $garp_1 > expout
+garp_2="fffffffffffff0000000000408060001080006040001f00000000004c0a80004000000000000c0a80004"
+echo $garp_2 >> expout
+
+cat packets | grep $garp_1 | head -1 > exp
+cat packets | grep $garp_2 | head -1 >> exp
+AT_CHECK([cat exp], [0], [expout])
OVN_CLEANUP([hv1],[hv2],[hv3])
@@ -10763,16 +10795,31 @@ AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
AT_CHECK([ovn-nbctl set Logical_Switch_Port ln_port tag=2014])
# wait for earlier changes to take effect
-AT_CHECK([ovn-nbctl --timeout=3 --wait=hv sync], [0], [ignore])
+OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-ofctl dump-flows br-int table=65 | \
+grep "actions=mod_vlan_vid:2014" | wc -l`
+])
+
+OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-ofctl dump-flows br-int table=65 | \
+grep "actions=mod_vlan_vid:2014" | wc -l`
+])
# update nat-addresses option
-ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
-ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
+ovn-nbctl --wait=hv clear logical_switch_port lrp0-rp options
+
+#Wait until the Port_Binding.nat_addresses is cleared.
+OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns nat_addresses find port_binding \
+logical_port=lrp0-rp | grep is_chassis | wc -l`])
as hv1 reset_pcap_file snoopvif hv1/snoopvif
as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
+ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
+
+#Wait until the Port_Binding.nat_addresses is set.
+OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns nat_addresses find port_binding \
+logical_port=lrp0-rp | grep is_chassis | wc -l`])
+
# Wait for packets to be received.
OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
trim_zeros() {
--
2.21.0
More information about the dev
mailing list