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