On 6/30/21 11:33 AM, Lorenzo Bianconi wrote:
> 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.bianc...@redhat.com>
> ---

Overall this looks good to me; I do have some suggestions inline though.

Thanks,
Dumitru

>  northd/ovn-northd.c | 109 +++++++++++++++++++++++++++++---------------
>  1 file changed, 73 insertions(+), 36 deletions(-)
> 
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index f23b299d8..b6889d887 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -5126,52 +5126,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));

Nit: indentation.

>      if (lb_vip->vip_port) {
>          free(vip);
>      }
> -    free(action);
> +

Nit: no need for a newline here I think.

> +    return true;
>  }
>  
>  static bool
> @@ -5227,16 +5228,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);

build_empty_lb_event_flow() also clears 'action' and 'match'.  It's
enough to do it in one place.

> +            if (build_empty_lb_event_flow(lb_vip, nb_lb, meter_groups,
> +                                           &match, &action)) {

Nit: indentation.

> +                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);
>      }
> @@ -8752,11 +8765,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) {
> @@ -8867,11 +8877,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++) {

s/int j/size_t 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_);
> +            }
> +        }

Nit: to reduce indentation I'd change this to:

if (!build_empty_lb_event_flow(...)) {
    continue;
}
ovn_lflow_add_with_hint(...)

> +    }
> +
> +    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);
> @@ -8956,7 +8992,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);
> @@ -11704,7 +11740,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)
>  {
> @@ -11906,8 +11941,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);
>  }
> @@ -11973,8 +12007,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.
> @@ -12082,6 +12116,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);

We can pass the &lsi->match and &lsi->actions "scratchpads" here.

>                  }
>              }
>              for (bnum = control->id;
> @@ -12245,6 +12281,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);

Same here.

>          }
>          HMAP_FOR_EACH (igmp_group, hmap_node, igmp_groups) {
>              build_lswitch_ip_mcast_igmp_mld(igmp_group,
> 

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

Reply via email to