When a VM sends an ARP or an ND NS for its own IP address, it is trying to
check for a duplicate address in the network.  OVN needs to suppress the
reply in such a case, otherwise the VM thinks that its address is a
duplicate.

Reported-by: Valentine Sinitsyn <valentine.sinit...@gmail.com>
Reported-at: http://openvswitch.org/pipermail/dev/2016-September/080037.html
Signed-off-by: Ben Pfaff <b...@ovn.org>
---
 ovn/northd/ovn-northd.8.xml | 23 +++++++++++++++++++++++
 ovn/northd/ovn-northd.c     | 22 ++++++++++++++++++++++
 tests/ovn.at                | 14 ++++++++++----
 3 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml
index 1da633a..77eb3d1 100644
--- a/ovn/northd/ovn-northd.8.xml
+++ b/ovn/northd/ovn-northd.8.xml
@@ -479,6 +479,29 @@ nd_na {
       </li>
 
       <li>
+        <p>
+          Priority-100 flows with match criteria like the ARP and ND flows
+          above, except that they only match packets from the
+          <code>inport</code> that owns the IP addresses in question, with
+          action <code>next;</code>.  These flows prevent OVN from replying to,
+          for example, an ARP request emitted by a VM for its own IP address.
+          A VM only makes this kind of request to attempt to detect a duplicate
+          IP address assignment, so sending a reply will prevent the VM from
+          accepting the IP address that it owns.
+        </p>
+
+        <p>
+          In place of <code>next;</code>, it would be reasonable to use
+          <code>drop;</code> for the flows' actions.  If everything is working
+          as it is configured, then this would produce equivalent results,
+          since no host should reply to the request.  But ARPing for one's own
+          IP address is intended to detect situations where the network is not
+          working as configured, so dropping the request would frustrate that
+          intent.
+        </p>
+      </li>
+
+      <li>
         One priority-0 fallback flow that matches all packets and advances to
         the next table.
       </li>
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index cdc5525..eeeb41d 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -2728,6 +2728,22 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap 
*ports,
                     op->lsp_addrs[i].ipv4_addrs[j].addr_s);
                 ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 50,
                               ds_cstr(&match), ds_cstr(&actions));
+
+                /* Do not reply to an ARP request from the port that owns the
+                 * address (otherwise a DHCP client that ARPs to check for a
+                 * duplicate address will fail).  Instead, forward it the usual
+                 * way.
+                 *
+                 * (Another alternative would be to simply drop the packet.  If
+                 * everything is working as it is configured, then this would
+                 * produce equivalent results, since no one should reply to the
+                 * request.  But ARPing for one's own IP address is intended to
+                 * detect situations where the network is not working as
+                 * configured, so dropping the request would frustrate that
+                 * intent.) */
+                ds_put_format(&match, " && inport == %s", op->json_key);
+                ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 100,
+                              ds_cstr(&match), "next;");
             }
 
             /* For ND solicitations, we need to listen for both the
@@ -2758,6 +2774,12 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap 
*ports,
                         op->lsp_addrs[i].ea_s);
                 ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 50,
                               ds_cstr(&match), ds_cstr(&actions));
+
+                /* Do not reply to a solicitation from the port that owns the
+                 * address (otherwise DAD detection will fail). */
+                ds_put_format(&match, " && inport == %s", op->json_key);
+                ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 100,
+                              ds_cstr(&match), "next;");
             }
         }
     }
diff --git a/tests/ovn.at b/tests/ovn.at
index 677ab46..68885b9 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1159,13 +1159,18 @@ for is in 1 2 3; do
                 sip=`ip_to_hex 192 168 0 $i$j`
                 tip=`ip_to_hex 192 168 0 $id$jd`
                 tip_unknown=`ip_to_hex 11 11 11 11`
-                test_arp $s f000000000$s $sip $tip f000000000$d            #9
+                if test $d != $s; then
+                    reply_ha=f000000000$d
+                else
+                    reply_ha=
+                fi
+                test_arp $s f000000000$s $sip $tip $reply_ha               #9
                 test_arp $s f000000000$s $sip $tip_unknown                 #10
 
                 if test $jd = 3; then
                     # lsp[123]3 has an additional ip 192.169.0.[123]3.
                     tip=`ip_to_hex 192 169 0 $id$jd`
-                    test_arp $s f000000000$s $sip $tip f000000000$d        #9
+                    test_arp $s f000000000$s $sip $tip $reply_ha           #9
                 fi
             done
         done
@@ -1413,13 +1418,14 @@ for s in 1 2 3; do
         sip=192.168.0.$s
         tip=192.168.0.$d
         tip_unknown=11.11.11.11
-        test_arp $s f0:00:00:00:00:0$s $sip $tip f0:00:00:00:00:0$d        #9
+        if test $d != $s; then reply_ha=f0:00:00:00:00:0$d; else reply_ha=; fi
+        test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha                 #9
         test_arp $s f0:00:00:00:00:0$s $sip $tip_unknown                   #10
 
         if test $d = 3; then
             # lp3 has an additional ip 192.169.0.[123]3.
             tip=192.169.0.$d
-            test_arp $s f0:00:00:00:00:0$s $sip $tip f0:00:00:00:00:0$d    #9
+            test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha             #9
         fi
     done
 
-- 
2.1.3

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to