This allows CMS to tweak the way logical routers reply to ARP/ND packets
targeting load balancer VIPs. By default a router only replies for VIPs
that are reachable locally (they're part of a subnet configured on the
router). There are cases though when it's desirable for routers to
reply for all VIPs.
Reported-at: https://github.com/ovn-org/ovn/issues/124
Reported-by: Tom Parrott <[email protected]>
Signed-off-by: Dumitru Ceara <[email protected]>
---
NEWS | 4 ++++
northd/northd.c | 20 ++++++++++++++++++++
ovn-nb.xml | 9 +++++++++
tests/ovn-northd.at | 10 ++++++++--
4 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/NEWS b/NEWS
index dbe89e9cf..ed735c32c 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,10 @@ Post v22.03.0
- Support NAT for logical routers with multiple distributed
gateway ports.
- Add global option (NB_Global.options:default_acl_drop) to enable
implicit drop behavior on logical switches with ACLs applied.
+ - Add NB.Load_Balancer.options:neighbor_responder to allow the CMS to
+ explicitly request routers to reply to any ARP/ND request for a VIP
+ (when set to "all") and only for reachable VIPs (when set to
"reachable"
+ or by default).
OVN v22.03.0 - 11 Mar 2022
--------------------------
diff --git a/northd/northd.c b/northd/northd.c
index a56666297..f01bd2cf7 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -3920,6 +3920,26 @@ static void
build_lrouter_lb_reachable_ips(struct ovn_datapath *od,
const struct ovn_northd_lb *lb)
{
+ const char *neighbor_responder_mode =
+ smap_get_def(&lb->nlb->options, "neighbor_responder",
"reachable");
+
+ /* If configured to reply to neighbor requests for all VIPs force
them
+ * all to be considered "reachable".
+ */
+ if (!strcmp(neighbor_responder_mode, "all")) {
+ for (size_t i = 0; i < lb->n_vips; i++) {
+ if (IN6_IS_ADDR_V4MAPPED(&lb->vips[i].vip)) {
+ sset_add(&od->lb_ips_v4_reachable, lb->vips[i].vip_str);
+ } else {
+ sset_add(&od->lb_ips_v6_reachable, lb->vips[i].vip_str);
+ }
+ }
+ return;
+ }
+
+ /* Otherwise, a VIP is reachable if there's at least one router
+ * subnet that includes it.
+ */
for (size_t i = 0; i < lb->n_vips; i++) {
if (IN6_IS_ADDR_V4MAPPED(&lb->vips[i].vip)) {
ovs_be32 vip_ip4 =
in6_addr_get_mapped_ipv4(&lb->vips[i].vip);
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 9010240a8..756c2a378 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1856,6 +1856,15 @@
more information about what flows are added for IP routes,
please
see the <code>ovn-northd</code> manpage section on IP Routing.
</column>
+
+ <column name="options" key="neighbor_responder">
+ If set to <code>all</code>, then routers on which the load
balancer
+ is applied reply to ARP/neighbor discovery requests for all VIPs
+ of the load balancer. If set to <code>reachable</code>, then
routers
+ on which the load balancer is applied reply to ARP/neighbor
discovery
+ requests only for VIPs that are part of a router's subnet.
The default
+ value of this option, if not specified, is
<code>reachable</code>.
+ </column>
</group>
</table>
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 69ad85533..8e256de2e 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -1708,6 +1708,10 @@ ovn-nbctl lb-add lb5
"[[fe80::200:ff:fe00:101]]:8080" "[[fe02::200:ff:fe00:101]]
ovn-nbctl lb-add lb5 "[[fe80::200:ff:fe00:102]]:8080"
"[[fe02::200:ff:fe00:102]]:8080"
ovn-nbctl lb-add lb6 "43.43.43.43:8080" "10.0.0.8:8080" udp
ovn-nbctl lb-add lb7 "[[4343::4343]]:8080" "[[10::10]]:8080" udp
+ovn-nbctl lb-add lb8 "44.44.44.44:8080" "10.0.0.8:8080" udp
+ovn-nbctl set Load_Balancer lb8 options:neighbor_responder=all
+ovn-nbctl lb-add lb9 "[[4444::4444]]:8080" "[[10::10]]:8080" udp
+ovn-nbctl set Load_Balancer lb9 options:neighbor_responder=all
ovn-nbctl lr-lb-add lr lb1
ovn-nbctl lr-lb-add lr lb2
@@ -1716,6 +1720,8 @@ ovn-nbctl lr-lb-add lr lb4
ovn-nbctl lr-lb-add lr lb5
ovn-nbctl lr-lb-add lr lb6
ovn-nbctl lr-lb-add lr lb7
+ovn-nbctl lr-lb-add lr lb8
+ovn-nbctl lr-lb-add lr lb9
ovn-nbctl --wait=sb sync
lr_key=$(fetch_column sb:datapath_binding tunnel_key
external_ids:name=lr)
@@ -1723,8 +1729,8 @@ lb_as_v4="_rtr_lb_${lr_key}_ip4"
lb_as_v6="_rtr_lb_${lr_key}_ip6"
# Check generated VIP address sets (only reachable IPs).
-check_column '43.43.43.43' Address_Set addresses name=${lb_as_v4}
-check_column '4343::4343 fe80::200:ff:fe00:101 fe80::200:ff:fe00:102'
Address_Set addresses name=${lb_as_v6}
+check_column '43.43.43.43 44.44.44.44' Address_Set addresses
name=${lb_as_v4}
+check_column '4343::4343 4444::4444 fe80::200:ff:fe00:101
fe80::200:ff:fe00:102' Address_Set addresses name=${lb_as_v6}
# Ingress router port ETH address is stored in lr_in_admission.
AT_CHECK([ovn-sbctl lflow-list | grep -E
"lr_in_admission.*xreg0\[[0..47\]]" | sort], [0], [dnl