|
|
bbaaef |
From 14de43e68f38fab76e50c21d3773f44c6e119d0e Mon Sep 17 00:00:00 2001
|
|
|
bbaaef |
From: Numan Siddique <numans@ovn.org>
|
|
|
bbaaef |
Date: Mon, 27 Jan 2020 18:36:24 +0530
|
|
|
bbaaef |
Subject: [PATCH 2/2] ovn-northd: Consider load balancer active backends in
|
|
|
bbaaef |
router pipeline
|
|
|
bbaaef |
MIME-Version: 1.0
|
|
|
bbaaef |
Content-Type: text/plain; charset=UTF-8
|
|
|
bbaaef |
Content-Transfer-Encoding: 8bit
|
|
|
bbaaef |
|
|
|
bbaaef |
The commit [1] which added lood balancer health check support
|
|
|
bbaaef |
missed out on updating the logical flows to consider only
|
|
|
bbaaef |
active backends in the logical router pipeline if a load balancer
|
|
|
bbaaef |
is associated. This patch fixes it. It also refactors the code
|
|
|
bbaaef |
a bit.
|
|
|
bbaaef |
|
|
|
bbaaef |
Without this, an offline backend may be chosen for load balancing,
|
|
|
bbaaef |
resulting in the packet loss.
|
|
|
bbaaef |
|
|
|
bbaaef |
This patch also adds logical flows in ingress ACL and egress ACL logical
|
|
|
bbaaef |
switch datapath pipeline to skip the ACL policies for service monitor health
|
|
|
bbaaef |
check traffic.
|
|
|
bbaaef |
|
|
|
bbaaef |
[1] - ba0d6eae960d("ovn-northd: Add support for Load Balancer health check")
|
|
|
bbaaef |
|
|
|
bbaaef |
Reported-by: Maciej Józefczyk <mjozefcz@redhat.com>
|
|
|
bbaaef |
Fixes - ba0d6eae960d("ovn-northd: Add support for Load Balancer health check")
|
|
|
bbaaef |
Signed-off-by: Numan Siddique <numans@ovn.org>
|
|
|
bbaaef |
Acked-by: Dumitru Ceara <dceara@redhat.com>
|
|
|
bbaaef |
|
|
|
bbaaef |
(cherry-picked from upstream commit bb9f2b9ce56c9319066524c0ad89034adae6b168)
|
|
|
bbaaef |
Conflicts:
|
|
|
bbaaef |
tests/ovn.at
|
|
|
bbaaef |
|
|
|
bbaaef |
Change-Id: Ibacbaace0d710aa4d3e0b1d077e032443dd2a9e6
|
|
|
bbaaef |
---
|
|
|
bbaaef |
ovn/northd/ovn-northd.8.xml | 22 +++
|
|
|
bbaaef |
ovn/northd/ovn-northd.c | 268 +++++++++++++++++-------------------
|
|
|
bbaaef |
tests/ovn.at | 27 ++++
|
|
|
bbaaef |
3 files changed, 172 insertions(+), 145 deletions(-)
|
|
|
bbaaef |
|
|
|
bbaaef |
diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml
|
|
|
bbaaef |
index 11ef65964..50f7d941b 100644
|
|
|
bbaaef |
--- a/ovn/northd/ovn-northd.8.xml
|
|
|
bbaaef |
+++ b/ovn/northd/ovn-northd.8.xml
|
|
|
bbaaef |
@@ -410,6 +410,17 @@
|
|
|
bbaaef |
in the request direction are skipped here to let a newly created
|
|
|
bbaaef |
ACL re-allow this connection.
|
|
|
bbaaef |
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ A priority 34000 logical flow is added for each logical switch datapath
|
|
|
bbaaef |
+ with the match eth.dst = E to allow the service
|
|
|
bbaaef |
+ monitor reply packet destined to ovn-controller
|
|
|
bbaaef |
+ with the action next , where E is the
|
|
|
bbaaef |
+ service monitor mac defined in the
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ db="OVN_Northbound"/> colum of
|
|
|
bbaaef |
+ db="OVN_Northbound"/> table.
|
|
|
bbaaef |
+
|
|
|
bbaaef |
|
|
|
bbaaef |
|
|
|
bbaaef |
Ingress Table 7: from-lport QoS Marking
|
|
|
bbaaef |
@@ -1220,6 +1231,17 @@ output;
|
|
|
bbaaef |
to allow the DNS reply packet from the
|
|
|
bbaaef |
Ingress Table 15:DNS responses .
|
|
|
bbaaef |
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ A priority 34000 logical flow is added for each logical switch datapath
|
|
|
bbaaef |
+ with the match eth.src = E to allow the service
|
|
|
bbaaef |
+ monitor request packet generated by ovn-controller
|
|
|
bbaaef |
+ with the action next , where E is the
|
|
|
bbaaef |
+ service monitor mac defined in the
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ db="OVN_Northbound"/> colum of
|
|
|
bbaaef |
+ db="OVN_Northbound"/> table.
|
|
|
bbaaef |
+
|
|
|
bbaaef |
|
|
|
bbaaef |
|
|
|
bbaaef |
Egress Table 5: to-lport QoS Marking
|
|
|
bbaaef |
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
|
|
|
bbaaef |
index b71ae7a94..7139143b3 100644
|
|
|
bbaaef |
--- a/ovn/northd/ovn-northd.c
|
|
|
bbaaef |
+++ b/ovn/northd/ovn-northd.c
|
|
|
bbaaef |
@@ -3008,6 +3008,7 @@ struct lb_vip {
|
|
|
bbaaef |
struct lb_vip_backend {
|
|
|
bbaaef |
char *ip;
|
|
|
bbaaef |
uint16_t port;
|
|
|
bbaaef |
+ int addr_family;
|
|
|
bbaaef |
|
|
|
bbaaef |
struct ovn_port *op; /* Logical port to which the ip belong to. */
|
|
|
bbaaef |
bool health_check;
|
|
|
bbaaef |
@@ -3163,6 +3164,7 @@ ovn_lb_create(struct northd_context *ctx, struct hmap *lbs,
|
|
|
bbaaef |
|
|
|
bbaaef |
lb->vips[n_vips].backends[i].ip = backend_ip;
|
|
|
bbaaef |
lb->vips[n_vips].backends[i].port = backend_port;
|
|
|
bbaaef |
+ lb->vips[n_vips].backends[i].addr_family = addr_family;
|
|
|
bbaaef |
lb->vips[n_vips].backends[i].op = op;
|
|
|
bbaaef |
lb->vips[n_vips].backends[i].svc_mon_src_ip = svc_mon_src_ip;
|
|
|
bbaaef |
|
|
|
bbaaef |
@@ -3226,6 +3228,38 @@ ovn_lb_destroy(struct ovn_lb *lb)
|
|
|
bbaaef |
free(lb->vips);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
+static void build_lb_vip_ct_lb_actions(struct lb_vip *lb_vip,
|
|
|
bbaaef |
+ struct ds *action)
|
|
|
bbaaef |
+{
|
|
|
bbaaef |
+ if (lb_vip->health_check) {
|
|
|
bbaaef |
+ ds_put_cstr(action, "ct_lb(");
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ size_t n_active_backends = 0;
|
|
|
bbaaef |
+ for (size_t k = 0; k < lb_vip->n_backends; k++) {
|
|
|
bbaaef |
+ struct lb_vip_backend *backend = &lb_vip->backends[k];
|
|
|
bbaaef |
+ if (backend->health_check && backend->sbrec_monitor &&
|
|
|
bbaaef |
+ backend->sbrec_monitor->status &&
|
|
|
bbaaef |
+ strcmp(backend->sbrec_monitor->status, "online")) {
|
|
|
bbaaef |
+ continue;
|
|
|
bbaaef |
+ }
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ n_active_backends++;
|
|
|
bbaaef |
+ ds_put_format(action, "%s:%"PRIu16",",
|
|
|
bbaaef |
+ backend->ip, backend->port);
|
|
|
bbaaef |
+ }
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ if (!n_active_backends) {
|
|
|
bbaaef |
+ ds_clear(action);
|
|
|
bbaaef |
+ ds_put_cstr(action, "drop;");
|
|
|
bbaaef |
+ } else {
|
|
|
bbaaef |
+ ds_chomp(action, ',');
|
|
|
bbaaef |
+ ds_put_cstr(action, ");");
|
|
|
bbaaef |
+ }
|
|
|
bbaaef |
+ } else {
|
|
|
bbaaef |
+ ds_put_format(action, "ct_lb(%s);", lb_vip->backend_ips);
|
|
|
bbaaef |
+ }
|
|
|
bbaaef |
+}
|
|
|
bbaaef |
+
|
|
|
bbaaef |
static void
|
|
|
bbaaef |
build_ovn_lbs(struct northd_context *ctx, struct hmap *ports,
|
|
|
bbaaef |
struct hmap *lbs)
|
|
|
bbaaef |
@@ -4579,11 +4613,11 @@ ls_has_dns_records(const struct nbrec_logical_switch *nbs)
|
|
|
bbaaef |
|
|
|
bbaaef |
static void
|
|
|
bbaaef |
build_empty_lb_event_flow(struct ovn_datapath *od, struct hmap *lflows,
|
|
|
bbaaef |
- struct smap_node *node, char *ip_address,
|
|
|
bbaaef |
- struct nbrec_load_balancer *lb, uint16_t port,
|
|
|
bbaaef |
- int addr_family, int pl, struct shash *meter_groups)
|
|
|
bbaaef |
+ struct lb_vip *lb_vip,
|
|
|
bbaaef |
+ struct nbrec_load_balancer *lb,
|
|
|
bbaaef |
+ int pl, struct shash *meter_groups)
|
|
|
bbaaef |
{
|
|
|
bbaaef |
- if (!controller_event_en || node->value[0]) {
|
|
|
bbaaef |
+ if (!controller_event_en || lb_vip->n_backends) {
|
|
|
bbaaef |
return;
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
@@ -4594,32 +4628,35 @@ build_empty_lb_event_flow(struct ovn_datapath *od, struct hmap *lflows,
|
|
|
bbaaef |
meter = "event-elb";
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
- if (addr_family == AF_INET) {
|
|
|
bbaaef |
- ds_put_format(&match, "ip4.dst == %s && %s",
|
|
|
bbaaef |
- ip_address, lb->protocol);
|
|
|
bbaaef |
- } else {
|
|
|
bbaaef |
- ds_put_format(&match, "ip6.dst == %s && %s",
|
|
|
bbaaef |
- ip_address, lb->protocol);
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
- if (port) {
|
|
|
bbaaef |
+ ds_put_format(&match, "ip%s.dst == %s && %s",
|
|
|
bbaaef |
+ lb_vip->addr_family == AF_INET ? "4": "6",
|
|
|
bbaaef |
+ lb_vip->vip, lb->protocol);
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ char *vip = lb_vip->vip;
|
|
|
bbaaef |
+ if (lb_vip->vip_port) {
|
|
|
bbaaef |
ds_put_format(&match, " && %s.dst == %u", lb->protocol,
|
|
|
bbaaef |
- port);
|
|
|
bbaaef |
+ lb_vip->vip_port);
|
|
|
bbaaef |
+ vip = xasprintf("%s:%u", lb_vip->vip, lb_vip->vip_port);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
+
|
|
|
bbaaef |
action = xasprintf("trigger_event(event = \"%s\", "
|
|
|
bbaaef |
"meter = \"%s\", vip = \"%s\", "
|
|
|
bbaaef |
"protocol = \"%s\", "
|
|
|
bbaaef |
"load_balancer = \"" UUID_FMT "\");",
|
|
|
bbaaef |
event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS),
|
|
|
bbaaef |
- meter, node->key, lb->protocol,
|
|
|
bbaaef |
+ meter, vip, lb->protocol,
|
|
|
bbaaef |
UUID_ARGS(&lb->header_.uuid));
|
|
|
bbaaef |
ovn_lflow_add(lflows, od, pl, 130, ds_cstr(&match), action);
|
|
|
bbaaef |
ds_destroy(&match);
|
|
|
bbaaef |
+ if (lb_vip->vip_port) {
|
|
|
bbaaef |
+ free(vip);
|
|
|
bbaaef |
+ }
|
|
|
bbaaef |
free(action);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
static void
|
|
|
bbaaef |
build_pre_lb(struct ovn_datapath *od, struct hmap *lflows,
|
|
|
bbaaef |
- struct shash *meter_groups)
|
|
|
bbaaef |
+ struct shash *meter_groups, struct hmap *lbs)
|
|
|
bbaaef |
{
|
|
|
bbaaef |
/* Do not send ND packets to conntrack */
|
|
|
bbaaef |
ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_LB, 110,
|
|
|
bbaaef |
@@ -4643,40 +4680,29 @@ build_pre_lb(struct ovn_datapath *od, struct hmap *lflows,
|
|
|
bbaaef |
struct sset all_ips_v6 = SSET_INITIALIZER(&all_ips_v6);
|
|
|
bbaaef |
bool vip_configured = false;
|
|
|
bbaaef |
for (int i = 0; i < od->nbs->n_load_balancer; i++) {
|
|
|
bbaaef |
- struct nbrec_load_balancer *lb = od->nbs->load_balancer[i];
|
|
|
bbaaef |
- struct smap *vips = &lb->vips;
|
|
|
bbaaef |
- struct smap_node *node;
|
|
|
bbaaef |
- int addr_family = AF_INET;
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- SMAP_FOR_EACH (node, vips) {
|
|
|
bbaaef |
- vip_configured = true;
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- /* node->key contains IP:port or just IP. */
|
|
|
bbaaef |
- char *ip_address = NULL;
|
|
|
bbaaef |
- uint16_t port;
|
|
|
bbaaef |
- ip_address_and_port_from_lb_key(node->key, &ip_address, &port,
|
|
|
bbaaef |
- &addr_family);
|
|
|
bbaaef |
- if (!ip_address) {
|
|
|
bbaaef |
- continue;
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
+ struct nbrec_load_balancer *nb_lb = od->nbs->load_balancer[i];
|
|
|
bbaaef |
+ struct ovn_lb *lb =
|
|
|
bbaaef |
+ ovn_lb_find(lbs, &nb_lb->header_.uuid);
|
|
|
bbaaef |
+ ovs_assert(lb);
|
|
|
bbaaef |
|
|
|
bbaaef |
- if (addr_family == AF_INET) {
|
|
|
bbaaef |
- sset_add(&all_ips_v4, ip_address);
|
|
|
bbaaef |
+ for (size_t j = 0; j < lb->n_vips; j++) {
|
|
|
bbaaef |
+ struct lb_vip *lb_vip = &lb->vips[j];
|
|
|
bbaaef |
+ if (lb_vip->addr_family == AF_INET) {
|
|
|
bbaaef |
+ sset_add(&all_ips_v4, lb_vip->vip);
|
|
|
bbaaef |
} else {
|
|
|
bbaaef |
- sset_add(&all_ips_v6, ip_address);
|
|
|
bbaaef |
+ sset_add(&all_ips_v6, lb_vip->vip);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
- build_empty_lb_event_flow(od, lflows, node, ip_address, lb,
|
|
|
bbaaef |
- port, addr_family, S_SWITCH_IN_PRE_LB,
|
|
|
bbaaef |
- meter_groups);
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- free(ip_address);
|
|
|
bbaaef |
+ build_empty_lb_event_flow(od, lflows, lb_vip, nb_lb,
|
|
|
bbaaef |
+ S_SWITCH_IN_PRE_LB, meter_groups);
|
|
|
bbaaef |
|
|
|
bbaaef |
/* Ignore L4 port information in the key because fragmented packets
|
|
|
bbaaef |
* may not have L4 information. The pre-stateful table will send
|
|
|
bbaaef |
* the packet through ct() action to de-fragment. In stateful
|
|
|
bbaaef |
* table, we will eventually look at L4 information. */
|
|
|
bbaaef |
}
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ vip_configured = !!lb->n_vips;
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
/* 'REGBIT_CONNTRACK_DEFRAG' is set to let the pre-stateful table send
|
|
|
bbaaef |
@@ -5224,6 +5250,20 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows,
|
|
|
bbaaef |
lflows, od, S_SWITCH_OUT_ACL, 34000, "udp.src == 53",
|
|
|
bbaaef |
actions);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ /* Add a 34000 priority flow to advance the service monitor reply
|
|
|
bbaaef |
+ * packets to skip applying ingress ACLs. */
|
|
|
bbaaef |
+ char *svc_check_match = xasprintf("eth.dst == %s", svc_monitor_mac);
|
|
|
bbaaef |
+ ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, 34000, svc_check_match,
|
|
|
bbaaef |
+ "next;");
|
|
|
bbaaef |
+ free(svc_check_match);
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ /* Add a 34000 priority flow to advance the service monitor packets
|
|
|
bbaaef |
+ * generated by ovn-controller to skip applying egress ACLs. */
|
|
|
bbaaef |
+ svc_check_match = xasprintf("eth.src == %s", svc_monitor_mac);
|
|
|
bbaaef |
+ ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 34000, svc_check_match,
|
|
|
bbaaef |
+ "next;");
|
|
|
bbaaef |
+ free(svc_check_match);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
static void
|
|
|
bbaaef |
@@ -5349,36 +5389,7 @@ build_stateful(struct ovn_datapath *od, struct hmap *lflows, struct hmap *lbs)
|
|
|
bbaaef |
struct lb_vip *lb_vip = &lb->vips[j];
|
|
|
bbaaef |
/* New connections in Ingress table. */
|
|
|
bbaaef |
struct ds action = DS_EMPTY_INITIALIZER;
|
|
|
bbaaef |
- if (lb_vip->health_check) {
|
|
|
bbaaef |
- ds_put_cstr(&action, "ct_lb(");
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- size_t n_active_backends = 0;
|
|
|
bbaaef |
- for (size_t k = 0; k < lb_vip->n_backends; k++) {
|
|
|
bbaaef |
- struct lb_vip_backend *backend = &lb_vip->backends[k];
|
|
|
bbaaef |
- bool is_up = true;
|
|
|
bbaaef |
- if (backend->health_check && backend->sbrec_monitor &&
|
|
|
bbaaef |
- backend->sbrec_monitor->status &&
|
|
|
bbaaef |
- strcmp(backend->sbrec_monitor->status, "online")) {
|
|
|
bbaaef |
- is_up = false;
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- if (is_up) {
|
|
|
bbaaef |
- n_active_backends++;
|
|
|
bbaaef |
- ds_put_format(&action, "%s:%"PRIu16",",
|
|
|
bbaaef |
- backend->ip, backend->port);
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- if (!n_active_backends) {
|
|
|
bbaaef |
- ds_clear(&action);
|
|
|
bbaaef |
- ds_put_cstr(&action, "drop;");
|
|
|
bbaaef |
- } else {
|
|
|
bbaaef |
- ds_chomp(&action, ',');
|
|
|
bbaaef |
- ds_put_cstr(&action, ");");
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
- } else {
|
|
|
bbaaef |
- ds_put_format(&action, "ct_lb(%s);", lb_vip->backend_ips);
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
+ build_lb_vip_ct_lb_actions(lb_vip, &action);
|
|
|
bbaaef |
|
|
|
bbaaef |
struct ds match = DS_EMPTY_INITIALIZER;
|
|
|
bbaaef |
if (lb_vip->addr_family == AF_INET) {
|
|
|
bbaaef |
@@ -5699,7 +5710,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
build_pre_acls(od, lflows);
|
|
|
bbaaef |
- build_pre_lb(od, lflows, meter_groups);
|
|
|
bbaaef |
+ build_pre_lb(od, lflows, meter_groups, lbs);
|
|
|
bbaaef |
build_pre_stateful(od, lflows);
|
|
|
bbaaef |
build_acls(od, lflows, port_groups);
|
|
|
bbaaef |
build_qos(od, lflows);
|
|
|
bbaaef |
@@ -6963,15 +6974,11 @@ get_force_snat_ip(struct ovn_datapath *od, const char *key_type,
|
|
|
bbaaef |
static void
|
|
|
bbaaef |
add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
|
|
|
bbaaef |
struct ds *match, struct ds *actions, int priority,
|
|
|
bbaaef |
- const char *lb_force_snat_ip, struct smap_node *lb_info,
|
|
|
bbaaef |
- bool is_udp, int addr_family, char *ip_addr,
|
|
|
bbaaef |
- uint16_t l4_port, struct nbrec_load_balancer *lb,
|
|
|
bbaaef |
+ const char *lb_force_snat_ip, struct lb_vip *lb_vip,
|
|
|
bbaaef |
+ bool is_udp, struct nbrec_load_balancer *lb,
|
|
|
bbaaef |
struct shash *meter_groups)
|
|
|
bbaaef |
{
|
|
|
bbaaef |
- char *backend_ips = lb_info->value;
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- build_empty_lb_event_flow(od, lflows, lb_info, ip_addr, lb,
|
|
|
bbaaef |
- l4_port, addr_family, S_ROUTER_IN_DNAT,
|
|
|
bbaaef |
+ build_empty_lb_event_flow(od, lflows, lb_vip, lb, S_ROUTER_IN_DNAT,
|
|
|
bbaaef |
meter_groups);
|
|
|
bbaaef |
|
|
|
bbaaef |
/* A match and actions for new connections. */
|
|
|
bbaaef |
@@ -7000,7 +7007,7 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
|
|
|
bbaaef |
free(new_match);
|
|
|
bbaaef |
free(est_match);
|
|
|
bbaaef |
|
|
|
bbaaef |
- if (!od->l3dgw_port || !od->l3redirect_port || !backend_ips) {
|
|
|
bbaaef |
+ if (!od->l3dgw_port || !od->l3redirect_port || !lb_vip->n_backends) {
|
|
|
bbaaef |
return;
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
@@ -7009,46 +7016,28 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
|
|
|
bbaaef |
* router has a gateway router port associated.
|
|
|
bbaaef |
*/
|
|
|
bbaaef |
struct ds undnat_match = DS_EMPTY_INITIALIZER;
|
|
|
bbaaef |
- if (addr_family == AF_INET) {
|
|
|
bbaaef |
+ if (lb_vip->addr_family == AF_INET) {
|
|
|
bbaaef |
ds_put_cstr(&undnat_match, "ip4 && (");
|
|
|
bbaaef |
} else {
|
|
|
bbaaef |
ds_put_cstr(&undnat_match, "ip6 && (");
|
|
|
bbaaef |
}
|
|
|
bbaaef |
- char *start, *next, *ip_str;
|
|
|
bbaaef |
- start = next = xstrdup(backend_ips);
|
|
|
bbaaef |
- ip_str = strsep(&next, ",");
|
|
|
bbaaef |
- bool backend_ips_found = false;
|
|
|
bbaaef |
- while (ip_str && ip_str[0]) {
|
|
|
bbaaef |
- char *ip_address = NULL;
|
|
|
bbaaef |
- uint16_t port = 0;
|
|
|
bbaaef |
- int addr_family_;
|
|
|
bbaaef |
- ip_address_and_port_from_lb_key(ip_str, &ip_address, &port,
|
|
|
bbaaef |
- &addr_family_);
|
|
|
bbaaef |
- if (!ip_address) {
|
|
|
bbaaef |
- break;
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
|
|
|
bbaaef |
- if (addr_family_ == AF_INET) {
|
|
|
bbaaef |
- ds_put_format(&undnat_match, "(ip4.src == %s", ip_address);
|
|
|
bbaaef |
+ for (size_t i = 0; i < lb_vip->n_backends; i++) {
|
|
|
bbaaef |
+ struct lb_vip_backend *backend = &lb_vip->backends[i];
|
|
|
bbaaef |
+ if (backend->addr_family == AF_INET) {
|
|
|
bbaaef |
+ ds_put_format(&undnat_match, "(ip4.src == %s", backend->ip);
|
|
|
bbaaef |
} else {
|
|
|
bbaaef |
- ds_put_format(&undnat_match, "(ip6.src == %s", ip_address);
|
|
|
bbaaef |
+ ds_put_format(&undnat_match, "(ip6.src == %s", backend->ip);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
- free(ip_address);
|
|
|
bbaaef |
- if (port) {
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ if (backend->port) {
|
|
|
bbaaef |
ds_put_format(&undnat_match, " && %s.src == %d) || ",
|
|
|
bbaaef |
- is_udp ? "udp" : "tcp", port);
|
|
|
bbaaef |
+ is_udp ? "udp" : "tcp", backend->port);
|
|
|
bbaaef |
} else {
|
|
|
bbaaef |
ds_put_cstr(&undnat_match, ") || ");
|
|
|
bbaaef |
}
|
|
|
bbaaef |
- ip_str = strsep(&next, ",");
|
|
|
bbaaef |
- backend_ips_found = true;
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
- free(start);
|
|
|
bbaaef |
- if (!backend_ips_found) {
|
|
|
bbaaef |
- ds_destroy(&undnat_match);
|
|
|
bbaaef |
- return;
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
ds_chomp(&undnat_match, ' ');
|
|
|
bbaaef |
ds_chomp(&undnat_match, '|');
|
|
|
bbaaef |
ds_chomp(&undnat_match, '|');
|
|
|
bbaaef |
@@ -7166,7 +7155,8 @@ lrouter_nat_is_stateless(const struct nbrec_nat *nat)
|
|
|
bbaaef |
|
|
|
bbaaef |
static void
|
|
|
bbaaef |
build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
bbaaef |
- struct hmap *lflows, struct shash *meter_groups)
|
|
|
bbaaef |
+ struct hmap *lflows, struct shash *meter_groups,
|
|
|
bbaaef |
+ struct hmap *lbs)
|
|
|
bbaaef |
{
|
|
|
bbaaef |
/* This flow table structure is documented in ovn-northd(8), so please
|
|
|
bbaaef |
* update ovn-northd.8.xml if you change anything. */
|
|
|
bbaaef |
@@ -8546,24 +8536,18 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
bbaaef |
struct sset all_ips = SSET_INITIALIZER(&all_ips);
|
|
|
bbaaef |
|
|
|
bbaaef |
for (int i = 0; i < od->nbr->n_load_balancer; i++) {
|
|
|
bbaaef |
- struct nbrec_load_balancer *lb = od->nbr->load_balancer[i];
|
|
|
bbaaef |
- struct smap *vips = &lb->vips;
|
|
|
bbaaef |
- struct smap_node *node;
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- SMAP_FOR_EACH (node, vips) {
|
|
|
bbaaef |
- uint16_t port = 0;
|
|
|
bbaaef |
- int addr_family;
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- /* node->key contains IP:port or just IP. */
|
|
|
bbaaef |
- char *ip_address = NULL;
|
|
|
bbaaef |
- ip_address_and_port_from_lb_key(node->key, &ip_address, &port,
|
|
|
bbaaef |
- &addr_family);
|
|
|
bbaaef |
- if (!ip_address) {
|
|
|
bbaaef |
- continue;
|
|
|
bbaaef |
- }
|
|
|
bbaaef |
+ struct nbrec_load_balancer *nb_lb = od->nbr->load_balancer[i];
|
|
|
bbaaef |
+ struct ovn_lb *lb =
|
|
|
bbaaef |
+ ovn_lb_find(lbs, &nb_lb->header_.uuid);
|
|
|
bbaaef |
+ ovs_assert(lb);
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ for (size_t j = 0; j < lb->n_vips; j++) {
|
|
|
bbaaef |
+ struct lb_vip *lb_vip = &lb->vips[j];
|
|
|
bbaaef |
+ ds_clear(&actions);
|
|
|
bbaaef |
+ build_lb_vip_ct_lb_actions(lb_vip, &actions);
|
|
|
bbaaef |
|
|
|
bbaaef |
- if (!sset_contains(&all_ips, ip_address)) {
|
|
|
bbaaef |
- sset_add(&all_ips, ip_address);
|
|
|
bbaaef |
+ if (!sset_contains(&all_ips, lb_vip->vip)) {
|
|
|
bbaaef |
+ sset_add(&all_ips, lb_vip->vip);
|
|
|
bbaaef |
/* If there are any load balancing rules, we should send
|
|
|
bbaaef |
* the packet to conntrack for defragmentation and
|
|
|
bbaaef |
* tracking. This helps with two things.
|
|
|
bbaaef |
@@ -8573,12 +8557,12 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
bbaaef |
* 2. If there are L4 ports in load balancing rules, we
|
|
|
bbaaef |
* need the defragmentation to match on L4 ports. */
|
|
|
bbaaef |
ds_clear(&match);
|
|
|
bbaaef |
- if (addr_family == AF_INET) {
|
|
|
bbaaef |
+ if (lb_vip->addr_family == AF_INET) {
|
|
|
bbaaef |
ds_put_format(&match, "ip && ip4.dst == %s",
|
|
|
bbaaef |
- ip_address);
|
|
|
bbaaef |
- } else if (addr_family == AF_INET6) {
|
|
|
bbaaef |
+ lb_vip->vip);
|
|
|
bbaaef |
+ } else if (lb_vip->addr_family == AF_INET6) {
|
|
|
bbaaef |
ds_put_format(&match, "ip && ip6.dst == %s",
|
|
|
bbaaef |
- ip_address);
|
|
|
bbaaef |
+ lb_vip->vip);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG,
|
|
|
bbaaef |
100, ds_cstr(&match), "ct_next;");
|
|
|
bbaaef |
@@ -8589,28 +8573,25 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
bbaaef |
* via add_router_lb_flow(). One flow is for specific matching
|
|
|
bbaaef |
* on ct.new with an action of "ct_lb($targets);". The other
|
|
|
bbaaef |
* flow is for ct.est with an action of "ct_dnat;". */
|
|
|
bbaaef |
- ds_clear(&actions);
|
|
|
bbaaef |
- ds_put_format(&actions, "ct_lb(%s);", node->value);
|
|
|
bbaaef |
-
|
|
|
bbaaef |
ds_clear(&match);
|
|
|
bbaaef |
- if (addr_family == AF_INET) {
|
|
|
bbaaef |
+ if (lb_vip->addr_family == AF_INET) {
|
|
|
bbaaef |
ds_put_format(&match, "ip && ip4.dst == %s",
|
|
|
bbaaef |
- ip_address);
|
|
|
bbaaef |
- } else if (addr_family == AF_INET6) {
|
|
|
bbaaef |
+ lb_vip->vip);
|
|
|
bbaaef |
+ } else if (lb_vip->addr_family == AF_INET6) {
|
|
|
bbaaef |
ds_put_format(&match, "ip && ip6.dst == %s",
|
|
|
bbaaef |
- ip_address);
|
|
|
bbaaef |
+ lb_vip->vip);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
|
|
|
bbaaef |
int prio = 110;
|
|
|
bbaaef |
- bool is_udp = lb->protocol && !strcmp(lb->protocol, "udp") ?
|
|
|
bbaaef |
- true : false;
|
|
|
bbaaef |
- if (port) {
|
|
|
bbaaef |
+ bool is_udp = nullable_string_is_equal(nb_lb->protocol, "udp");
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+ if (lb_vip->vip_port) {
|
|
|
bbaaef |
if (is_udp) {
|
|
|
bbaaef |
ds_put_format(&match, " && udp && udp.dst == %d",
|
|
|
bbaaef |
- port);
|
|
|
bbaaef |
+ lb_vip->vip_port);
|
|
|
bbaaef |
} else {
|
|
|
bbaaef |
ds_put_format(&match, " && tcp && tcp.dst == %d",
|
|
|
bbaaef |
- port);
|
|
|
bbaaef |
+ lb_vip->vip_port);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
prio = 120;
|
|
|
bbaaef |
}
|
|
|
bbaaef |
@@ -8620,11 +8601,8 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
bbaaef |
od->l3redirect_port->json_key);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
add_router_lb_flow(lflows, od, &match, &actions, prio,
|
|
|
bbaaef |
- lb_force_snat_ip, node, is_udp,
|
|
|
bbaaef |
- addr_family, ip_address, port, lb,
|
|
|
bbaaef |
- meter_groups);
|
|
|
bbaaef |
-
|
|
|
bbaaef |
- free(ip_address);
|
|
|
bbaaef |
+ lb_force_snat_ip, lb_vip, is_udp,
|
|
|
bbaaef |
+ nb_lb, meter_groups);
|
|
|
bbaaef |
}
|
|
|
bbaaef |
}
|
|
|
bbaaef |
sset_destroy(&all_ips);
|
|
|
bbaaef |
@@ -9431,7 +9409,7 @@ build_lflows(struct northd_context *ctx, struct hmap *datapaths,
|
|
|
bbaaef |
|
|
|
bbaaef |
build_lswitch_flows(datapaths, ports, port_groups, &lflows, mcgroups,
|
|
|
bbaaef |
igmp_groups, meter_groups, lbs);
|
|
|
bbaaef |
- build_lrouter_flows(datapaths, ports, &lflows, meter_groups);
|
|
|
bbaaef |
+ build_lrouter_flows(datapaths, ports, &lflows, meter_groups, lbs);
|
|
|
bbaaef |
|
|
|
bbaaef |
/* Push changes to the Logical_Flow table to database. */
|
|
|
bbaaef |
const struct sbrec_logical_flow *sbflow, *next_sbflow;
|
|
|
bbaaef |
diff --git a/tests/ovn.at b/tests/ovn.at
|
|
|
bbaaef |
index e2565f274..3a5ecf211 100644
|
|
|
bbaaef |
--- a/tests/ovn.at
|
|
|
bbaaef |
+++ b/tests/ovn.at
|
|
|
bbaaef |
@@ -17007,6 +17007,22 @@ ovn-nbctl --wait=sb ls-lb-add sw0 lb1
|
|
|
bbaaef |
ovn-nbctl --wait=sb ls-lb-add sw1 lb1
|
|
|
bbaaef |
ovn-nbctl --wait=sb lr-lb-add lr0 lb1
|
|
|
bbaaef |
|
|
|
bbaaef |
+ovn-nbctl ls-add public
|
|
|
bbaaef |
+ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
|
|
|
bbaaef |
+ovn-nbctl lsp-add public public-lr0
|
|
|
bbaaef |
+ovn-nbctl lsp-set-type public-lr0 router
|
|
|
bbaaef |
+ovn-nbctl lsp-set-addresses public-lr0 router
|
|
|
bbaaef |
+ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+# localnet port
|
|
|
bbaaef |
+ovn-nbctl lsp-add public ln-public
|
|
|
bbaaef |
+ovn-nbctl lsp-set-type ln-public localnet
|
|
|
bbaaef |
+ovn-nbctl lsp-set-addresses ln-public unknown
|
|
|
bbaaef |
+ovn-nbctl lsp-set-options ln-public network_name=public
|
|
|
bbaaef |
+
|
|
|
bbaaef |
+# schedule the gw router port to a chassis. Change the name of the chassis
|
|
|
bbaaef |
+ovn-nbctl --wait=hv lrp-set-gateway-chassis lr0-public hv1 20
|
|
|
bbaaef |
+
|
|
|
bbaaef |
OVN_POPULATE_ARP
|
|
|
bbaaef |
ovn-nbctl --wait=hv sync
|
|
|
bbaaef |
|
|
|
bbaaef |
@@ -17018,6 +17034,11 @@ AT_CHECK([cat lflows.txt], [0], [dnl
|
|
|
bbaaef |
table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);)
|
|
|
bbaaef |
])
|
|
|
bbaaef |
|
|
|
bbaaef |
+ovn-sbctl dump-flows lr0 | grep ct_lb | grep priority=120 > lflows.txt
|
|
|
bbaaef |
+AT_CHECK([cat lflows.txt], [0], [dnl
|
|
|
bbaaef |
+ table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);)
|
|
|
bbaaef |
+])
|
|
|
bbaaef |
+
|
|
|
bbaaef |
# get the svc monitor mac.
|
|
|
bbaaef |
svc_mon_src_mac=`ovn-nbctl get NB_Global . options:svc_monitor_mac | \
|
|
|
bbaaef |
sed s/":"//g | sed s/\"//g`
|
|
|
bbaaef |
@@ -17051,5 +17072,11 @@ AT_CHECK([cat lflows.txt], [0], [dnl
|
|
|
bbaaef |
table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(drop;)
|
|
|
bbaaef |
])
|
|
|
bbaaef |
|
|
|
bbaaef |
+ovn-sbctl dump-flows lr0 | grep lr_in_dnat | grep priority=120 > lflows.txt
|
|
|
bbaaef |
+AT_CHECK([cat lflows.txt], [0], [dnl
|
|
|
bbaaef |
+ table=6 (lr_in_dnat ), priority=120 , match=(ct.est && ip && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_dnat;)
|
|
|
bbaaef |
+ table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;)
|
|
|
bbaaef |
+])
|
|
|
bbaaef |
+
|
|
|
bbaaef |
OVN_CLEANUP([hv1], [hv2])
|
|
|
bbaaef |
AT_CLEANUP
|
|
|
bbaaef |
--
|
|
|
bbaaef |
2.24.1
|
|
|
bbaaef |
|