Blob Blame History Raw
From 1dabc27cf3b0d8848b37be35260c2c6c56797fe7 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Date: Mon, 8 Mar 2021 15:00:27 +0100
Subject: [PATCH 10/16] northd: introduce build_lrouter_out_snat_flow routine

Introduce build_lrouter_out_snat_flow routine as a container for logical
router per nat configuration in build_lrouter_nat_defrag_and_lb
routine for S_ROUTER_OUT_SNAT table.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Numan Siddique <numans@ovn.org>
(cherry picked from commit 5e8fadf69161bc7e56b8f9f57124e5083b496b83)
---
 northd/ovn-northd.c | 195 ++++++++++++++++++++++----------------------
 1 file changed, 98 insertions(+), 97 deletions(-)

diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index c6df0fe6e..65bbffc07 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -11304,6 +11304,100 @@ build_lrouter_out_undnat_flow(struct hmap *lflows, struct ovn_datapath *od,
                             &nat->header_);
 }
 
+static void
+build_lrouter_out_snat_flow(struct hmap *lflows, struct ovn_datapath *od,
+                            const struct nbrec_nat *nat, struct ds *match,
+                            struct ds *actions, bool distributed,
+                            struct eth_addr mac, ovs_be32 mask,
+                            int cidr_bits, bool is_v6)
+{
+    /* Egress SNAT table: Packets enter the egress pipeline with
+    * source ip address that needs to be SNATted to a external ip
+    * address. */
+    if (strcmp(nat->type, "snat") && strcmp(nat->type, "dnat_and_snat")) {
+        return;
+    }
+
+    bool stateless = lrouter_nat_is_stateless(nat);
+    if (!od->l3dgw_port) {
+        /* Gateway router. */
+        ds_clear(match);
+        ds_put_format(match, "ip && ip%s.src == %s",
+                      is_v6 ? "6" : "4", nat->logical_ip);
+        ds_clear(actions);
+
+        if (nat->allowed_ext_ips || nat->exempted_ext_ips) {
+            lrouter_nat_add_ext_ip_match(od, lflows, match, nat,
+                                         is_v6, false, mask);
+        }
+
+        if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
+            ds_put_format(actions, "ip%s.src=%s; next;",
+                          is_v6 ? "6" : "4", nat->external_ip);
+        } else {
+            ds_put_format(actions, "ct_snat(%s", nat->external_ip);
+
+            if (nat->external_port_range[0]) {
+                ds_put_format(actions, ",%s",
+                              nat->external_port_range);
+            }
+            ds_put_format(actions, ");");
+        }
+
+        /* The priority here is calculated such that the
+        * nat->logical_ip with the longest mask gets a higher
+        * priority. */
+        ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT,
+                                cidr_bits + 1, ds_cstr(match),
+                                ds_cstr(actions), &nat->header_);
+    } else {
+        uint16_t priority = cidr_bits + 1;
+
+        /* Distributed router. */
+        ds_clear(match);
+        ds_put_format(match, "ip && ip%s.src == %s && outport == %s",
+                      is_v6 ? "6" : "4", nat->logical_ip,
+                      od->l3dgw_port->json_key);
+        if (!distributed && od->l3redirect_port) {
+            /* Flows for NAT rules that are centralized are only
+            * programmed on the gateway chassis. */
+            priority += 128;
+            ds_put_format(match, " && is_chassis_resident(%s)",
+                          od->l3redirect_port->json_key);
+        }
+        ds_clear(actions);
+
+        if (nat->allowed_ext_ips || nat->exempted_ext_ips) {
+            lrouter_nat_add_ext_ip_match(od, lflows, match, nat,
+                                         is_v6, false, mask);
+        }
+
+        if (distributed) {
+            ds_put_format(actions, "eth.src = "ETH_ADDR_FMT"; ",
+                          ETH_ADDR_ARGS(mac));
+        }
+
+        if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
+            ds_put_format(actions, "ip%s.src=%s; next;",
+                          is_v6 ? "6" : "4", nat->external_ip);
+        } else {
+            ds_put_format(actions, "ct_snat(%s",
+                        nat->external_ip);
+            if (nat->external_port_range[0]) {
+                ds_put_format(actions, ",%s", nat->external_port_range);
+            }
+            ds_put_format(actions, ");");
+        }
+
+        /* The priority here is calculated such that the
+        * nat->logical_ip with the longest mask gets a higher
+        * priority. */
+        ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT,
+                                priority, ds_cstr(match),
+                                ds_cstr(actions), &nat->header_);
+    }
+}
+
 /* NAT, Defrag and load balancing. */
 static void
 build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
@@ -11352,13 +11446,8 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
         ovs_be32 ip, mask;
         struct in6_addr ipv6, mask_v6, v6_exact = IN6ADDR_EXACT_INIT;
         bool is_v6 = false;
-        bool stateless = lrouter_nat_is_stateless(nat);
-        struct nbrec_address_set *allowed_ext_ips =
-                                  nat->allowed_ext_ips;
-        struct nbrec_address_set *exempted_ext_ips =
-                                  nat->exempted_ext_ips;
 
-        if (allowed_ext_ips && exempted_ext_ips) {
+        if (nat->allowed_ext_ips && nat->exempted_ext_ips) {
             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
             VLOG_WARN_RL(&rl, "NAT rule: "UUID_FMT" not applied, since "
                          "both allowed and exempt external ips set",
@@ -11486,97 +11575,9 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od,
         /* S_ROUTER_OUT_UNDNAT */
         build_lrouter_out_undnat_flow(lflows, od, nat, match, actions, distributed,
                                       mac, is_v6);
-
-        /* Egress SNAT table: Packets enter the egress pipeline with
-         * source ip address that needs to be SNATted to a external ip
-         * address. */
-        if (!strcmp(nat->type, "snat")
-            || !strcmp(nat->type, "dnat_and_snat")) {
-            if (!od->l3dgw_port) {
-                /* Gateway router. */
-                ds_clear(match);
-                ds_put_format(match, "ip && ip%s.src == %s",
-                              is_v6 ? "6" : "4",
-                              nat->logical_ip);
-                ds_clear(actions);
-
-                if (allowed_ext_ips || exempted_ext_ips) {
-                    lrouter_nat_add_ext_ip_match(od, lflows, match, nat,
-                                                 is_v6, false, mask);
-                }
-
-                if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
-                    ds_put_format(actions, "ip%s.src=%s; next;",
-                                  is_v6 ? "6" : "4", nat->external_ip);
-                } else {
-                    ds_put_format(actions, "ct_snat(%s",
-                                  nat->external_ip);
-
-                    if (nat->external_port_range[0]) {
-                        ds_put_format(actions, ",%s",
-                                      nat->external_port_range);
-                    }
-                    ds_put_format(actions, ");");
-                }
-
-                /* The priority here is calculated such that the
-                 * nat->logical_ip with the longest mask gets a higher
-                 * priority. */
-                ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT,
-                                        cidr_bits + 1,
-                                        ds_cstr(match), ds_cstr(actions),
-                                        &nat->header_);
-            } else {
-                uint16_t priority = cidr_bits + 1;
-
-                /* Distributed router. */
-                ds_clear(match);
-                ds_put_format(match, "ip && ip%s.src == %s"
-                                      " && outport == %s",
-                              is_v6 ? "6" : "4",
-                              nat->logical_ip,
-                              od->l3dgw_port->json_key);
-                if (!distributed && od->l3redirect_port) {
-                    /* Flows for NAT rules that are centralized are only
-                     * programmed on the gateway chassis. */
-                    priority += 128;
-                    ds_put_format(match, " && is_chassis_resident(%s)",
-                                  od->l3redirect_port->json_key);
-                }
-                ds_clear(actions);
-
-                if (allowed_ext_ips || exempted_ext_ips) {
-                    lrouter_nat_add_ext_ip_match(od, lflows, match, nat,
-                                                 is_v6, false, mask);
-                }
-
-                if (distributed) {
-                    ds_put_format(actions, "eth.src = "ETH_ADDR_FMT"; ",
-                                  ETH_ADDR_ARGS(mac));
-                }
-
-                if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
-                    ds_put_format(actions, "ip%s.src=%s; next;",
-                                  is_v6 ? "6" : "4", nat->external_ip);
-                } else {
-                    ds_put_format(actions, "ct_snat(%s",
-                                  nat->external_ip);
-                    if (nat->external_port_range[0]) {
-                        ds_put_format(actions, ",%s",
-                                      nat->external_port_range);
-                    }
-                    ds_put_format(actions, ");");
-                }
-
-                /* The priority here is calculated such that the
-                 * nat->logical_ip with the longest mask gets a higher
-                 * priority. */
-                ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT,
-                                        priority, ds_cstr(match),
-                                        ds_cstr(actions),
-                                        &nat->header_);
-            }
-        }
+        /* S_ROUTER_OUT_SNAT */
+        build_lrouter_out_snat_flow(lflows, od, nat, match, actions, distributed,
+                                    mac, mask, cidr_bits, is_v6);
 
         /* Logical router ingress table 0:
          * For NAT on a distributed router, add rules allowing
-- 
2.29.2