@@ -8832,8 +8832,15 @@ 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);
- ds_put_format(match, "arp.tpa == %s && arp.op == 1",
- op->lsp_addrs[i].ipv4_addrs[j].addr_s);
+ /* NOTE(vsaienko): Do not reply on unicast ARPs, forward
+ * them to the target to have ability to monitor target
+ * aliveness via ARPs.
+ */
+ 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_clear(actions);
ds_put_format(actions,
"eth.dst = eth.src; "
@@ -1435,9 +1435,10 @@
<li>
<p>
- Priority-50 flows that match ARP requests to each known IP address
- <var>A</var> of every logical switch port, and respond with ARP
- replies directly with corresponding Ethernet address <var>E</var>:
+ Priority-50 flows that match only broadcast ARP requests to each
+ known IPv4 address <var>A</var> of every logical switch port, and
+ respond with ARP replies directly with corresponding Ethernet
+ address <var>E</var>:
</p>
<pre>
@@ -9283,9 +9283,9 @@ 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=(arp.tpa == 192.168.0.10 && arp.op == 1 && eth.dst == ff:ff:ff:ff:ff:ff && inport == "S1-vm1"), action=(next;)
table=??(ls_in_arp_rsp ), priority=100 , match=(nd_ns && ip6.dst == {fd00::10, 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=(arp.tpa == 192.168.0.10 && arp.op == 1 && eth.dst == ff:ff:ff:ff:ff:ff), 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 && ip6.dst == {fd00::10, 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; };)
])
Reply only if target ethernet address is broadcast, if address is specified explicitly do noting to let target reply by itself. This technique allows to monitor target aliveness with arping. Closes #239 Signed-off-by: Vasyl Saienko <vsaienko@mirantis.com> --- northd/northd.c | 11 +++++++++-- northd/ovn-northd.8.xml | 7 ++++--- tests/ovn-northd.at | 4 ++-- 3 files changed, 15 insertions(+), 7 deletions(-)