|
|
773311 |
From 74e1bf4dd0f6c62602ab708eabb5534a274a4d75 Mon Sep 17 00:00:00 2001
|
|
|
773311 |
From: Dumitru Ceara <dceara@redhat.com>
|
|
|
773311 |
Date: Tue, 28 Apr 2020 12:39:26 +0200
|
|
|
773311 |
Subject: [PATCH] ovn-northd: Optimize flows for LB Hairpin traffic.
|
|
|
773311 |
|
|
|
773311 |
In order to detect that traffic was hairpinned due to logical switch load
|
|
|
773311 |
balancers we need to match on source and destination IPs of packets (and
|
|
|
773311 |
protocol ports potentially) in table ls_in_pre_hairpin.
|
|
|
773311 |
|
|
|
773311 |
For this, until now, we created 2 logical flows for each backend of a load
|
|
|
773311 |
balancer VIP. However, in scenarios where large load balancers (i.e.,
|
|
|
773311 |
with large numbers of backends) are applied to multiple logical
|
|
|
773311 |
switches, this might generate logical flow count explosion.
|
|
|
773311 |
|
|
|
773311 |
One optimization is to generate a single logical flow per VIP that
|
|
|
773311 |
combines all conditions generated for each backend. This reduces load on
|
|
|
773311 |
the SB DB because of lower number of logical flows and also reduces
|
|
|
773311 |
overall DB size because of less overhead due to other fields on the
|
|
|
773311 |
logical_flow records.
|
|
|
773311 |
|
|
|
773311 |
Comparison of various performance aspects when running OVN with the NB
|
|
|
773311 |
database attached to the bug report on a deployment with all VIFs bound
|
|
|
773311 |
to a single node (62 load balancer VIPs with 513 load balancer
|
|
|
773311 |
backends, applied on 106 logical switches):
|
|
|
773311 |
|
|
|
773311 |
Without this patch:
|
|
|
773311 |
- SB database size: 60MB
|
|
|
773311 |
- # of pre-hairpin logical flows: 109074
|
|
|
773311 |
- # of logical flows: 159414
|
|
|
773311 |
- ovn-controller max loop iteration time when processing SB DB: 8803ms
|
|
|
773311 |
- ovn-northd max loop iteration time: 3988ms
|
|
|
773311 |
|
|
|
773311 |
With this patch:
|
|
|
773311 |
- SB database size: 29MB (~50% decrease)
|
|
|
773311 |
- # of pre-hairpin logical flows: 13250 (~88% decrease)
|
|
|
773311 |
- # of logical flows: 63590 (~60% decrease)
|
|
|
773311 |
- ovn-controller max loop iteration time when processing SB DB: 5585ms
|
|
|
773311 |
- ovn-northd max loop iteration time: 1594ms
|
|
|
773311 |
|
|
|
773311 |
Reported-by: Aniket Bhat <anbhat@redhat.com>
|
|
|
773311 |
Reported-at: https://bugzilla.redhat.com/1827403
|
|
|
773311 |
Fixes: 1be8ac65bc60 ("ovn-northd: Support hairpinning for logical switch load balancing.")
|
|
|
773311 |
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
|
|
|
773311 |
Signed-off-by: Numan Siddique <numans@ovn.org>
|
|
|
773311 |
(cherry picked from upstream commit 97e82ae5f135a088c9e95b49122d8217718d23f4)
|
|
|
773311 |
|
|
|
773311 |
Change-Id: Id713209f8bd159e8ad924e91681bab784606faff
|
|
|
773311 |
---
|
|
|
773311 |
northd/ovn-northd.8.xml | 4 +--
|
|
|
773311 |
northd/ovn-northd.c | 79 ++++++++++++++++++++++++++++++++-----------------
|
|
|
773311 |
2 files changed, 54 insertions(+), 29 deletions(-)
|
|
|
773311 |
|
|
|
773311 |
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
|
|
|
773311 |
index d39e259..1f81742 100644
|
|
|
773311 |
--- a/northd/ovn-northd.8.xml
|
|
|
773311 |
+++ b/northd/ovn-northd.8.xml
|
|
|
773311 |
@@ -559,14 +559,14 @@
|
|
|
773311 |
Ingress Table 11: Pre-Hairpin
|
|
|
773311 |
|
|
|
773311 |
|
|
|
773311 |
- For all configured load balancer backends a priority-2 flow that
|
|
|
773311 |
+ For all configured load balancer VIPs a priority-2 flow that
|
|
|
773311 |
matches on traffic that needs to be hairpinned, i.e., after load
|
|
|
773311 |
balancing the destination IP matches the source IP, which sets
|
|
|
773311 |
reg0[6] = 1 and executes ct_snat(VIP)
|
|
|
773311 |
to force replies to these packets to come back through OVN.
|
|
|
773311 |
|
|
|
773311 |
|
|
|
773311 |
- For all configured load balancer backends a priority-1 flow that
|
|
|
773311 |
+ For all configured load balancer VIPs a priority-1 flow that
|
|
|
773311 |
matches on replies to hairpinned traffic, i.e., destination IP is VIP,
|
|
|
773311 |
source IP is the backend IP and source L4 port is backend port, which
|
|
|
773311 |
sets reg0[6] = 1 and executes ct_snat; .
|
|
|
773311 |
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
|
|
|
773311 |
index 0082e2e..5ada3ae 100644
|
|
|
773311 |
--- a/northd/ovn-northd.c
|
|
|
773311 |
+++ b/northd/ovn-northd.c
|
|
|
773311 |
@@ -5542,52 +5542,77 @@ build_lb_hairpin_rules(struct ovn_datapath *od, struct hmap *lflows,
|
|
|
773311 |
struct ovn_lb *lb, struct lb_vip *lb_vip,
|
|
|
773311 |
const char *ip_match, const char *proto)
|
|
|
773311 |
{
|
|
|
773311 |
+ if (lb_vip->n_backends == 0) {
|
|
|
773311 |
+ return;
|
|
|
773311 |
+ }
|
|
|
773311 |
+
|
|
|
773311 |
+ struct ds action = DS_EMPTY_INITIALIZER;
|
|
|
773311 |
+ struct ds match_initiator = DS_EMPTY_INITIALIZER;
|
|
|
773311 |
+ struct ds match_reply = DS_EMPTY_INITIALIZER;
|
|
|
773311 |
+ struct ds proto_match = DS_EMPTY_INITIALIZER;
|
|
|
773311 |
+
|
|
|
773311 |
/* Ingress Pre-Hairpin table.
|
|
|
773311 |
- * - Priority 2: SNAT load balanced traffic that needs to be hairpinned.
|
|
|
773311 |
+ * - Priority 2: SNAT load balanced traffic that needs to be hairpinned:
|
|
|
773311 |
+ * - Both SRC and DST IP match backend->ip and destination port
|
|
|
773311 |
+ * matches backend->port.
|
|
|
773311 |
* - Priority 1: unSNAT replies to hairpinned load balanced traffic.
|
|
|
773311 |
+ * - SRC IP matches backend->ip, DST IP matches LB VIP and source port
|
|
|
773311 |
+ * matches backend->port.
|
|
|
773311 |
*/
|
|
|
773311 |
+ ds_put_char(&match_reply, '(');
|
|
|
773311 |
for (size_t i = 0; i < lb_vip->n_backends; i++) {
|
|
|
773311 |
struct lb_vip_backend *backend = &lb_vip->backends[i];
|
|
|
773311 |
- struct ds action = DS_EMPTY_INITIALIZER;
|
|
|
773311 |
- struct ds match = DS_EMPTY_INITIALIZER;
|
|
|
773311 |
- struct ds proto_match = DS_EMPTY_INITIALIZER;
|
|
|
773311 |
|
|
|
773311 |
/* Packets that after load balancing have equal source and
|
|
|
773311 |
- * destination IPs should be hairpinned. SNAT them so that the reply
|
|
|
773311 |
- * traffic is directed also through OVN.
|
|
|
773311 |
+ * destination IPs should be hairpinned.
|
|
|
773311 |
*/
|
|
|
773311 |
if (lb_vip->vip_port) {
|
|
|
773311 |
- ds_put_format(&proto_match, " && %s && %s.dst == %"PRIu16,
|
|
|
773311 |
- proto, proto, backend->port);
|
|
|
773311 |
+ ds_put_format(&proto_match, " && %s.dst == %"PRIu16,
|
|
|
773311 |
+ proto, backend->port);
|
|
|
773311 |
}
|
|
|
773311 |
- ds_put_format(&match, "%s.src == %s && %s.dst == %s%s",
|
|
|
773311 |
+ ds_put_format(&match_initiator, "(%s.src == %s && %s.dst == %s%s)",
|
|
|
773311 |
ip_match, backend->ip, ip_match, backend->ip,
|
|
|
773311 |
ds_cstr(&proto_match));
|
|
|
773311 |
- ds_put_format(&action, REGBIT_HAIRPIN " = 1; ct_snat(%s);",
|
|
|
773311 |
- lb_vip->vip);
|
|
|
773311 |
- ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 2,
|
|
|
773311 |
- ds_cstr(&match), ds_cstr(&action),
|
|
|
773311 |
- &lb->nlb->header_);
|
|
|
773311 |
|
|
|
773311 |
- /* If the packets are replies for hairpinned traffic, UNSNAT them. */
|
|
|
773311 |
+ /* Replies to hairpinned traffic are originated by backend->ip:port. */
|
|
|
773311 |
ds_clear(&proto_match);
|
|
|
773311 |
- ds_clear(&match);
|
|
|
773311 |
if (lb_vip->vip_port) {
|
|
|
773311 |
- ds_put_format(&proto_match, " && %s && %s.src == %"PRIu16,
|
|
|
773311 |
- proto, proto, backend->port);
|
|
|
773311 |
+ ds_put_format(&proto_match, " && %s.src == %"PRIu16, proto,
|
|
|
773311 |
+ backend->port);
|
|
|
773311 |
}
|
|
|
773311 |
- ds_put_format(&match, "%s.src == %s && %s.dst == %s%s",
|
|
|
773311 |
- ip_match, backend->ip, ip_match, lb_vip->vip,
|
|
|
773311 |
+ ds_put_format(&match_reply, "(%s.src == %s%s)", ip_match, backend->ip,
|
|
|
773311 |
ds_cstr(&proto_match));
|
|
|
773311 |
- ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 1,
|
|
|
773311 |
- ds_cstr(&match),
|
|
|
773311 |
- REGBIT_HAIRPIN " = 1; ct_snat;",
|
|
|
773311 |
- &lb->nlb->header_);
|
|
|
773311 |
+ ds_clear(&proto_match);
|
|
|
773311 |
|
|
|
773311 |
- ds_destroy(&action);
|
|
|
773311 |
- ds_destroy(&match);
|
|
|
773311 |
- ds_destroy(&proto_match);
|
|
|
773311 |
+ if (i < lb_vip->n_backends - 1) {
|
|
|
773311 |
+ ds_put_cstr(&match_initiator, " || ");
|
|
|
773311 |
+ ds_put_cstr(&match_reply, " || ");
|
|
|
773311 |
+ }
|
|
|
773311 |
}
|
|
|
773311 |
+ ds_put_char(&match_reply, ')');
|
|
|
773311 |
+
|
|
|
773311 |
+ /* SNAT hairpinned initiator traffic so that the reply traffic is
|
|
|
773311 |
+ * also directed through OVN.
|
|
|
773311 |
+ */
|
|
|
773311 |
+ ds_put_format(&action, REGBIT_HAIRPIN " = 1; ct_snat(%s);",
|
|
|
773311 |
+ lb_vip->vip);
|
|
|
773311 |
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 2,
|
|
|
773311 |
+ ds_cstr(&match_initiator), ds_cstr(&action),
|
|
|
773311 |
+ &lb->nlb->header_);
|
|
|
773311 |
+
|
|
|
773311 |
+ /* Replies to hairpinned traffic are destined to the LB VIP. */
|
|
|
773311 |
+ ds_put_format(&match_reply, " && %s.dst == %s", ip_match, lb_vip->vip);
|
|
|
773311 |
+
|
|
|
773311 |
+ /* UNSNAT replies for hairpinned traffic. */
|
|
|
773311 |
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 1,
|
|
|
773311 |
+ ds_cstr(&match_reply),
|
|
|
773311 |
+ REGBIT_HAIRPIN " = 1; ct_snat;",
|
|
|
773311 |
+ &lb->nlb->header_);
|
|
|
773311 |
+
|
|
|
773311 |
+ ds_destroy(&action);
|
|
|
773311 |
+ ds_destroy(&match_initiator);
|
|
|
773311 |
+ ds_destroy(&match_reply);
|
|
|
773311 |
+ ds_destroy(&proto_match);
|
|
|
773311 |
}
|
|
|
773311 |
|
|
|
773311 |
static void
|
|
|
773311 |
--
|
|
|
773311 |
1.8.3.1
|
|
|
773311 |
|