From patchwork Fri Apr 9 15:50:12 2021
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Lorenzo Bianconi flags.force_snat_for_lb = 1;
- ct_lb(args);
. If health check is enabled, then
+ ct_lb(args);.
+ If the load balancing rule is configured with skip_snat
+ set to true, the above action will be replaced by
+ flags.skip_snat_for_lb = 1; ct_lb(args);
.
+ If health check is enabled, then
args will only contain those endpoints whose service
monitor status entry in OVN_Southbound
db is
either online
or empty.
@@ -2771,6 +2775,9 @@ icmp6 {
with an action of ct_dnat;
. If the router is
configured to force SNAT any load-balanced packets, the above action
will be replaced by flags.force_snat_for_lb = 1; ct_dnat;
.
+ If the load balancing rule is configured with skip_snat
+ set to true, the above action will be replaced by
+ flags.skip_snat_for_lb = 1; ct_dnat;
.
flags.force_snat_for_lb = 1;
ct_lb(args);
.
+ If the load balancing rule is configured with skip_snat
+ set to true, the above action will be replaced by
+ flags.skip_snat_for_lb = 1; ct_lb(args);
.
flags.force_snat_for_lb = 1; ct_dnat;
.
+ If the load balancing rule is configured with skip_snat
+ set to true, the above action will be replaced by
+ flags.skip_snat_for_lb = 1; ct_dnat;
.
+ If a load balancer configured to skip snat has been applied to
+ the Gateway router pipeline, a priority-120 flow matches
+ flags.skip_snat_for_lb == 1 && ip
with an
+ action next;
.
+
If the Gateway router in the OVN Northbound database has been
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 9839b8c4f..8de106c84 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -8573,10 +8573,16 @@ 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
add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
struct ds *match, struct ds *actions, int priority,
- bool force_snat_for_lb, struct ovn_lb_vip *lb_vip,
+ 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)
{
@@ -8585,9 +8591,10 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
/* A match and actions for new connections. */
char *new_match = xasprintf("ct.new && %s", ds_cstr(match));
- if (force_snat_for_lb) {
- char *new_actions = xasprintf("flags.force_snat_for_lb = 1; %s",
- ds_cstr(actions));
+ 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);
@@ -8598,11 +8605,12 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
/* A match and actions for established connections. */
char *est_match = xasprintf("ct.est && %s", ds_cstr(match));
- if (force_snat_for_lb) {
+ 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,
- "flags.force_snat_for_lb = 1; ct_dnat;",
- &lb->header_);
+ 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_);
@@ -8675,11 +8683,13 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
ds_put_format(&undnat_match, ") && outport == %s && "
"is_chassis_resident(%s)", od->l3dgw_port->json_key,
od->l3redirect_port->json_key);
- if (force_snat_for_lb) {
+ if (snat_type == FORCE_SNAT || snat_type == SKIP_SNAT) {
+ char *action = xasprintf("flags.%s_snat_for_lb = 1; ct_dnat;",
+ snat_type == SKIP_SNAT ? "skip" : "force");
ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120,
- ds_cstr(&undnat_match),
- "flags.force_snat_for_lb = 1; ct_dnat;",
+ ds_cstr(&undnat_match), action,
&lb->header_);
+ free(action);
} else {
ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120,
ds_cstr(&undnat_match), "ct_dnat;",
@@ -8706,6 +8716,12 @@ build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od,
ovn_northd_lb_find(lbs, &nb_lb->header_.uuid);
ovs_assert(lb);
+ bool lb_skip_snat = smap_get_bool(&nb_lb->options, "skip_snat", false);
+ if (lb_skip_snat) {
+ ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 120,
+ "flags.skip_snat_for_lb == 1 && ip", "next;");
+ }
+
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];
@@ -8767,11 +8783,16 @@ build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od,
ds_put_format(match, " && is_chassis_resident(%s)",
od->l3redirect_port->json_key);
}
- bool force_snat_for_lb =
- lb_force_snat_ip || od->lb_force_snat_router_ip;
+
+ enum lb_snat_type snat_type = NO_FORCE_SNAT;
+ if (lb_skip_snat) {
+ snat_type = SKIP_SNAT;
+ } else if (lb_force_snat_ip || od->lb_force_snat_router_ip) {
+ snat_type = FORCE_SNAT;
+ }
add_router_lb_flow(lflows, od, match, actions, prio,
- force_snat_for_lb, lb_vip, proto,
- nb_lb, meter_groups, nat_entries);
+ snat_type, lb_vip, proto, nb_lb,
+ meter_groups, nat_entries);
}
}
sset_destroy(&all_ips);
diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl
index 0063021e1..4c02e2d5a 100644
--- a/northd/ovn_northd.dl
+++ b/northd/ovn_northd.dl
@@ -5367,6 +5367,16 @@ for (&Router(.lr = lr)) {
.external_ids = map_empty())
}
+Flow(.logical_datapath = lr,
+ .stage = s_ROUTER_OUT_SNAT(),
+ .priority = 120,
+ .__match = "flags.skip_snat_for_lb == 1 && ip",
+ .actions = "next;",
+ .external_ids = stage_hint(lb._uuid)) :-
+ LogicalRouterLB(lr, lb),
+ lb.options.get_bool_def("skip_snat", false)
+ .
+
function lrouter_nat_is_stateless(nat: NAT): bool = {
Some{"true"} == nat.nat.options.get("stateless")
}
@@ -6010,14 +6020,15 @@ for (RouterLBVIP(
(Some{gwport}, true) -> " && is_chassis_resident(${redirect_port_name})",
_ -> ""
} in
- var force_snat_for_lb = force_snat_for_lb(lr) in
+ var snat_for_lb = snat_for_lb(lr, lb) in
{
/* A match and actions for established connections. */
var est_match = "ct.est && " ++ __match in
var actions =
- match (force_snat_for_lb) {
- true -> "flags.force_snat_for_lb = 1; ct_dnat;",
- false -> "ct_dnat;"
+ match (snat_for_lb) {
+ SkipSNAT -> "flags.skip_snat_for_lb = 1; ct_dnat;",
+ ForceSNAT -> "flags.force_snat_for_lb = 1; ct_dnat;",
+ _ -> "ct_dnat;"
} in
Flow(.logical_datapath = lr._uuid,
.stage = s_ROUTER_IN_DNAT(),
@@ -6076,9 +6087,10 @@ for (RouterLBVIP(
") && outport == ${json_string_escape(gwport.name)} && "
"is_chassis_resident(${redirect_port_name})" in
var action =
- match (force_snat_for_lb) {
- true -> "flags.force_snat_for_lb = 1; ct_dnat;",
- false -> "ct_dnat;"
+ match (snat_for_lb) {
+ SkipSNAT -> "flags.skip_snat_for_lb = 1; ct_dnat;",
+ ForceSNAT -> "flags.force_snat_for_lb = 1; ct_dnat;",
+ _ -> "ct_dnat;"
} in
Flow(.logical_datapath = lr._uuid,
.stage = s_ROUTER_OUT_UNDNAT(),
@@ -6113,7 +6125,11 @@ Flow(.logical_datapath = r.lr._uuid,
_ -> ""
},
var priority = if (lbvip.vip_port != 0) 120 else 110,
- var force_snat = if (force_snat_for_lb(r.lr)) "flags.force_snat_for_lb = 1; " else "",
+ var force_snat = match (snat_for_lb(r.lr, lb)) {
+ SkipSNAT -> "flags.skip_snat_for_lb = 1; ",
+ ForceSNAT -> "flags.force_snat_for_lb = 1; ",
+ _ -> ""
+ },
var actions = build_lb_vip_actions(lbvip, s_ROUTER_OUT_SNAT(), force_snat).
diff --git a/ovn-nb.xml b/ovn-nb.xml
index b0a4adffe..408c98090 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -1653,6 +1653,12 @@
exactly one IPv4 and/or one IPv6 address on it, separated by a space
character.
+
+ skip_snat
+ option, the force_snat_for_lb option configured for the router
+ pipeline will not be applied for this load balancer.
+