From: Numan Siddique <num...@ovn.org>

After the commit [1], OVN doesn't reply to the unicast ARP
requests for the known IPs.  This patch adds a global option
"unicast_arp_responder" and if set to true, OVN will also
respond to the unicast ARP requests.  This gives the option
for deployments which were relying on the older behavior.

However the main reason to add this option is to address
another issue.  Consider the below topology where logical switches
sw0 and sw1 are connected lr0. lr0 is also connected to a
public switch which is not shown here.

switch 8144b9c4-b38f-47db-a403-62283c8a5756 (sw0)
    port sw0-port2
        addresses: ["50:54:00:00:00:04 10.0.0.4"]
    port sw0-port1
        addresses: ["50:54:00:00:00:03 10.0.0.3"]
    port sw0-lr0
        type: router
        addresses: ["00:00:00:00:ff:01"]
        router-port: lr0-sw0

switch 8f53c293-9486-49ff-9e62-98ea3408ee2e (sw1)
    port sw1-port2
        addresses: ["40:54:00:00:00:04 20.0.0.4"]
    port sw1-lr0
        type: router
        addresses: ["00:00:00:00:ff:02"]
        router-port: lr0-sw1
    port sw1-port1
        addresses: ["40:54:00:00:00:03 20.0.0.3"]

ovn-nbctl lr-nat-list lr0
TYPE            EXTERNAL_IP      LOGICAL_IP          EXTERNAL_MAC         
LOGICAL_PORT
dnat_and_snat   172.168.0.110    10.0.0.3            50:54:00:00:00:03    
sw0-port1
dnat_and_snat   172.168.0.120    20.0.0.3            40:54:00:00:00:04    
sw1-port1

Here the logical port's mac is also used as external mac in the NATs.

ovn-northd adds the below logical flow in both the sw0 and sw1 pipeline

table=28(ls_in_l2_lkup      ), priority=75   ,
  match=(eth.src == {.., 50:54:00:00:00:03, 40:54:00:00:00:04, ..}
         && (arp.op == 1 || rarp.op == 3 || nd_ns)),
  action=(outport = "_MC_flood_l2"; output;)

This lflow is added to broadcast the self originated GARP packets.
Most likely to broadcast the GARPs generated by ovn-controller
and where the router MAC is used as source address [2].
Seems like this flow should have been added only on the logical switches
connected to the router if the IPs are reachable from it.

When sw0-port1 sends a unicast ARP request to any IP in its subnet,
instead of tunneling the packet to the destination chassis, the packet
gets flooded in the L2 domain since the sw0-port1's mac matches this
flow.

Until we fix this logical flow properly, this patch is sufficient to
address the unicast ARP request issue.  This causes a flood of
ARP packets in the geneve network.

[1] - c48ed1736a58("Do not reply on unicast arps for IPv4 targets.")
[2] - 32f5ebb06226 ("ovn-northd: Limit ARP/ND broadcast domain whenever 
possible.")

Signed-off-by: Numan Siddique <num...@ovn.org>
---
 northd/en-global-config.c |  6 ++++++
 northd/northd.c           | 26 +++++++++++++++++---------
 ovn-nb.xml                |  9 +++++++++
 tests/ovn-northd.at       | 19 +++++++++++++++++--
 4 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/northd/en-global-config.c b/northd/en-global-config.c
index c103b137f6..d9b7dcb0a8 100644
--- a/northd/en-global-config.c
+++ b/northd/en-global-config.c
@@ -269,6 +269,12 @@ global_config_nb_global_handler(struct engine_node *node, 
void *data)
         return false;
     }
 
+    /* Check if northd_internal_version has changed or not. */
+    if (config_out_of_sync(&nb->options, &config_data->nb_options,
+                           "unicast_arp_responder", false)) {
+        return false;
+    }
+
     if (check_nb_options_out_of_sync(nb, config_data, sampling_apps)) {
         config_data->tracked_data.nb_options_changed = true;
     }
diff --git a/northd/northd.c b/northd/northd.c
index 880ec92ac2..78a7125ce1 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -98,6 +98,9 @@ static bool vxlan_mode;
 
 static bool vxlan_ic_mode;
 
+/* Respond to unicast ARP requests for known ips or not. */
+static bool unicast_arp_responder = false;
+
 #define MAX_OVN_TAGS 4096
 
 
@@ -9515,15 +9518,16 @@ build_lswitch_arp_nd_responder_known_ips(struct 
ovn_port *op,
         for (size_t i = 0; i < op->n_lsp_addrs; i++) {
             for (size_t j = 0; j < op->lsp_addrs[i].n_ipv4_addrs; j++) {
                 ds_clear(match);
-                /* Do not reply on unicast ARPs, forward them to the target
-                 * to have ability to monitor target liveness via unicast
-                 * ARP requests.
-                */
-                ds_put_format(match,
-                    "arp.tpa == %s && "
-                    "arp.op == 1 && "
-                    "eth.dst == ff:ff:ff:ff:ff:ff",
-                    op->lsp_addrs[i].ipv4_addrs[j].addr_s);
+                ds_put_format(match, "arp.tpa == %s && arp.op == 1",
+                              op->lsp_addrs[i].ipv4_addrs[j].addr_s);
+
+                if (!unicast_arp_responder) {
+                    /* Do not reply on unicast ARPs, forward them to the target
+                     * to have ability to monitor target liveness via unicast
+                     * ARP requests.
+                    */
+                   ds_put_cstr(match, " && eth.dst == ff:ff:ff:ff:ff:ff");
+                }
                 ds_clear(actions);
                 ds_put_format(actions,
                     "eth.dst = eth.src; "
@@ -18980,6 +18984,10 @@ ovnnb_db_run(struct northd_input *input_data,
     use_common_zone = smap_get_bool(input_data->nb_options, "use_common_zone",
                                     false);
 
+    unicast_arp_responder = smap_get_bool(input_data->nb_options,
+                                          "unicast_arp_responder",
+                                          false);
+
     vxlan_mode = is_vxlan_mode(input_data->nb_options,
                                input_data->sbrec_chassis_table);
 
diff --git a/ovn-nb.xml b/ovn-nb.xml
index bf1f1628bd..7f8021667c 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -429,6 +429,15 @@
         </p>
       </column>
 
+      <column name="options" key="unicast_arp_responder" type='{"type": 
"boolean"}'>
+        <p>
+          <code>ovn-northd</code> adds ARP responder flows for known IPs for
+          broadcast ARP request packets.  If this option is set, it will also
+          respond to unicast ARP requests.  By default this option is set to
+          <code>false</code>.
+        </p>
+      </column>
+
       <group title="Options for configuring interconnection route 
advertisement">
         <p>
           These options control how routes are advertised between OVN
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index e3a65e7a44..f0322a311c 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -9869,7 +9869,7 @@ AT_CLEANUP
 ])
 
 OVN_FOR_EACH_NORTHD_NO_HV([
-AT_SETUP([check options:disable_arp_nd_rsp for LSP])
+AT_SETUP([ARP responder flows])
 ovn_start NORTHD_TYPE
 check ovn-nbctl ls-add S1
 check ovn-nbctl --wait=sb lsp-add S1 S1-vm1
@@ -9886,7 +9886,22 @@ AT_CHECK([grep -e "ls_in_arp_rsp" S1flows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_arp_rsp      ), priority=50   , match=(nd_ns_mcast && ip6.dst 
== ff02::1:ff00:10 && nd.target == fd00::10), action=(nd_na { eth.src = 
50:54:00:00:00:10; ip6.src = fd00::10; nd.target = fd00::10; nd.tll = 
50:54:00:00:00:10; outport = inport; flags.loopback = 1; output; };)
 ])
 
-#Set the disable_arp_nd_rsp option and verify the flow
+check ovn-nbctl set NB_Global . options:unicast_arp_responder=true
+check ovn-nbctl --wait=sb sync
+
+ovn-sbctl dump-flows S1 > S1flows
+AT_CAPTURE_FILE([S1flows])
+
+AT_CHECK([grep -e "ls_in_arp_rsp" S1flows | ovn_strip_lflows], [0], [dnl
+  table=??(ls_in_arp_rsp      ), priority=0    , match=(1), action=(next;)
+  table=??(ls_in_arp_rsp      ), priority=100  , match=(arp.tpa == 
192.168.0.10 && arp.op == 1 && inport == "S1-vm1"), action=(next;)
+  table=??(ls_in_arp_rsp      ), priority=100  , match=(nd_ns_mcast && ip6.dst 
== ff02::1:ff00:10 && nd.target == fd00::10 && inport == "S1-vm1"), 
action=(next;)
+  table=??(ls_in_arp_rsp      ), priority=50   , match=(arp.tpa == 
192.168.0.10 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 
50:54:00:00:00:10; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 
50:54:00:00:00:10; arp.tpa = arp.spa; arp.spa = 192.168.0.10; outport = inport; 
flags.loopback = 1; output;)
+  table=??(ls_in_arp_rsp      ), priority=50   , match=(nd_ns_mcast && ip6.dst 
== ff02::1:ff00:10 && nd.target == fd00::10), action=(nd_na { eth.src = 
50:54:00:00:00:10; ip6.src = fd00::10; nd.target = fd00::10; nd.tll = 
50:54:00:00:00:10; outport = inport; flags.loopback = 1; output; };)
+])
+
+
+# Set the disable_arp_nd_rsp option and verify the flow
 check ovn-nbctl --wait=sb set logical_switch_port S1-vm1 
options:disable_arp_nd_rsp=true
 
 ovn-sbctl dump-flows S1 > S1flows
-- 
2.49.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to