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
