From 913179b88c7b0e191a5cad635efb65e661726f09 Mon Sep 17 00:00:00 2001
From: Dumitru Ceara <dceara@redhat.com>
Date: Tue, 12 Nov 2019 08:57:08 -0800
Subject: [PATCH ovn 1/3] ovn-northd: Fix get_router_load_balancer_ips() for
mixed address families.
Function get_router_load_balancer_ips() was incorrectly returning a
single address_family even though the IP set could contain a mix of
IPv4 and IPv6 addresses.
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
Signed-off-by: Han Zhou <hzhou@ovn.org>
(cherry-picked from upstream commit d0ef9f0ac9b9e78a8a54e31ca62a66c640c0346a)
---
ovn/northd/ovn-northd.c | 126 +++++++++++++++++++++++++++---------------------
1 file changed, 72 insertions(+), 54 deletions(-)
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index d94276b..81c313f 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -2184,7 +2184,7 @@ ip_address_and_port_from_lb_key(const char *key, char **ip_address,
static void
get_router_load_balancer_ips(const struct ovn_datapath *od,
- struct sset *all_ips, int *addr_family)
+ struct sset *all_ips_v4, struct sset *all_ips_v6)
{
if (!od->nbr) {
return;
@@ -2199,13 +2199,21 @@ get_router_load_balancer_ips(const struct ovn_datapath *od,
/* node->key contains IP:port or just IP. */
char *ip_address = NULL;
uint16_t port;
+ int addr_family;
ip_address_and_port_from_lb_key(node->key, &ip_address, &port,
- addr_family);
+ &addr_family);
if (!ip_address) {
continue;
}
+ struct sset *all_ips;
+ if (addr_family == AF_INET) {
+ all_ips = all_ips_v4;
+ } else {
+ all_ips = all_ips_v6;
+ }
+
if (!sset_contains(all_ips, ip_address)) {
sset_add(all_ips, ip_address);
}
@@ -2299,17 +2307,22 @@ get_nat_addresses(const struct ovn_port *op, size_t *n)
}
}
- /* A set to hold all load-balancer vips. */
- struct sset all_ips = SSET_INITIALIZER(&all_ips);
- int addr_family;
- get_router_load_balancer_ips(op->od, &all_ips, &addr_family);
+ /* Two sets to hold all load-balancer vips. */
+ struct sset all_ips_v4 = SSET_INITIALIZER(&all_ips_v4);
+ struct sset all_ips_v6 = SSET_INITIALIZER(&all_ips_v6);
+ get_router_load_balancer_ips(op->od, &all_ips_v4, &all_ips_v6);
const char *ip_address;
- SSET_FOR_EACH (ip_address, &all_ips) {
+ SSET_FOR_EACH (ip_address, &all_ips_v4) {
ds_put_format(&c_addresses, " %s", ip_address);
central_ip_address = true;
}
- sset_destroy(&all_ips);
+ SSET_FOR_EACH (ip_address, &all_ips_v6) {
+ ds_put_format(&c_addresses, " %s", ip_address);
+ central_ip_address = true;
+ }
+ sset_destroy(&all_ips_v4);
+ sset_destroy(&all_ips_v6);
if (central_ip_address) {
/* Gratuitous ARP for centralized NAT rules on distributed gateway
@@ -6893,61 +6906,66 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
}
/* A set to hold all load-balancer vips that need ARP responses. */
- struct sset all_ips = SSET_INITIALIZER(&all_ips);
- int addr_family;
- get_router_load_balancer_ips(op->od, &all_ips, &addr_family);
+ struct sset all_ips_v4 = SSET_INITIALIZER(&all_ips_v4);
+ struct sset all_ips_v6 = SSET_INITIALIZER(&all_ips_v6);
+ get_router_load_balancer_ips(op->od, &all_ips_v4, &all_ips_v6);
const char *ip_address;
- SSET_FOR_EACH(ip_address, &all_ips) {
+ SSET_FOR_EACH (ip_address, &all_ips_v4) {
ds_clear(&match);
- if (addr_family == AF_INET) {
- ds_put_format(&match,
- "inport == %s && arp.tpa == %s && arp.op == 1",
- op->json_key, ip_address);
- } else {
- ds_put_format(&match,
- "inport == %s && nd_ns && nd.target == %s",
- op->json_key, ip_address);
- }
+ ds_put_format(&match,
+ "inport == %s && arp.tpa == %s && arp.op == 1",
+ op->json_key, ip_address);
ds_clear(&actions);
- if (addr_family == AF_INET) {
- ds_put_format(&actions,
- "eth.dst = eth.src; "
- "eth.src = %s; "
- "arp.op = 2; /* ARP reply */ "
- "arp.tha = arp.sha; "
- "arp.sha = %s; "
- "arp.tpa = arp.spa; "
- "arp.spa = %s; "
- "outport = %s; "
- "flags.loopback = 1; "
- "output;",
- op->lrp_networks.ea_s,
- op->lrp_networks.ea_s,
- ip_address,
- op->json_key);
- } else {
- ds_put_format(&actions,
- "nd_na { "
- "eth.src = %s; "
- "ip6.src = %s; "
- "nd.target = %s; "
- "nd.tll = %s; "
- "outport = inport; "
- "flags.loopback = 1; "
- "output; "
- "};",
- op->lrp_networks.ea_s,
- ip_address,
- ip_address,
- op->lrp_networks.ea_s);
- }
+ ds_put_format(&actions,
+ "eth.dst = eth.src; "
+ "eth.src = %s; "
+ "arp.op = 2; /* ARP reply */ "
+ "arp.tha = arp.sha; "
+ "arp.sha = %s; "
+ "arp.tpa = arp.spa; "
+ "arp.spa = %s; "
+ "outport = %s; "
+ "flags.loopback = 1; "
+ "output;",
+ op->lrp_networks.ea_s,
+ op->lrp_networks.ea_s,
+ ip_address,
+ op->json_key);
+
ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
ds_cstr(&match), ds_cstr(&actions));
}
- sset_destroy(&all_ips);
+ SSET_FOR_EACH (ip_address, &all_ips_v6) {
+ ds_clear(&match);
+ ds_put_format(&match,
+ "inport == %s && nd_ns && nd.target == %s",
+ op->json_key, ip_address);
+
+ ds_clear(&actions);
+ ds_put_format(&actions,
+ "nd_na { "
+ "eth.src = %s; "
+ "ip6.src = %s; "
+ "nd.target = %s; "
+ "nd.tll = %s; "
+ "outport = inport; "
+ "flags.loopback = 1; "
+ "output; "
+ "};",
+ op->lrp_networks.ea_s,
+ ip_address,
+ ip_address,
+ op->lrp_networks.ea_s);
+
+ ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
+ ds_cstr(&match), ds_cstr(&actions));
+ }
+
+ sset_destroy(&all_ips_v4);
+ sset_destroy(&all_ips_v6);
/* A gateway router can have 2 SNAT IP addresses to force DNATed and
* LBed traffic respectively to be SNATed. In addition, there can be
--
1.8.3.1