bbaaef
From 8f0056c923bbd0af9256ef7735d070e128fa77df Mon Sep 17 00:00:00 2001
bbaaef
From: Dumitru Ceara <dceara@redhat.com>
bbaaef
Date: Tue, 24 Mar 2020 11:03:29 +0100
bbaaef
Subject: [PATCH 1/2] ovn-northd: Forward ARP requests on localnet ports.
bbaaef
bbaaef
Commit 32f5ebb06226 limited the ARP/ND broadcast domain but in scenarios
bbaaef
where ARP responder flows are installed only on chassis that own the
bbaaef
associated logical ports ARP requests should still be forwarded on
bbaaef
localnet ports because the router pipeline should be executed on the
bbaaef
chassis that owns the logical port. Only that chassis will reply to the
bbaaef
ARP/ND request.
bbaaef
bbaaef
Reported-by: Michael Plato <michael.plato@tu-berlin.de>
bbaaef
Reported-at: https://mail.openvswitch.org/pipermail/ovs-discuss/2020-March/049856.html
bbaaef
Fixes: 32f5ebb06226 ("ovn-northd: Limit ARP/ND broadcast domain whenever possible.")
bbaaef
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
bbaaef
Signed-off-by: Numan Siddique <numans@ovn.org>
bbaaef
(cherry picked from upstream commit d2ab98463f299e67a9f9a31e8b7c42680b8645cf)
bbaaef
bbaaef
Change-Id: I1c7cd9341b249ba754a698ac205a10ddc10d2dc2
bbaaef
---
bbaaef
 ovn/northd/ovn-northd.8.xml |   3 +-
bbaaef
 ovn/northd/ovn-northd.c     |   6 +-
bbaaef
 tests/ovn.at                | 169 ++++++++++++++++++++++++++++++++++++++++----
bbaaef
 3 files changed, 162 insertions(+), 16 deletions(-)
bbaaef
bbaaef
diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml
bbaaef
index 5f98099..ad17323 100644
bbaaef
--- a/ovn/northd/ovn-northd.8.xml
bbaaef
+++ b/ovn/northd/ovn-northd.8.xml
bbaaef
@@ -1104,7 +1104,8 @@ output;
bbaaef
         Priority-75 flows for each IP address/VIP/NAT address owned by a
bbaaef
         router port connected to the switch. These flows match ARP requests
bbaaef
         and ND packets for the specific IP addresses.  Matched packets are
bbaaef
-        forwarded only to the router that owns the IP address.
bbaaef
+        forwarded only to the router that owns the IP address and, if
bbaaef
+        present, to the localnet port of the logical switch.
bbaaef
       
bbaaef
 
bbaaef
       
  • bbaaef
    diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
    bbaaef
    index d734d36..7cb3773 100644
    bbaaef
    --- a/ovn/northd/ovn-northd.c
    bbaaef
    +++ b/ovn/northd/ovn-northd.c
    bbaaef
    @@ -5625,8 +5625,12 @@ build_lswitch_rport_arp_req_flow_for_ip(struct sset *ips,
    bbaaef
         ds_put_cstr(&match, "}");
    bbaaef
     
    bbaaef
         /* Send a the packet only to the router pipeline and skip flooding it
    bbaaef
    -     * in the broadcast domain.
    bbaaef
    +     * in the broadcast domain (except for the localnet port).
    bbaaef
          */
    bbaaef
    +    if (od->localnet_port) {
    bbaaef
    +        ds_put_format(&actions, "clone { outport = %s; output; }; ",
    bbaaef
    +                      od->localnet_port->json_key);
    bbaaef
    +    }
    bbaaef
         ds_put_format(&actions, "outport = %s; output;", patch_op->json_key);
    bbaaef
         ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, priority,
    bbaaef
                       ds_cstr(&match), ds_cstr(&actions));
    bbaaef
    diff --git a/tests/ovn.at b/tests/ovn.at
    bbaaef
    index da016be..551c399 100644
    bbaaef
    --- a/tests/ovn.at
    bbaaef
    +++ b/tests/ovn.at
    bbaaef
    @@ -15856,13 +15856,14 @@ net_add n1
    bbaaef
     sim_add hv1
    bbaaef
     as hv1
    bbaaef
     ovs-vsctl add-br br-phys
    bbaaef
    +ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
    bbaaef
     ovn_attach n1 br-phys 192.168.0.1
    bbaaef
     
    bbaaef
    -ovs-vsctl -- add-port br-int hv1-vif1 -- \
    bbaaef
    -    set interface hv1-vif1 external-ids:iface-id=sw-agg-ext \
    bbaaef
    -    options:tx_pcap=hv1/vif1-tx.pcap \
    bbaaef
    -    options:rxq_pcap=hv1/vif1-rx.pcap \
    bbaaef
    -    ofport-request=1
    bbaaef
    +sim_add hv2
    bbaaef
    +as hv2
    bbaaef
    +ovs-vsctl add-br br-phys
    bbaaef
    +ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
    bbaaef
    +ovn_attach n1 br-phys 192.168.0.2
    bbaaef
     
    bbaaef
     # One Aggregation Switch connected to two Logical networks (routers).
    bbaaef
     ovn-nbctl ls-add sw-agg
    bbaaef
    @@ -15878,18 +15879,66 @@ ovn-nbctl lsp-add sw-agg sw-rtr2                   \
    bbaaef
         -- lsp-set-addresses sw-rtr2 00:00:00:00:02:00 \
    bbaaef
         -- lsp-set-options sw-rtr2 router-port=rtr2-sw
    bbaaef
     
    bbaaef
    -# Configure L3 interface IPv4 & IPv6 on both routers
    bbaaef
    +# Localnet port on the Aggregation Switch.
    bbaaef
    +ovn-nbctl lsp-add sw-agg sw-agg-ln
    bbaaef
    +ovn-nbctl lsp-set-addresses sw-agg-ln unknown
    bbaaef
    +ovn-nbctl lsp-set-type sw-agg-ln localnet
    bbaaef
    +ovn-nbctl lsp-set-options sw-agg-ln network_name=phys
    bbaaef
    +
    bbaaef
    +# Configure L3 interface IPv4 & IPv6 on both routers.
    bbaaef
     ovn-nbctl lr-add rtr1
    bbaaef
     ovn-nbctl lrp-add rtr1 rtr1-sw 00:00:00:00:01:00 10.0.0.1/24 10::1/64
    bbaaef
     
    bbaaef
    +ovn-nbctl lrp-add rtr1 rtr1-sw1 00:00:01:00:00:00 20.0.0.1/24 20::1/64
    bbaaef
    +
    bbaaef
     ovn-nbctl lr-add rtr2
    bbaaef
     ovn-nbctl lrp-add rtr2 rtr2-sw 00:00:00:00:02:00 10.0.0.2/24 10::2/64
    bbaaef
     
    bbaaef
    +# Configure router gateway ports.
    bbaaef
    +ovn-nbctl lrp-set-gateway-chassis rtr1-sw hv1 20
    bbaaef
    +ovn-nbctl lrp-set-gateway-chassis rtr2-sw hv1 20
    bbaaef
    +
    bbaaef
    +# One private network behind rtr1 with two VMs.
    bbaaef
    +ovn-nbctl ls-add sw1
    bbaaef
    +ovn-nbctl lsp-add sw1 sw1-p1 \
    bbaaef
    +    -- lsp-set-addresses sw1-p1 00:00:00:01:00:00
    bbaaef
    +ovn-nbctl lsp-add sw1 sw1-p2 \
    bbaaef
    +    -- lsp-set-addresses sw1-p2 00:00:00:02:00:00
    bbaaef
    +ovn-nbctl lsp-add sw1 sw1-rtr1                       \
    bbaaef
    +    -- lsp-set-type sw1-rtr1 router                  \
    bbaaef
    +    -- lsp-set-addresses sw1-rtr1 00:00:01:00:00:00  \
    bbaaef
    +    -- lsp-set-options sw1-rtr1 router-port=rtr1-sw1
    bbaaef
    +
    bbaaef
    +# Bind a "VM" connected to sw-agg on hv1.
    bbaaef
    +as hv1
    bbaaef
    +ovs-vsctl -- add-port br-int hv1-vif0 -- \
    bbaaef
    +    set interface hv1-vif0 external-ids:iface-id=sw-agg-ext \
    bbaaef
    +    options:tx_pcap=hv1/vif0-tx.pcap \
    bbaaef
    +    options:rxq_pcap=hv1/vif0-rx.pcap \
    bbaaef
    +    ofport-request=1
    bbaaef
    +
    bbaaef
    +# Bind a "VM" connected to sw1 on hv1.
    bbaaef
    +as hv1
    bbaaef
    +ovs-vsctl -- add-port br-int hv1-vif1 -- \
    bbaaef
    +    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
    bbaaef
    +    options:tx_pcap=hv1/vif1-tx.pcap \
    bbaaef
    +    options:rxq_pcap=hv1/vif1-rx.pcap \
    bbaaef
    +    ofport-request=2
    bbaaef
    +
    bbaaef
    +# Bind a "VM" connected to sw1 on hv2.
    bbaaef
    +as hv2
    bbaaef
    +ovs-vsctl -- add-port br-int hv1-vif2 -- \
    bbaaef
    +    set interface hv1-vif2 external-ids:iface-id=sw1-p2 \
    bbaaef
    +    options:tx_pcap=hv1/vif2-tx.pcap \
    bbaaef
    +    options:rxq_pcap=hv1/vif2-rx.pcap \
    bbaaef
    +    ofport-request=3
    bbaaef
    +
    bbaaef
     OVN_POPULATE_ARP
    bbaaef
     ovn-nbctl --wait=hv sync
    bbaaef
     
    bbaaef
     sw_dp_uuid=$(ovn-sbctl --bare --columns _uuid list datapath_binding sw-agg)
    bbaaef
     sw_dp_key=$(ovn-sbctl --bare --columns tunnel_key list datapath_binding sw-agg)
    bbaaef
    +r1_dp_key=$(ovn-sbctl --bare --columns tunnel_key list datapath_binding rtr1)
    bbaaef
     
    bbaaef
     r1_tnl_key=$(ovn-sbctl --bare --columns tunnel_key list port_binding sw-rtr1)
    bbaaef
     r2_tnl_key=$(ovn-sbctl --bare --columns tunnel_key list port_binding sw-rtr2)
    bbaaef
    @@ -15898,9 +15947,10 @@ mc_key=$(ovn-sbctl --bare --columns tunnel_key find multicast_group datapath=${s
    bbaaef
     mc_key=$(printf "%04x" $mc_key)
    bbaaef
     
    bbaaef
     match_sw_metadata="metadata=0x${sw_dp_key}"
    bbaaef
    +match_r1_metadata="metadata=0x${r1_dp_key}"
    bbaaef
     
    bbaaef
     # Inject ARP request for first router owned IP address.
    bbaaef
    -send_arp_request 1 1 ${src_mac} $(ip_to_hex 10 0 0 254) $(ip_to_hex 10 0 0 1)
    bbaaef
    +send_arp_request 1 0 ${src_mac} $(ip_to_hex 10 0 0 254) $(ip_to_hex 10 0 0 1)
    bbaaef
     
    bbaaef
     # Verify that the ARP request is sent only to rtr1.
    bbaaef
     match_arp_req="priority=75.*${match_sw_metadata}.*arp_tpa=10.0.0.1,arp_op=1"
    bbaaef
    @@ -15929,7 +15979,7 @@ OVS_WAIT_UNTIL([
    bbaaef
     # Inject ND_NS for ofirst router owned IP address.
    bbaaef
     src_ipv6=00100000000000000000000000000254
    bbaaef
     dst_ipv6=00100000000000000000000000000001
    bbaaef
    -send_nd_ns 1 1 ${src_mac} ${src_ipv6} ${dst_ipv6} 751d
    bbaaef
    +send_nd_ns 1 0 ${src_mac} ${src_ipv6} ${dst_ipv6} 751d
    bbaaef
     
    bbaaef
     # Verify that the ND_NS is sent only to rtr1.
    bbaaef
     match_nd_ns="priority=75.*${match_sw_metadata}.*icmp_type=135.*nd_target=10::1"
    bbaaef
    @@ -15966,7 +16016,7 @@ ovn-nbctl lr-lb-add rtr2 lb2-v6
    bbaaef
     ovn-nbctl --wait=hv sync
    bbaaef
     
    bbaaef
     # Inject ARP request for first router owned VIP address.
    bbaaef
    -send_arp_request 1 1 ${src_mac} $(ip_to_hex 10 0 0 254) $(ip_to_hex 10 0 0 11)
    bbaaef
    +send_arp_request 1 0 ${src_mac} $(ip_to_hex 10 0 0 254) $(ip_to_hex 10 0 0 11)
    bbaaef
     
    bbaaef
     # Verify that the ARP request is sent only to rtr1.
    bbaaef
     match_arp_req="priority=75.*${match_sw_metadata}.*arp_tpa=10.0.0.11,arp_op=1"
    bbaaef
    @@ -15995,7 +16045,7 @@ OVS_WAIT_UNTIL([
    bbaaef
     # Inject ND_NS for first router owned VIP address.
    bbaaef
     src_ipv6=00100000000000000000000000000254
    bbaaef
     dst_ipv6=00100000000000000000000000000011
    bbaaef
    -send_nd_ns 1 1 ${src_mac} ${src_ipv6} ${dst_ipv6} 751d
    bbaaef
    +send_nd_ns 1 0 ${src_mac} ${src_ipv6} ${dst_ipv6} 751d
    bbaaef
     
    bbaaef
     # Verify that the ND_NS is sent only to rtr1.
    bbaaef
     match_nd_ns="priority=75.*${match_sw_metadata}.*icmp_type=135.*nd_target=10::11"
    bbaaef
    @@ -16019,14 +16069,21 @@ OVS_WAIT_UNTIL([
    bbaaef
         test "0" = "${pkts_flooded}"
    bbaaef
     ])
    bbaaef
     
    bbaaef
    -# Configure NAT on both routers
    bbaaef
    +# Configure NAT on both routers.
    bbaaef
     ovn-nbctl lr-nat-add rtr1 dnat_and_snat 10.0.0.111 42.42.42.1
    bbaaef
     ovn-nbctl lr-nat-add rtr1 dnat_and_snat 10::111 42::1
    bbaaef
     ovn-nbctl lr-nat-add rtr2 dnat_and_snat 10.0.0.222 42.42.42.2
    bbaaef
     ovn-nbctl lr-nat-add rtr2 dnat_and_snat 10::222 42::2
    bbaaef
     
    bbaaef
    +# Configure FIP1 and FIP2 on rtr1 for sw1-p1 and sw1-p2.
    bbaaef
    +ovn-nbctl lr-nat-add rtr1 dnat_and_snat 10.0.0.121 20.0.0.11 sw1-p1 00:00:00:01:00:00
    bbaaef
    +ovn-nbctl lr-nat-add rtr1 dnat_and_snat 10::121 20::11 sw1-p1 00:00:00:01:00:00
    bbaaef
    +ovn-nbctl lr-nat-add rtr1 dnat_and_snat 10.0.0.122 20.0.0.12 sw1-p2 00:00:00:02:00:00
    bbaaef
    +ovn-nbctl lr-nat-add rtr1 dnat_and_snat 10::122 20::12 sw1-p2 00:00:00:02:00:00
    bbaaef
    +ovn-nbctl --wait=hv sync
    bbaaef
    +
    bbaaef
     # Inject ARP request for first router owned NAT address.
    bbaaef
    -send_arp_request 1 1 ${src_mac} $(ip_to_hex 10 0 0 254) $(ip_to_hex 10 0 0 111)
    bbaaef
    +send_arp_request 1 0 ${src_mac} $(ip_to_hex 10 0 0 254) $(ip_to_hex 10 0 0 111)
    bbaaef
     
    bbaaef
     # Verify that the ARP request is sent only to rtr1.
    bbaaef
     match_arp_req="priority=75.*${match_sw_metadata}.*arp_tpa=10.0.0.111,arp_op=1"
    bbaaef
    @@ -16052,10 +16109,50 @@ OVS_WAIT_UNTIL([
    bbaaef
         test "0" = "${pkts_flooded}"
    bbaaef
     ])
    bbaaef
     
    bbaaef
    +# Inject ARP request for FIP1.
    bbaaef
    +send_arp_request 1 0 ${src_mac} $(ip_to_hex 10 0 0 254) $(ip_to_hex 10 0 0 121)
    bbaaef
    +
    bbaaef
    +# Verify that the ARP request is replied to from hv1 and not hv2.
    bbaaef
    +match_arp_req="priority=90.*${match_r1_metadata}.*arp_tpa=10.0.0.121,arp_op=1"
    bbaaef
    +
    bbaaef
    +as hv1
    bbaaef
    +OVS_WAIT_UNTIL([
    bbaaef
    +    pkts_on_rtr1=$(ovs-ofctl dump-flows br-int | \
    bbaaef
    +    grep -E "${match_arp_req}" | grep n_packets=1 -c)
    bbaaef
    +    test "1" = "${pkts_on_rtr1}"
    bbaaef
    +])
    bbaaef
    +
    bbaaef
    +as hv2
    bbaaef
    +OVS_WAIT_UNTIL([
    bbaaef
    +    pkts_on_rtr1=$(ovs-ofctl dump-flows br-int | \
    bbaaef
    +    grep -E "${match_arp_req}" | grep n_packets=1 -c)
    bbaaef
    +    test "0" = "${pkts_on_rtr1}"
    bbaaef
    +])
    bbaaef
    +
    bbaaef
    +# Inject ARP request for FIP2.
    bbaaef
    +send_arp_request 1 0 ${src_mac} $(ip_to_hex 10 0 0 254) $(ip_to_hex 10 0 0 122)
    bbaaef
    +
    bbaaef
    +# Verify that the ARP request is replied to from hv2 and not hv1.
    bbaaef
    +match_arp_req="priority=90.*${match_r1_metadata}.*arp_tpa=10.0.0.122,arp_op=1"
    bbaaef
    +
    bbaaef
    +as hv2
    bbaaef
    +OVS_WAIT_UNTIL([
    bbaaef
    +    pkts_on_rtr1=$(ovs-ofctl dump-flows br-int | \
    bbaaef
    +    grep -E "${match_arp_req}" | grep n_packets=1 -c)
    bbaaef
    +    test "1" = "${pkts_on_rtr1}"
    bbaaef
    +])
    bbaaef
    +
    bbaaef
    +as hv1
    bbaaef
    +OVS_WAIT_UNTIL([
    bbaaef
    +    pkts_on_rtr1=$(ovs-ofctl dump-flows br-int | \
    bbaaef
    +    grep -E "${match_arp_req}" | grep n_packets=1 -c)
    bbaaef
    +    test "0" = "${pkts_on_rtr1}"
    bbaaef
    +])
    bbaaef
    +
    bbaaef
     # Inject ND_NS for first router owned IP address.
    bbaaef
     src_ipv6=00100000000000000000000000000254
    bbaaef
     dst_ipv6=00100000000000000000000000000111
    bbaaef
    -send_nd_ns 1 1 ${src_mac} ${src_ipv6} ${dst_ipv6} 751d
    bbaaef
    +send_nd_ns 1 0 ${src_mac} ${src_ipv6} ${dst_ipv6} 751d
    bbaaef
     
    bbaaef
     # Verify that the ND_NS is sent only to rtr1.
    bbaaef
     match_nd_ns="priority=75.*${match_sw_metadata}.*icmp_type=135.*nd_target=10::111"
    bbaaef
    @@ -16079,7 +16176,51 @@ OVS_WAIT_UNTIL([
    bbaaef
         test "0" = "${pkts_flooded}"
    bbaaef
     ])
    bbaaef
     
    bbaaef
    -OVN_CLEANUP([hv1])
    bbaaef
    +# Inject ND_NS for FIP1.
    bbaaef
    +src_ipv6=00100000000000000000000000000254
    bbaaef
    +dst_ipv6=00100000000000000000000000000121
    bbaaef
    +send_nd_ns 1 0 ${src_mac} ${src_ipv6} ${dst_ipv6} 72dd
    bbaaef
    +
    bbaaef
    +# Verify that the ND_NS is replied to from hv1 and not hv2.
    bbaaef
    +match_nd_ns="priority=90.*${match_r1_metadata}.*icmp_type=135.*nd_target=10::121"
    bbaaef
    +
    bbaaef
    +as hv1
    bbaaef
    +OVS_WAIT_UNTIL([
    bbaaef
    +    pkts_on_rtr1=$(ovs-ofctl dump-flows br-int | \
    bbaaef
    +    grep -E "${match_nd_ns}" | grep n_packets=1 -c)
    bbaaef
    +    test "1" = "${pkts_on_rtr1}"
    bbaaef
    +])
    bbaaef
    +
    bbaaef
    +as hv2
    bbaaef
    +OVS_WAIT_UNTIL([
    bbaaef
    +    pkts_on_rtr1=$(ovs-ofctl dump-flows br-int | \
    bbaaef
    +    grep -E "${match_nd_ns}" | grep n_packets=1 -c)
    bbaaef
    +    test "0" = "${pkts_on_rtr1}"
    bbaaef
    +])
    bbaaef
    +
    bbaaef
    +# Inject ND_NS for FIP2.
    bbaaef
    +src_ipv6=00100000000000000000000000000254
    bbaaef
    +dst_ipv6=00100000000000000000000000000122
    bbaaef
    +send_nd_ns 1 0 ${src_mac} ${src_ipv6} ${dst_ipv6} 72db
    bbaaef
    +
    bbaaef
    +# Verify that the ND_NS is replied to from hv2 and not hv1.
    bbaaef
    +match_nd_ns="priority=90.*${match_r1_metadata}.*icmp_type=135.*nd_target=10::122"
    bbaaef
    +
    bbaaef
    +as hv2
    bbaaef
    +OVS_WAIT_UNTIL([
    bbaaef
    +    pkts_on_rtr1=$(ovs-ofctl dump-flows br-int | \
    bbaaef
    +    grep -E "${match_nd_ns}" | grep n_packets=1 -c)
    bbaaef
    +    test "1" = "${pkts_on_rtr1}"
    bbaaef
    +])
    bbaaef
    +
    bbaaef
    +as hv1
    bbaaef
    +OVS_WAIT_UNTIL([
    bbaaef
    +    pkts_on_rtr1=$(ovs-ofctl dump-flows br-int | \
    bbaaef
    +    grep -E "${match_nd_ns}" | grep n_packets=1 -c)
    bbaaef
    +    test "0" = "${pkts_on_rtr1}"
    bbaaef
    +])
    bbaaef
    +
    bbaaef
    +OVN_CLEANUP([hv1], [hv2])
    bbaaef
     AT_CLEANUP
    bbaaef
     
    bbaaef
     
    bbaaef
    -- 
    bbaaef
    1.8.3.1
    bbaaef