[ovs-dev] [PATCH ovn v2 03/10] ovn-northd-ddlog: Derive load balancer IP addresses in new LoadBalancer.
Ben Pfaff
blp at ovn.org
Tue Sep 7 22:45:09 UTC 2021
This makes the get_router_load_balancer_ips() function much faster.
This function is a hot path for the use of load balancers, so it
improves performance overall when they are in use.
Signed-off-by: Ben Pfaff <blp at ovn.org>
---
northd/lrouter.dl | 68 +++++++++++++++++++++++++++++++++------
northd/ovn_northd.dl | 76 +++++++++++++++++++-------------------------
2 files changed, 91 insertions(+), 53 deletions(-)
diff --git a/northd/lrouter.dl b/northd/lrouter.dl
index b6e752f7c..17d803292 100644
--- a/northd/lrouter.dl
+++ b/northd/lrouter.dl
@@ -402,14 +402,13 @@ LogicalRouterSnatIPs(lr._uuid, map_empty()) :-
lr in nb::Logical_Router(),
not LogicalRouterSnatIP(.lr = lr._uuid).
-relation LogicalRouterLB(lr: uuid, nat: Intern<nb::Load_Balancer>)
-
+relation LogicalRouterLB(lr: uuid, nat: Intern<LoadBalancer>)
LogicalRouterLB(lr, lb) :-
nb::Logical_Router(._uuid = lr, .load_balancer = lbs),
var lb_uuid = FlatMap(lbs),
- lb in &nb::Load_Balancer(._uuid = lb_uuid).
+ lb in &LoadBalancer(.lb = &nb::Load_Balancer{._uuid = lb_uuid}).
-relation LogicalRouterLBs(lr: uuid, nat: Vec<Intern<nb::Load_Balancer>>)
+relation LogicalRouterLBs(lr: uuid, nat: Vec<Intern<LoadBalancer>>)
LogicalRouterLBs(lr, lbs) :-
LogicalRouterLB(lr, lb),
@@ -448,6 +447,31 @@ LogicalRouterCopp0(lr, meters) :-
function chassis_redirect_name(port_name: istring): string = "cr-${port_name}"
+typedef LoadBalancer = LoadBalancer {
+ lb: Intern<nb::Load_Balancer>,
+ ipv4s: Set<istring>,
+ ipv6s: Set<istring>,
+ routable: bool
+}
+
+relation LoadBalancer[Intern<LoadBalancer>]
+LoadBalancer[LoadBalancer{lb, ipv4s, ipv6s, routable}.intern()] :-
+ nb::Load_Balancer[lb],
+ var routable = lb.options.get_bool_def(i"add_route", false),
+ (var ipv4s, var ipv6s) = {
+ var ipv4s = set_empty();
+ var ipv6s = set_empty();
+ for ((vip, _) in lb.vips) {
+ /* node->key contains IP:port or just IP. */
+ match (ip_address_and_port_from_lb_key(vip.ival())) {
+ None -> (),
+ Some{(IPv4{ipv4}, _)} -> ipv4s.insert(i"${ipv4}"),
+ Some{(IPv6{ipv6}, _)} -> ipv6s.insert(i"${ipv6}"),
+ }
+ };
+ (ipv4s, ipv6s)
+ }.
+
typedef Router = Router {
/* Fields copied from nb::Logical_Router. */
_uuid: uuid,
@@ -464,7 +488,11 @@ typedef Router = Router {
is_gateway: bool,
nats: Vec<NAT>,
snat_ips: Map<v46_ip, Set<NAT>>,
- lbs: Vec<Intern<nb::Load_Balancer>>,
+ lbs: Vec<Intern<LoadBalancer>>,
+ lb_ipv4s_routable: Set<istring>,
+ lb_ipv4s_unroutable: Set<istring>,
+ lb_ipv6s_routable: Set<istring>,
+ lb_ipv6s_unroutable: Set<istring>,
mcast_cfg: Intern<McastRouterCfg>,
learn_from_arp_request: bool,
force_lb_snat: bool,
@@ -488,6 +516,10 @@ Router[Router{
.nats = nats,
.snat_ips = snat_ips,
.lbs = lbs,
+ .lb_ipv4s_routable = lb_ipv4s_routable,
+ .lb_ipv4s_unroutable = lb_ipv4s_unroutable,
+ .lb_ipv6s_routable = lb_ipv6s_routable,
+ .lb_ipv6s_unroutable = lb_ipv6s_unroutable,
.mcast_cfg = mcast_cfg,
.learn_from_arp_request = learn_from_arp_request,
.force_lb_snat = force_lb_snat,
@@ -501,10 +533,28 @@ Router[Router{
LogicalRouterCopp(lr._uuid, copp),
mcast_cfg in &McastRouterCfg(.datapath = lr._uuid),
var learn_from_arp_request = lr.options.get_bool_def(i"always_learn_from_arp_request", true),
- var force_lb_snat = lb_force_snat_router_ip(lr.options).
+ var force_lb_snat = lb_force_snat_router_ip(lr.options),
+ (var lb_ipv4s_routable, var lb_ipv4s_unroutable,
+ var lb_ipv6s_routable, var lb_ipv6s_unroutable) = {
+ var lb_ipv4s_routable = set_empty();
+ var lb_ipv4s_unroutable = set_empty();
+ var lb_ipv6s_routable = set_empty();
+ var lb_ipv6s_unroutable = set_empty();
+ for (lb in lbs) {
+ if (lb.routable) {
+ lb_ipv4s_routable = lb_ipv4s_routable.union(lb.ipv4s);
+ lb_ipv6s_routable = lb_ipv6s_routable.union(lb.ipv6s);
+ } else {
+ lb_ipv4s_unroutable = lb_ipv4s_unroutable.union(lb.ipv4s);
+ lb_ipv6s_unroutable = lb_ipv6s_unroutable.union(lb.ipv6s);
+ }
+ };
+ (lb_ipv4s_routable, lb_ipv4s_unroutable,
+ lb_ipv6s_routable, lb_ipv6s_unroutable)
+ }.
/* RouterLB: many-to-many relation between logical routers and nb::LB */
-relation RouterLB(router: Intern<Router>, lb: Intern<nb::Load_Balancer>)
+relation RouterLB(router: Intern<Router>, lb: Intern<LoadBalancer>)
RouterLB(router, lb) :-
router in &Router(.lbs = lbs),
@@ -513,12 +563,12 @@ RouterLB(router, lb) :-
/* Load balancer VIPs associated with routers */
relation RouterLBVIP(
router: Intern<Router>,
- lb: Intern<nb::Load_Balancer>,
+ lb: Intern<LoadBalancer>,
vip: istring,
backends: istring)
RouterLBVIP(router, lb, vip, backends) :-
- RouterLB(router, lb@(&nb::Load_Balancer{.vips = vips})),
+ RouterLB(router, lb@(&LoadBalancer{.lb = &nb::Load_Balancer{.vips = vips}})),
(var vip, var backends) = FlatMap(vips).
/* Router-to-router logical port connections */
diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl
index c41a79b84..4348171ba 100644
--- a/northd/ovn_northd.dl
+++ b/northd/ovn_northd.dl
@@ -312,22 +312,12 @@ function get_router_load_balancer_ips(router: Intern<Router>,
routable_only: bool) :
(Set<istring>, Set<istring>) =
{
- var all_ips_v4 = set_empty();
- var all_ips_v6 = set_empty();
- for (lb in router.lbs) {
- if (routable_only and not lb.options.get_bool_def(i"add_route", false)) {
- continue;
- };
- for ((vip, _) in lb.vips) {
- /* node->key contains IP:port or just IP. */
- match (ip_address_and_port_from_lb_key(vip.ival())) {
- None -> (),
- Some{(IPv4{ipv4}, _)} -> all_ips_v4.insert(i"${ipv4}"),
- Some{(IPv6{ipv6}, _)} -> all_ips_v6.insert(i"${ipv6}")
- }
- }
- };
- (all_ips_v4, all_ips_v6)
+ if (routable_only) {
+ (router.lb_ipv4s_routable, router.lb_ipv6s_routable)
+ } else {
+ (union(router.lb_ipv4s_routable, router.lb_ipv4s_unroutable),
+ union(router.lb_ipv6s_routable, router.lb_ipv6s_unroutable))
+ }
}
/* Returns an array of strings, each consisting of a MAC address followed
@@ -2204,11 +2194,11 @@ function build_empty_lb_event_flow(key: istring, lb: Intern<nb::Load_Balancer>):
* The deprecated way is to set nb::NB_Global options:controller_event=true,
* which enables events for every load balancer.
*/
-relation LoadBalancerEmptyEvents(lb: Intern<nb::Load_Balancer>)
-LoadBalancerEmptyEvents(lb) :-
+relation LoadBalancerEmptyEvents(lb_uuid: uuid)
+LoadBalancerEmptyEvents(lb_uuid) :-
nb::NB_Global(.options = global_options),
var global_events = global_options.get_bool_def(i"controller_event", false),
- lb in &nb::Load_Balancer(.options = local_options),
+ &nb::Load_Balancer(._uuid = lb_uuid, .options = local_options),
var local_events = local_options.get_bool_def(i"event", false),
global_events or local_events.
@@ -2221,7 +2211,7 @@ Flow(.logical_datapath = sw._uuid,
.controller_meter = sw.copp.get(cOPP_EVENT_ELB()),
.stage_hint = stage_hint(lb._uuid)) :-
SwitchLBVIP(.sw_uuid = sw_uuid, .lb = lb, .vip = vip, .backends = backends),
- LoadBalancerEmptyEvents(lb),
+ LoadBalancerEmptyEvents(lb._uuid),
not lb.options.get_bool_def(i"reject", false),
sw in &Switch(._uuid = sw_uuid),
backends == i"",
@@ -5676,18 +5666,16 @@ var residence_check = match (is_redirect) {
true -> Some{i"is_chassis_resident(${json_escape(chassis_redirect_name(lrp.name))})"},
false -> None
} in {
- (var all_ips_v4, _) = get_router_load_balancer_ips(router, false) in {
- if (not all_ips_v4.is_empty()) {
- LogicalRouterArpFlow(.lr = router,
- .lrp = Some{lrp},
- .ip = i"{ ${all_ips_v4.map(ival).to_vec().join(\", \")} }",
- .mac = rEG_INPORT_ETH_ADDR(),
- .extra_match = residence_check,
- .drop = false,
- .priority = 90,
- .stage_hint = 0)
- }
- };
+ var all_ipv4s = union(router.lb_ipv4s_routable, router.lb_ipv4s_unroutable) in
+ not all_ipv4s.is_empty() in
+ LogicalRouterArpFlow(.lr = router,
+ .lrp = Some{lrp},
+ .ip = i"{ ${all_ipv4s.map(ival).to_vec().join(\", \")} }",
+ .mac = rEG_INPORT_ETH_ADDR(),
+ .extra_match = residence_check,
+ .drop = false,
+ .priority = 90,
+ .stage_hint = 0);
for (RouterLBVIP(.router = &Router{._uuid= lr_uuid}, .vip = vip)) {
Some{(var ip_address, _)} = ip_address_and_port_from_lb_key(vip.ival()) in {
IPv6{var ipv6} = ip_address in
@@ -6057,11 +6045,11 @@ Flow(.logical_datapath = lr,
.priority = 120,
.__match = i"flags.skip_snat_for_lb == 1 && ip",
.actions = i"next;",
- .stage_hint = stage_hint(lb._uuid),
+ .stage_hint = stage_hint(lb.lb._uuid),
.io_port = None,
.controller_meter = None) :-
LogicalRouterLB(lr, lb),
- lb.options.get_bool_def(i"skip_snat", false)
+ lb.lb.options.get_bool_def(i"skip_snat", false)
.
function lrouter_nat_is_stateless(nat: NAT): bool = {
@@ -6683,10 +6671,10 @@ for (RouterLBVIP(
.backends = backends)
if not l3dgw_ports.is_empty() or is_gateway)
{
- if (backends == i"" and not lb.options.get_bool_def(i"reject", false)) {
- for (LoadBalancerEmptyEvents(lb)) {
+ if (backends == i"" and not lb.lb.options.get_bool_def(i"reject", false)) {
+ for (LoadBalancerEmptyEvents(lb.lb._uuid)) {
Some {(var __match, var __action)} =
- build_empty_lb_event_flow(vip, lb) in
+ build_empty_lb_event_flow(vip, lb.lb) in
Flow(.logical_datapath = lr_uuid,
.stage = s_ROUTER_IN_DNAT(),
.priority = 130,
@@ -6694,7 +6682,7 @@ for (RouterLBVIP(
.actions = __action,
.io_port = None,
.controller_meter = r.copp.get(cOPP_EVENT_ELB()),
- .stage_hint = stage_hint(lb._uuid))
+ .stage_hint = stage_hint(lb.lb._uuid))
}
};
@@ -6703,7 +6691,7 @@ for (RouterLBVIP(
/* vip contains IP:port or just IP. */
Some{(var ip_address, var port)} = ip_address_and_port_from_lb_key(vip.ival()) in
var ipX = ip_address.ipX() in
- var proto = match (lb.protocol) {
+ var proto = match (lb.lb.protocol) {
Some{proto} -> proto,
_ -> i"tcp"
} in {
@@ -6759,15 +6747,15 @@ for (RouterLBVIP(
(110, "")
} in
var __match = match1 ++ match2 ++
- match ((l3dgw_ports.nth(0), backends != i"" or lb.options.get_bool_def(i"reject", false))) {
+ match ((l3dgw_ports.nth(0), backends != i"" or lb.lb.options.get_bool_def(i"reject", false))) {
(Some{gw_port}, true) -> " && is_chassis_resident(${json_escape(chassis_redirect_name(gw_port.name))})",
_ -> ""
} in
- var snat_for_lb = snat_for_lb(r.options, lb) in
+ var snat_for_lb = snat_for_lb(r.options, lb.lb) in
{
/* A match and actions for established connections. */
var est_match = "ct.est && " ++ match1 ++ match2 ++ " && ct_label.natted == 1" ++
- match ((l3dgw_ports.nth(0), backends != i"" or lb.options.get_bool_def(i"reject", false))) {
+ match ((l3dgw_ports.nth(0), backends != i"" or lb.lb.options.get_bool_def(i"reject", false))) {
(Some {var gw_port}, true) -> " && is_chassis_resident(${json_string_escape(chassis_redirect_name(gw_port.name))})",
_ -> ""
} in
@@ -6806,7 +6794,7 @@ for (RouterLBVIP(
.priority = 120,
.__match = match3.intern(),
.actions = i"next;",
- .stage_hint = stage_hint(lb._uuid),
+ .stage_hint = stage_hint(lb.lb._uuid),
.io_port = None,
.controller_meter = None)
};
@@ -6848,7 +6836,7 @@ for (RouterLBVIP(
.priority = 120,
.__match = undnat_match.intern(),
.actions = action,
- .stage_hint = stage_hint(lb._uuid),
+ .stage_hint = stage_hint(lb.lb._uuid),
.io_port = None,
.controller_meter = None)
}
--
2.31.1
More information about the dev
mailing list