Introduce build_lrouter_snat_flows_for_lb routine to configuring
lb_{skip,force}_snat flows for each configured load_balancerSigned-off-by: Lorenzo Bianconi <[email protected]> --- northd/ovn-northd.c | 163 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 127 insertions(+), 36 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 701cc4fbb..9a13dfcea 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -8730,41 +8730,10 @@ enum lb_snat_type { static void 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 sset *nat_entries) { - /* 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) { - char *new_actions = xasprintf("flags.%s_snat_for_lb = 1; %s", - snat_type == SKIP_SNAT ? "skip" : "force", - ds_cstr(actions)); - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority, - new_match, new_actions, &lb->header_); - free(new_actions); - } else { - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority, - new_match, ds_cstr(actions), &lb->header_); - } - - /* A match and actions for established connections. */ - char *est_match = xasprintf("ct.est && %s", ds_cstr(match)); - if (snat_type == FORCE_SNAT || snat_type == SKIP_SNAT) { - char *est_actions = xasprintf("flags.%s_snat_for_lb = 1; ct_dnat;", - snat_type == SKIP_SNAT ? "skip" : "force"); - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority, - est_match, est_actions, &lb->header_); - free(est_actions); - } else { - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority, - est_match, "ct_dnat;", &lb->header_); - } - - free(new_match); - free(est_match); - const char *ip_match = NULL; if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) { ip_match = "ip4"; @@ -8845,6 +8814,126 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od, ds_destroy(&undnat_match); } +static void +build_lrouter_snat_flows_for_lb(struct ovn_lb_vip *lb_vip, + struct ovn_northd_lb *lb, + struct ovn_northd_lb_vip *vips_nb, + struct hmap *lflows) +{ + char *new_match, *skip_snat_new_action = NULL; + char *est_match, *skip_snat_est_action = NULL; + struct ds action = DS_EMPTY_INITIALIZER; + struct ds match = DS_EMPTY_INITIALIZER; + + build_lb_vip_actions(lb_vip, vips_nb, &action, + lb->selection_fields, false); + + /* Higher priority rules are added for load-balancing in DNAT + * table. For every match (on a VIP[:port]), we add two flows. + * One flow is for specific matching on ct.new with an action + * of "ct_lb($targets);". The other flow is for ct.est with + * an action of "ct_dnat;". + */ + if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) { + ds_put_format(&match, "ip && ip4.dst == %s", lb_vip->vip_str); + } else { + ds_put_format(&match, "ip && ip6.dst == %s", lb_vip->vip_str); + } + + int prio = 110; + bool is_udp = nullable_string_is_equal(lb->nlb->protocol, "udp"); + bool is_sctp = nullable_string_is_equal(lb->nlb->protocol, + "sctp"); + const char *proto = is_udp ? "udp" : is_sctp ? "sctp" : "tcp"; + if (lb_vip->vip_port) { + ds_put_format(&match, " && %s && %s.dst == %d", proto, + proto, lb_vip->vip_port); + prio = 120; + } + + enum lb_snat_type snat_type = NO_FORCE_SNAT; + if (smap_get_bool(&lb->nlb->options, "skip_snat", false)) { + snat_type = 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; " + "ct_dnat;"); + } + new_match = xasprintf("ct.new && %s", ds_cstr(&match)); + est_match = xasprintf("ct.est && %s", ds_cstr(&match)); + + for (int i = 0; i < lb->n_nb_lr; i++) { + char *new_match_p = new_match, *est_match_p = est_match; + struct ovn_datapath *od = lb->nb_lr[i]; + + if (od->l3redirect_port && + (lb_vip->n_backends || !lb_vip->empty_backend_rej)) { + new_match_p = xasprintf("ct.new && %s && is_chassis_resident(%s)", + ds_cstr(&match), + od->l3redirect_port->json_key); + est_match_p = xasprintf("ct.est && %s && is_chassis_resident(%s)", + ds_cstr(&match), + od->l3redirect_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, + &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)); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, prio, + new_match_p, new_actions, + &lb->nlb->header_); + free(new_actions); + + char *est_actions = xasprintf("flags.force_snat_for_lb = 1; " + "ct_dnat;"); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, prio, + est_match_p, est_actions, + &lb->nlb->header_); + free(est_actions); + } else { + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, prio, + new_match_p, ds_cstr(&action), + &lb->nlb->header_); + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, prio, + est_match_p, "ct_dnat;", + &lb->nlb->header_); + } + + if (new_match_p != new_match) { + free(new_match_p); + } + if (est_match_p != est_match) { + free(est_match_p); + } + } + + ds_destroy(&action); + ds_destroy(&match); + + if (skip_snat_new_action) { + free(skip_snat_new_action); + } + if (skip_snat_est_action) { + free(skip_snat_est_action); + } + + free(est_match); + free(new_match); +} + static void build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows, struct shash *meter_groups) @@ -8857,7 +8946,9 @@ build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows, 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, + struct ovn_lb_vip *lb_vip = &lb->vips[i]; + + if (build_empty_lb_event_flow(lb_vip, 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, @@ -8866,6 +8957,9 @@ build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows, &lb->nlb->header_); } } + + build_lrouter_snat_flows_for_lb(lb_vip, lb, &lb->vips_nb[i], + lflows); } ds_destroy(&action); @@ -8941,7 +9035,6 @@ build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od, lb_vip->vip_str); } - int prio = 110; bool is_udp = nullable_string_is_equal(nb_lb->protocol, "udp"); bool is_sctp = nullable_string_is_equal(nb_lb->protocol, "sctp"); @@ -8950,7 +9043,6 @@ build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od, if (lb_vip->vip_port) { ds_put_format(match, " && %s && %s.dst == %d", proto, proto, lb_vip->vip_port); - prio = 120; } if (od->l3redirect_port && @@ -8958,8 +9050,7 @@ build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od, ds_put_format(match, " && is_chassis_resident(%s)", od->l3redirect_port->json_key); } - add_router_lb_flow(lflows, od, match, actions, prio, - snat_type, lb_vip, proto, nb_lb, + add_router_lb_flow(lflows, od, snat_type, lb_vip, proto, nb_lb, nat_entries); } } -- 2.31.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
