Group together 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 for gw routers.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianc...@redhat.com>
---
 northd/northd.c | 83 ++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 71 insertions(+), 12 deletions(-)

diff --git a/northd/northd.c b/northd/northd.c
index bcb470043..d90879eeb 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -9832,6 +9832,29 @@ enum lb_snat_type {
     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,
                                struct ovn_northd_lb *lb,
@@ -9929,6 +9952,42 @@ 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 (snat_type == 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;
+                snat_type = FORCE_SNAT;
+            } 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;
@@ -9967,19 +10026,15 @@ 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_);
+            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 (snat_type == FORCE_SNAT) {
             char *new_actions = xasprintf("flags.force_snat_for_lb = 1; %s",
                                           ds_cstr(action));
@@ -10044,6 +10099,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.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to