diff mbox series

[ovs-dev,3/6] northd: move build_empty_lb_event_flow in build_lrouter_flows_for_lb

Message ID 8530ab56ba03f76f7e33bb350281ddd2e63c708b.1623405172.git.lorenzo.bianconi@redhat.com
State New
Headers show
Series northd: rework ovn-northd lb flow installation | expand

Commit Message

Lorenzo Bianconi June 11, 2021, 10:17 a.m. UTC
Introduce build_lrouter_flows_for_lb routine in order to visit first each
load_balancer and then related datapath during lb flow installation.
This patch allows to reduce memory footprint and cpu utilization in
ovn-northd.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
 northd/ovn-northd.c | 109 +++++++++++++++++++++++++++++---------------
 1 file changed, 73 insertions(+), 36 deletions(-)
diff mbox series

Patch

diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 35d205eab..701cc4fbb 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -5125,52 +5125,53 @@  ls_has_dns_records(const struct nbrec_logical_switch *nbs)
     return false;
 }
 
-static void
-build_empty_lb_event_flow(struct ovn_datapath *od, struct hmap *lflows,
-                          struct ovn_lb_vip *lb_vip,
-                          struct nbrec_load_balancer *lb,
-                          int pl, struct shash *meter_groups)
+static bool
+build_empty_lb_event_flow(struct ovn_lb_vip *lb_vip,
+                          const struct nbrec_load_balancer *lb,
+                          struct shash *meter_groups,
+                          struct ds *match, struct ds *action)
 {
     bool controller_event = smap_get_bool(&lb->options, "event", false) ||
                             controller_event_en; /* deprecated */
     if (!controller_event || lb_vip->n_backends ||
         lb_vip->empty_backend_rej) {
-        return;
+        return false;
     }
 
+    ds_clear(action);
+    ds_clear(match);
+
     bool ipv4 = IN6_IS_ADDR_V4MAPPED(&lb_vip->vip);
-    struct ds match = DS_EMPTY_INITIALIZER;
-    char *meter = "", *action;
+    char *meter = "";
 
     if (meter_groups && shash_find(meter_groups, "event-elb")) {
         meter = "event-elb";
     }
 
-    ds_put_format(&match, "ip%s.dst == %s && %s",
+    ds_put_format(match, "ip%s.dst == %s && %s",
                   ipv4 ? "4": "6", lb_vip->vip_str, lb->protocol);
 
     char *vip = lb_vip->vip_str;
     if (lb_vip->vip_port) {
-        ds_put_format(&match, " && %s.dst == %u", lb->protocol,
+        ds_put_format(match, " && %s.dst == %u", lb->protocol,
                       lb_vip->vip_port);
         vip = xasprintf("%s%s%s:%u", ipv4 ? "" : "[", lb_vip->vip_str,
                         ipv4 ? "" : "]", lb_vip->vip_port);
     }
 
-    action = xasprintf("trigger_event(event = \"%s\", "
-                       "meter = \"%s\", vip = \"%s\", "
-                       "protocol = \"%s\", "
-                       "load_balancer = \"" UUID_FMT "\");",
-                       event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS),
-                       meter, vip, lb->protocol,
-                       UUID_ARGS(&lb->header_.uuid));
-    ovn_lflow_add_with_hint(lflows, od, pl, 130, ds_cstr(&match), action,
-                            &lb->header_);
-    ds_destroy(&match);
+    ds_put_format(action,
+                  "trigger_event(event = \"%s\", "
+                   "meter = \"%s\", vip = \"%s\", "
+                   "protocol = \"%s\", "
+                   "load_balancer = \"" UUID_FMT "\");",
+                   event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS),
+                   meter, vip, lb->protocol,
+                   UUID_ARGS(&lb->header_.uuid));
     if (lb_vip->vip_port) {
         free(vip);
     }
-    free(action);
+
+    return true;
 }
 
 static bool
@@ -5226,16 +5227,28 @@  build_pre_lb(struct ovn_datapath *od, struct hmap *lflows,
             ovn_northd_lb_find(lbs, &nb_lb->header_.uuid);
         ovs_assert(lb);
 
+        struct ds action = DS_EMPTY_INITIALIZER;
+        struct ds match = DS_EMPTY_INITIALIZER;
+
         for (size_t j = 0; j < lb->n_vips; j++) {
             struct ovn_lb_vip *lb_vip = &lb->vips[j];
-            build_empty_lb_event_flow(od, lflows, lb_vip, nb_lb,
-                                      S_SWITCH_IN_PRE_LB, meter_groups);
+
+            ds_clear(&action);
+            ds_clear(&match);
+            if (build_empty_lb_event_flow(lb_vip, nb_lb, meter_groups,
+                                           &match, &action)) {
+                ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_LB, 130,
+                                        ds_cstr(&match), ds_cstr(&action),
+                                        &nb_lb->header_);
+            }
 
             /* Ignore L4 port information in the key because fragmented packets
              * may not have L4 information.  The pre-stateful table will send
              * the packet through ct() action to de-fragment. In stateful
              * table, we will eventually look at L4 information. */
         }
+        ds_destroy(&action);
+        ds_destroy(&match);
 
         vip_configured = (vip_configured || lb->n_vips);
     }
@@ -8720,11 +8733,8 @@  add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
                    struct ds *match, struct ds *actions, int priority,
                    enum lb_snat_type snat_type, struct ovn_lb_vip *lb_vip,
                    const char *proto, struct nbrec_load_balancer *lb,
-                   struct shash *meter_groups, struct sset *nat_entries)
+                   struct sset *nat_entries)
 {
-    build_empty_lb_event_flow(od, lflows, lb_vip, lb, S_ROUTER_IN_DNAT,
-                              meter_groups);
-
     /* A match and actions for new connections. */
     char *new_match = xasprintf("ct.new && %s", ds_cstr(match));
     if (snat_type == FORCE_SNAT || snat_type == SKIP_SNAT) {
@@ -8835,11 +8845,37 @@  add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
     ds_destroy(&undnat_match);
 }
 
+static void
+build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows,
+                           struct shash *meter_groups)
+{
+    if (!lb->n_nb_lr) {
+        return;
+    }
+
+    struct ds action = DS_EMPTY_INITIALIZER;
+    struct ds match = DS_EMPTY_INITIALIZER;
+
+    for (size_t i = 0; i < lb->n_vips; i++) {
+        if (build_empty_lb_event_flow(&lb->vips[i], lb->nlb, meter_groups,
+                                      &match, &action)) {
+            for (int j = 0; j < lb->n_nb_lr; j++) {
+                ovn_lflow_add_with_hint(lflows, lb->nb_lr[j], S_ROUTER_IN_DNAT,
+                                        130, ds_cstr(&match),
+                                        ds_cstr(&action),
+                                        &lb->nlb->header_);
+            }
+        }
+    }
+
+    ds_destroy(&action);
+    ds_destroy(&match);
+}
+
 static void
 build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od,
-                       struct hmap *lbs, struct shash *meter_groups,
-                       struct sset *nat_entries, struct ds *match,
-                       struct ds *actions)
+                       struct hmap *lbs, struct sset *nat_entries,
+                       struct ds *match, struct ds *actions)
 {
     /* A set to hold all ips that need defragmentation and tracking. */
     struct sset all_ips = SSET_INITIALIZER(&all_ips);
@@ -8924,7 +8960,7 @@  build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od,
             }
             add_router_lb_flow(lflows, od, match, actions, prio,
                                snat_type, lb_vip, proto, nb_lb,
-                               meter_groups, nat_entries);
+                               nat_entries);
         }
     }
     sset_destroy(&all_ips);
@@ -11680,7 +11716,6 @@  lrouter_check_nat_entry(struct ovn_datapath *od, const struct nbrec_nat *nat,
 static void
 build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
                                 struct hmap *lflows,
-                                struct shash *meter_groups,
                                 struct hmap *lbs,
                                 struct ds *match, struct ds *actions)
 {
@@ -11882,8 +11917,7 @@  build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
         return;
     }
 
-    build_lrouter_lb_flows(lflows, od, lbs, meter_groups, &nat_entries,
-                           match, actions);
+    build_lrouter_lb_flows(lflows, od, lbs, &nat_entries, match, actions);
 
     sset_destroy(&nat_entries);
 }
@@ -11949,8 +11983,8 @@  build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od,
                                         &lsi->actions);
     build_misc_local_traffic_drop_flows_for_lrouter(od, lsi->lflows);
     build_lrouter_arp_nd_for_datapath(od, lsi->lflows);
-    build_lrouter_nat_defrag_and_lb(od, lsi->lflows, lsi->meter_groups,
-                                    lsi->lbs, &lsi->match, &lsi->actions);
+    build_lrouter_nat_defrag_and_lb(od, lsi->lflows, lsi->lbs, &lsi->match,
+                                    &lsi->actions);
 }
 
 /* Helper function to combine all lflow generation which is iterated by port.
@@ -12058,6 +12092,8 @@  build_lflows_thread(void *arg)
                     build_lswitch_arp_nd_service_monitor(lb, lsi->lflows,
                                                          &lsi->match,
                                                          &lsi->actions);
+                    build_lrouter_flows_for_lb(lb, lsi->lflows,
+                                               lsi->meter_groups);
                 }
             }
             for (bnum = control->id;
@@ -12221,6 +12257,7 @@  build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
             build_lswitch_arp_nd_service_monitor(lb, lsi.lflows,
                                                  &lsi.actions,
                                                  &lsi.match);
+            build_lrouter_flows_for_lb(lb, lsi.lflows, lsi.meter_groups);
         }
         HMAP_FOR_EACH (igmp_group, hmap_node, igmp_groups) {
             build_lswitch_ip_mcast_igmp_mld(igmp_group,