Group togheter gw routers where a given load balancer is installed
dividing them according to snat_type flag (skip_snat, force_snat).
This is a preliminary patch to reduce load balancer logical flows
computation cost.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
 northd/northd.c | 102 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 78 insertions(+), 24 deletions(-)

diff --git a/northd/northd.c b/northd/northd.c
index 389377542..361529be1 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -9826,11 +9826,28 @@ get_force_snat_ip(struct ovn_datapath *od, const char 
*key_type,
     return true;
 }
 
-enum lb_snat_type {
-    NO_FORCE_SNAT,
-    FORCE_SNAT,
-    SKIP_SNAT,
-};
+static void
+build_gw_lrouter_nat_flows_for_lb(struct ovn_northd_lb *lb,
+                                  struct ovn_datapath **dplist, int n_dplist,
+                                  bool reject, char *new_match,
+                                  char *new_action, char *est_match,
+                                  char *est_action, struct hmap *lflows,
+                                  int prio, const struct shash *meter_groups)
+{
+    for (size_t i = 0; i < n_dplist; i++) {
+        struct ovn_datapath *od = dplist[i];
+        const char *meter = NULL;
+
+        if (reject) {
+            meter = copp_meter_get(COPP_REJECT, od->nbr->copp, meter_groups);
+        }
+        ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_DNAT, prio,
+                                  new_match, new_action, NULL, meter,
+                                  &lb->nlb->header_);
+        ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, prio,
+                                est_match, est_action, &lb->nlb->header_);
+    }
+}
 
 static void
 build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip,
@@ -9865,9 +9882,8 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip,
                       lb_vip->vip_str);
     }
 
-    enum lb_snat_type snat_type = NO_FORCE_SNAT;
-    if (smap_get_bool(&lb->nlb->options, "skip_snat", false)) {
-        snat_type = SKIP_SNAT;
+    bool lb_skip_snat = smap_get_bool(&lb->nlb->options, "skip_snat", false);
+    if (lb_skip_snat) {
         skip_snat_new_action = xasprintf("flags.skip_snat_for_lb = 1; %s",
                                          ds_cstr(action));
         skip_snat_est_action = xasprintf("flags.skip_snat_for_lb = 1; "
@@ -9929,12 +9945,50 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip 
*lb_vip,
                       lb_vip->vip_port);
     }
 
+    struct ovn_datapath **gw_router_skip_snat =
+        xcalloc(lb->n_nb_lr, sizeof *gw_router_skip_snat);
+    int n_gw_router_skip_snat = 0;
+
+    struct ovn_datapath **gw_router_force_snat =
+        xcalloc(lb->n_nb_lr, sizeof *gw_router_force_snat);
+    int n_gw_router_force_snat = 0;
+
+    struct ovn_datapath **gw_router =
+        xcalloc(lb->n_nb_lr, sizeof *gw_router);
+    int n_gw_router = 0;
+
+    /* Group gw router since we do not have datapath dependency in
+     * lflow generation for them.
+     */
+    for (size_t i = 0; i < lb->n_nb_lr; i++) {
+        struct ovn_datapath *od = lb->nb_lr[i];
+        if (!od->n_l3dgw_ports) {
+            if (lb_skip_snat) {
+                gw_router_skip_snat[n_gw_router_skip_snat++] = od;
+            } else if (!lport_addresses_is_empty(&od->lb_force_snat_addrs) ||
+                       od->lb_force_snat_router_ip) {
+                gw_router_force_snat[n_gw_router_force_snat++] = od;
+            } else {
+                gw_router[n_gw_router++] = od;
+            }
+        }
+    }
+
+    build_gw_lrouter_nat_flows_for_lb(lb, gw_router_skip_snat,
+            n_gw_router_skip_snat, reject, new_match,
+            skip_snat_new_action, est_match,
+            skip_snat_est_action, lflows, prio, meter_groups);
+
+
     for (size_t i = 0; i < lb->n_nb_lr; i++) {
         struct ovn_datapath *od = lb->nb_lr[i];
         char *new_match_p = new_match;
         char *est_match_p = est_match;
         char *est_actions = NULL;
         const char *meter = NULL;
+        bool is_dp_lb_force_snat =
+            !lport_addresses_is_empty(&od->lb_force_snat_addrs) ||
+            od->lb_force_snat_router_ip;
 
         if (reject) {
             meter = copp_meter_get(COPP_REJECT, od->nbr->copp, meter_groups);
@@ -9967,20 +10021,16 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip 
*lb_vip,
                                     od->l3dgw_ports[0]->cr_port->json_key);
         }
 
-        if (snat_type == NO_FORCE_SNAT &&
-            (!lport_addresses_is_empty(&od->lb_force_snat_addrs) ||
-             od->lb_force_snat_router_ip)) {
-            snat_type = FORCE_SNAT;
-        }
-
-        if (snat_type == SKIP_SNAT) {
-            ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_DNAT, prio,
-                                      new_match_p, skip_snat_new_action, NULL,
-                                      meter, &lb->nlb->header_);
-            ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, prio,
-                                    est_match_p, skip_snat_est_action,
-                                    &lb->nlb->header_);
-        } else if (snat_type == FORCE_SNAT) {
+        if (lb_skip_snat) {
+            if (od->n_l3dgw_ports) {
+                ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_DNAT, prio,
+                                          new_match_p, skip_snat_new_action,
+                                          NULL, meter, &lb->nlb->header_);
+                ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, prio,
+                                        est_match_p, skip_snat_est_action,
+                                        &lb->nlb->header_);
+            }
+        } else if (is_dp_lb_force_snat) {
             char *new_actions = xasprintf("flags.force_snat_for_lb = 1; %s",
                                           ds_cstr(action));
             ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_DNAT, prio,
@@ -10018,11 +10068,11 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip 
*lb_vip,
             ds_cstr(&undnat_match),
             od->l3dgw_ports[0]->json_key,
             od->l3dgw_ports[0]->cr_port->json_key);
-        if (snat_type == SKIP_SNAT) {
+        if (lb_skip_snat) {
             ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120,
                                     undnat_match_p, skip_snat_est_action,
                                     &lb->nlb->header_);
-        } else if (snat_type == FORCE_SNAT) {
+        } else if (is_dp_lb_force_snat) {
             ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120,
                                     undnat_match_p, est_actions,
                                     &lb->nlb->header_);
@@ -10044,6 +10094,10 @@ next:
     free(skip_snat_est_action);
     free(est_match);
     free(new_match);
+
+    free(gw_router_force_snat);
+    free(gw_router_skip_snat);
+    free(gw_router);
 }
 
 static void
-- 
2.35.3

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to