[ovs-dev] [PATCH v5 ovn 4/8] northd: move lb_{skip, force}_snat code in build_lrouter_nat_lflows_for_lb
Lorenzo Bianconi
lorenzo.bianconi at redhat.com
Mon Jul 5 10:05:42 UTC 2021
Introduce build_lrouter_nat_lflows_for_lb routine to configuring
lb_{skip,force}_snat flows for each configured load_balancer
Acked-by: Dumitru Ceara <dceara at redhat.com>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
---
northd/ovn-northd.c | 210 +++++++++++++++++++++++++++++++-------------
1 file changed, 150 insertions(+), 60 deletions(-)
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 6d53e42a9..7d8033725 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -3384,6 +3384,29 @@ void build_lb_vip_actions(struct ovn_lb_vip *lb_vip,
}
}
+static void
+build_ovn_lr_lbs(struct hmap *datapaths, struct hmap *lbs)
+{
+ struct ovn_northd_lb *lb;
+ struct ovn_datapath *od;
+
+ HMAP_FOR_EACH (od, key_node, datapaths) {
+ if (!od->nbr) {
+ continue;
+ }
+ if (!smap_get(&od->nbr->options, "chassis") && !od->l3dgw_port) {
+ continue;
+ }
+
+ for (size_t i = 0; i < od->nbr->n_load_balancer; i++) {
+ const struct uuid *lb_uuid =
+ &od->nbr->load_balancer[i]->header_.uuid;
+ lb = ovn_northd_lb_find(lbs, lb_uuid);
+ ovn_northd_lb_add_lr(lb, od);
+ }
+ }
+}
+
static void
build_ovn_lbs(struct northd_context *ctx, struct hmap *datapaths,
struct hmap *lbs)
@@ -3413,23 +3436,6 @@ build_ovn_lbs(struct northd_context *ctx, struct hmap *datapaths,
}
}
- HMAP_FOR_EACH (od, key_node, datapaths) {
- if (!od->nbr) {
- continue;
- }
- if (!smap_get(&od->nbr->options, "chassis") && !od->l3dgw_port) {
- continue;
- }
-
- for (size_t i = 0; i < od->nbr->n_load_balancer; i++) {
- const struct uuid *lb_uuid =
- &od->nbr->load_balancer[i]->header_.uuid;
- lb = ovn_northd_lb_find(lbs, lb_uuid);
-
- ovn_northd_lb_add_lr(lb, od);
- }
- }
-
/* Delete any stale SB load balancer rows. */
const struct sbrec_load_balancer *sbrec_lb, *next;
SBREC_LOAD_BALANCER_FOR_EACH_SAFE (sbrec_lb, next, ctx->ovnsb_idl) {
@@ -8764,41 +8770,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";
@@ -8879,6 +8854,122 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
ds_destroy(&undnat_match);
}
+static void
+build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip,
+ struct ovn_northd_lb *lb,
+ struct ovn_northd_lb_vip *vips_nb,
+ struct hmap *lflows,
+ struct ds *match, struct ds *action)
+{
+ char *skip_snat_new_action = NULL;
+ char *skip_snat_est_action = NULL;
+ char *new_match;
+ char *est_match;
+
+ ds_clear(match);
+ ds_clear(action);
+
+ 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 (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;
+
+ 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);
+ }
+ }
+
+ free(skip_snat_new_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, struct ds *match,
@@ -8889,8 +8980,13 @@ build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows,
}
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)) {
+ struct ovn_lb_vip *lb_vip = &lb->vips[i];
+
+ build_lrouter_nat_flows_for_lb(lb_vip, lb, &lb->vips_nb[i], lflows,
+ match, action);
+
+ if (!build_empty_lb_event_flow(lb_vip, lb->nlb, meter_groups,
+ match, action)) {
continue;
}
for (size_t j = 0; j < lb->n_nb_lr; j++) {
@@ -8904,7 +9000,7 @@ build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows,
static void
build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od,
struct hmap *lbs, struct sset *nat_entries,
- struct ds *match, struct ds *actions)
+ struct ds *match)
{
/* A set to hold all ips that need defragmentation and tracking. */
struct sset all_ips = SSET_INITIALIZER(&all_ips);
@@ -8928,10 +9024,6 @@ build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od,
for (size_t j = 0; j < lb->n_vips; j++) {
struct ovn_lb_vip *lb_vip = &lb->vips[j];
- struct ovn_northd_lb_vip *lb_vip_nb = &lb->vips_nb[j];
- ds_clear(actions);
- build_lb_vip_actions(lb_vip, lb_vip_nb, actions,
- lb->selection_fields, false);
if (!sset_contains(&all_ips, lb_vip->vip_str)) {
sset_add(&all_ips, lb_vip->vip_str);
@@ -8970,7 +9062,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");
@@ -8979,7 +9070,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 &&
@@ -8987,8 +9077,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);
}
}
@@ -11939,7 +12028,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
return;
}
- build_lrouter_lb_flows(lflows, od, lbs, &nat_entries, match, actions);
+ build_lrouter_lb_flows(lflows, od, lbs, &nat_entries, match);
sset_destroy(&nat_entries);
}
@@ -13398,6 +13487,7 @@ ovnnb_db_run(struct northd_context *ctx,
build_ovn_lbs(ctx, datapaths, &lbs);
build_lrouter_lbs(datapaths, &lbs);
build_ports(ctx, sbrec_chassis_by_name, datapaths, ports);
+ build_ovn_lr_lbs(datapaths, &lbs);
build_ovn_lb_svcs(ctx, ports, &lbs);
build_ipam(datapaths, ports);
build_port_group_lswitches(ctx, &port_groups, ports);
--
2.31.1
More information about the dev
mailing list