[ovs-dev] [PATCH v3 ovn 3/3] northd: refactor unreachable IPs lb flows
Lorenzo Bianconi
lorenzo.bianconi at redhat.com
Thu Aug 26 16:50:46 UTC 2021
Refactor unreachable IPs for vip load-balancers inverting the logic used
during the lb flow creation in order to visit lb first and then related
datapath/ovn_ports. Rely on ovn_lflow_add_at_with_hash and
ovn_dp_group_add_with_reference in build_lflows_for_unreachable_vips.
Introduce ovs_list in ovn_datapath to link ovn ports on a given
datapath.
Using this approach we can reduce ovn-northd loop time of ~3s running an
ovnnb_db from production environment:
ovn-master:
-----------
Statistics for 'ovnnb_db_run'
Total samples: 37
Maximum: 12656 msec
Minimum: 12276 msec
95th percentile: 12557.000000 msec
Short term average: 12475.213654 msec
Long term average: 12336.498446 msec
build_lflows_for_unreachable_vips:
----------------------------------
Statistics for 'ovnnb_db_run'
Total samples: 37
Maximum: 9505 msec
Minimum: 9212 msec
95th percentile: 9493.000000 msec
Short term average: 9375.959755 msec
Long term average: 9311.952156 msec
ovn-nbctl lr-list | wc -l
121
ovn-nbctl ls-list | wc -l
241
ovn-nbctl lb-list | wc -l
47077
ovn-sbctl dump-flows |wc -l
9852935
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
---
northd/ovn-northd.c | 110 ++++++++++++++++++++++++++++++++++----------
1 file changed, 86 insertions(+), 24 deletions(-)
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 61fb5b159..cdc351c26 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -704,6 +704,8 @@ struct ovn_datapath {
/* Port groups related to the datapath, used only when nbs is NOT NULL. */
struct hmap nb_pgs;
+
+ struct ovs_list port_list;
};
/* Contains a NAT entry with the external addresses pre-parsed. */
@@ -944,6 +946,7 @@ ovn_datapath_create(struct hmap *datapaths, const struct uuid *key,
od->port_key_hint = 0;
hmap_insert(datapaths, &od->key_node, uuid_hash(&od->key));
od->lr_group = NULL;
+ ovs_list_init(&od->port_list);
return od;
}
@@ -1545,6 +1548,8 @@ struct ovn_port {
struct ovn_datapath *od;
struct ovs_list list; /* In list of similar records. */
+
+ struct ovs_list dp_node;
};
static bool
@@ -2470,6 +2475,7 @@ join_logical_ports(struct northd_context *ctx,
}
op->od = od;
+ ovs_list_push_back(&od->port_list, &op->dp_node);
tag_alloc_add_existing_tags(tag_alloc_table, nbsp);
}
} else {
@@ -2514,6 +2520,7 @@ join_logical_ports(struct northd_context *ctx,
op->lrp_networks = lrp_networks;
op->od = od;
+ ovs_list_push_back(&od->port_list, &op->dp_node);
if (op->nbrp->ha_chassis_group ||
op->nbrp->n_gateway_chassis) {
@@ -6924,16 +6931,11 @@ build_lswitch_rport_arp_req_flows(struct ovn_port *op,
/* Check if the ovn port has a network configured on which we could
* expect ARP requests for the LB VIP.
*/
- if (ip_parse(ip_addr, &ipv4_addr)) {
- if (lrouter_port_ipv4_reachable(op, ipv4_addr)) {
- build_lswitch_rport_arp_req_flow_for_reachable_ip(
- ip_addr, AF_INET, sw_op, sw_od, 80, lflows,
- stage_hint);
- } else {
- build_lswitch_rport_arp_req_flow_for_unreachable_ip(
- ip_addr, AF_INET, sw_od, 90, lflows,
- stage_hint);
- }
+ if (ip_parse(ip_addr, &ipv4_addr) &&
+ lrouter_port_ipv4_reachable(op, ipv4_addr)) {
+ build_lswitch_rport_arp_req_flow_for_reachable_ip(
+ ip_addr, AF_INET, sw_op, sw_od, 80, lflows,
+ stage_hint);
}
}
SSET_FOR_EACH (ip_addr, &op->od->lb_ips_v6) {
@@ -6942,16 +6944,11 @@ build_lswitch_rport_arp_req_flows(struct ovn_port *op,
/* Check if the ovn port has a network configured on which we could
* expect NS requests for the LB VIP.
*/
- if (ipv6_parse(ip_addr, &ipv6_addr)) {
- if (lrouter_port_ipv6_reachable(op, &ipv6_addr)) {
- build_lswitch_rport_arp_req_flow_for_reachable_ip(
- ip_addr, AF_INET6, sw_op, sw_od, 80, lflows,
- stage_hint);
- } else {
- build_lswitch_rport_arp_req_flow_for_unreachable_ip(
- ip_addr, AF_INET6, sw_od, 90, lflows,
- stage_hint);
- }
+ if (ipv6_parse(ip_addr, &ipv6_addr) &&
+ lrouter_port_ipv6_reachable(op, &ipv6_addr)) {
+ build_lswitch_rport_arp_req_flow_for_reachable_ip(
+ ip_addr, AF_INET6, sw_op, sw_od, 80, lflows,
+ stage_hint);
}
}
@@ -9496,10 +9493,73 @@ build_lrouter_defrag_flows_for_lb(struct ovn_northd_lb *lb,
ds_destroy(&defrag_actions);
}
+static void
+build_lflows_for_unreachable_vips(struct ovn_northd_lb *lb,
+ struct ovn_lb_vip *lb_vip,
+ struct hmap *lflows,
+ struct ds *match)
+{
+ static const char *action = "outport = \"_MC_flood\"; output;";
+ bool ipv4 = IN6_IS_ADDR_V4MAPPED(&lb_vip->vip);
+ ovs_be32 ipv4_addr;
+
+ ds_clear(match);
+ if (ipv4) {
+ if (!ip_parse(lb_vip->vip_str, &ipv4_addr)) {
+ return;
+ }
+ ds_put_format(match, "%s && arp.op == 1 && arp.tpa == %s",
+ FLAGBIT_NOT_VXLAN, lb_vip->vip_str);
+ } else {
+ ds_put_format(match, "%s && nd_ns && nd.target == %s",
+ FLAGBIT_NOT_VXLAN, lb_vip->vip_str);
+ }
+
+ struct ovn_lflow *lflow_ref = NULL;
+ uint32_t hash = ovn_logical_flow_hash(
+ ovn_stage_get_table(S_SWITCH_IN_L2_LKUP),
+ ovn_stage_get_pipeline_name(S_SWITCH_IN_L2_LKUP), 90,
+ ds_cstr(match), action);
+
+ for (size_t i = 0; i < lb->n_nb_lr; i++) {
+ struct ovn_datapath *od = lb->nb_lr[i];
+
+ if (!od->is_gw_router && !od->n_l3dgw_ports) {
+ continue;
+ }
+
+ struct ovn_port *op;
+ LIST_FOR_EACH (op, dp_node, &od->port_list) {
+ if (!od->is_gw_router && !is_l3dgw_port(op)) {
+ continue;
+ }
+
+ struct ovn_port *peer = op->peer;
+ if (!peer || !peer->nbsp || lsp_is_external(peer->nbsp)) {
+ continue;
+ }
+
+ if ((ipv4 && lrouter_port_ipv4_reachable(op, ipv4_addr)) ||
+ (!ipv4 && lrouter_port_ipv6_reachable(op, &lb_vip->vip))) {
+ continue;
+ }
+
+ if (ovn_dp_group_add_with_reference(lflow_ref, peer->od, hash)) {
+ continue;
+ }
+ lflow_ref = ovn_lflow_add_at_with_hash(lflows, peer->od,
+ S_SWITCH_IN_L2_LKUP, 90,
+ ds_cstr(match), action,
+ NULL, NULL, &peer->nbsp->header_,
+ OVS_SOURCE_LOCATOR, hash);
+ }
+ }
+}
+
static void
build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows,
- struct shash *meter_groups,
- struct ds *match, struct ds *action)
+ struct shash *meter_groups, struct ds *match,
+ struct ds *action)
{
if (!lb->n_nb_lr) {
return;
@@ -9508,6 +9568,8 @@ build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows,
for (size_t i = 0; i < lb->n_vips; i++) {
struct ovn_lb_vip *lb_vip = &lb->vips[i];
+ build_lflows_for_unreachable_vips(lb, lb_vip, lflows, match);
+
build_lrouter_nat_flows_for_lb(lb_vip, lb, &lb->vips_nb[i],
lflows, match, action,
meter_groups);
@@ -12833,8 +12895,8 @@ build_lflows_thread(void *arg)
build_lrouter_defrag_flows_for_lb(lb, lsi->lflows,
&lsi->match);
build_lrouter_flows_for_lb(lb, lsi->lflows,
- lsi->meter_groups,
- &lsi->match, &lsi->actions);
+ lsi->meter_groups, &lsi->match,
+ &lsi->actions);
build_lswitch_flows_for_lb(lb, lsi->lflows,
lsi->meter_groups,
&lsi->match, &lsi->actions);
--
2.31.1
More information about the dev
mailing list