[ovs-dev] [PATCH ovn v3 1/2] actions: Add new actions - ct_dnat_in_czone and ct_snat_in_czone.

numans at ovn.org numans at ovn.org
Fri Nov 19 16:32:08 UTC 2021


From: Numan Siddique <numans at ovn.org>

These actions are very similar to ct_dnat and ct_snat respectively
with one difference.  These new actions use the same zone id
for natting.  Upcoming patch will make use of these actions.

Acked-by: Mark Michelson <mmichels at redhat.com>
Signed-off-by: Numan Siddique <numans at ovn.org>
---

v2 -> v3
----
 * Added Mark's Ack

v1 -> v2
----
 * No changes.

 include/ovn/actions.h        |  2 ++
 include/ovn/logical-fields.h |  2 ++
 lib/actions.c                | 59 +++++++++++++++++++++++++-----
 ovn-sb.xml                   | 44 +++++++++++++++++++++++
 tests/ovn.at                 | 69 ++++++++++++++++++++++++++++++++++++
 utilities/ovn-trace.c        | 18 ++++++++--
 6 files changed, 184 insertions(+), 10 deletions(-)

diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index f023a37b9..ede5eb93c 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -66,6 +66,8 @@ struct ovn_extend_table;
     OVNACT(CT_COMMIT_V2,      ovnact_nest)            \
     OVNACT(CT_DNAT,           ovnact_ct_nat)          \
     OVNACT(CT_SNAT,           ovnact_ct_nat)          \
+    OVNACT(CT_DNAT_IN_CZONE,  ovnact_ct_nat)          \
+    OVNACT(CT_SNAT_IN_CZONE,  ovnact_ct_nat)          \
     OVNACT(CT_LB,             ovnact_ct_lb)           \
     OVNACT(SELECT,            ovnact_select)          \
     OVNACT(CT_CLEAR,          ovnact_null)            \
diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
index ef97117b9..c9675f81c 100644
--- a/include/ovn/logical-fields.h
+++ b/include/ovn/logical-fields.h
@@ -36,6 +36,8 @@ enum ovn_controller_event {
                                        * (32 bits). */
 #define MFF_LOG_SNAT_ZONE  MFF_REG12  /* conntrack snat zone for gateway router
                                        * (32 bits). */
+#define MFF_LOG_NAT_ZONE   MFF_LOG_DNAT_ZONE /* conntrack zone for both snat
+                                              * and dnat. */
 #define MFF_LOG_CT_ZONE    MFF_REG13  /* Logical conntrack zone for lports
                                        * (32 bits). */
 #define MFF_LOG_INPORT     MFF_REG14  /* Logical input port (32 bits). */
diff --git a/lib/actions.c b/lib/actions.c
index 7cf6be308..6b9a426ae 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -917,6 +917,20 @@ parse_CT_SNAT(struct action_context *ctx)
     parse_ct_nat(ctx, "ct_snat", ovnact_put_CT_SNAT(ctx->ovnacts));
 }
 
+static void
+parse_CT_DNAT_IN_CZONE(struct action_context *ctx)
+{
+    parse_ct_nat(ctx, "ct_dnat_in_czone",
+                 ovnact_put_CT_DNAT_IN_CZONE(ctx->ovnacts));
+}
+
+static void
+parse_CT_SNAT_IN_CZONE(struct action_context *ctx)
+{
+    parse_ct_nat(ctx, "ct_snat_in_czone",
+                 ovnact_put_CT_SNAT_IN_CZONE(ctx->ovnacts));
+}
+
 static void
 format_ct_nat(const struct ovnact_ct_nat *cn, const char *name, struct ds *s)
 {
@@ -954,21 +968,30 @@ format_CT_SNAT(const struct ovnact_ct_nat *cn, struct ds *s)
     format_ct_nat(cn, "ct_snat", s);
 }
 
+static void
+format_CT_DNAT_IN_CZONE(const struct ovnact_ct_nat *cn, struct ds *s)
+{
+    format_ct_nat(cn, "ct_dnat_in_czone", s);
+}
+
+static void
+format_CT_SNAT_IN_CZONE(const struct ovnact_ct_nat *cn, struct ds *s)
+{
+    format_ct_nat(cn, "ct_snat_in_czone", s);
+}
+
 static void
 encode_ct_nat(const struct ovnact_ct_nat *cn,
               const struct ovnact_encode_params *ep,
-              bool snat, struct ofpbuf *ofpacts)
+              bool snat, enum mf_field_id zone_src,
+              struct ofpbuf *ofpacts)
 {
     const size_t ct_offset = ofpacts->size;
     ofpbuf_pull(ofpacts, ct_offset);
 
     struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
     ct->recirc_table = cn->ltable + first_ptable(ep, ep->pipeline);
-    if (snat) {
-        ct->zone_src.field = mf_from_id(MFF_LOG_SNAT_ZONE);
-    } else {
-        ct->zone_src.field = mf_from_id(MFF_LOG_DNAT_ZONE);
-    }
+    ct->zone_src.field = mf_from_id(zone_src);
     ct->zone_src.ofs = 0;
     ct->zone_src.n_bits = 16;
     ct->flags = 0;
@@ -1020,7 +1043,7 @@ encode_CT_DNAT(const struct ovnact_ct_nat *cn,
                const struct ovnact_encode_params *ep,
                struct ofpbuf *ofpacts)
 {
-    encode_ct_nat(cn, ep, false, ofpacts);
+    encode_ct_nat(cn, ep, false, MFF_LOG_DNAT_ZONE, ofpacts);
 }
 
 static void
@@ -1028,7 +1051,23 @@ encode_CT_SNAT(const struct ovnact_ct_nat *cn,
                const struct ovnact_encode_params *ep,
                struct ofpbuf *ofpacts)
 {
-    encode_ct_nat(cn, ep, true, ofpacts);
+    encode_ct_nat(cn, ep, true, MFF_LOG_SNAT_ZONE, ofpacts);
+}
+
+static void
+encode_CT_DNAT_IN_CZONE(const struct ovnact_ct_nat *cn,
+                        const struct ovnact_encode_params *ep,
+                        struct ofpbuf *ofpacts)
+{
+    encode_ct_nat(cn, ep, false, MFF_LOG_NAT_ZONE, ofpacts);
+}
+
+static void
+encode_CT_SNAT_IN_CZONE(const struct ovnact_ct_nat *cn,
+                        const struct ovnact_encode_params *ep,
+                        struct ofpbuf *ofpacts)
+{
+    encode_ct_nat(cn, ep, true, MFF_LOG_NAT_ZONE, ofpacts);
 }
 
 static void
@@ -4017,6 +4056,10 @@ parse_action(struct action_context *ctx)
         parse_CT_DNAT(ctx);
     } else if (lexer_match_id(ctx->lexer, "ct_snat")) {
         parse_CT_SNAT(ctx);
+    } else if (lexer_match_id(ctx->lexer, "ct_dnat_in_czone")) {
+        parse_CT_DNAT_IN_CZONE(ctx);
+    } else if (lexer_match_id(ctx->lexer, "ct_snat_in_czone")) {
+        parse_CT_SNAT_IN_CZONE(ctx);
     } else if (lexer_match_id(ctx->lexer, "ct_lb")) {
         parse_ct_lb_action(ctx);
     } else if (lexer_match_id(ctx->lexer, "ct_clear")) {
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 150051f26..9ddacdf09 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -1383,6 +1383,50 @@
           </p>
         </dd>
 
+        <dt><code>ct_dnat_in_czone;</code></dt>
+        <dt><code>ct_dnat_in_czone(<var>IP</var>);</code></dt>
+        <dd>
+          <p>
+            <code>ct_dnat_in_czone</code> sends the packet through the common
+            NAT zone (used for both DNAT and SNAT) in connection tracking table
+            to unDNAT any packet that was DNATed in the opposite direction.
+            The packet is then automatically sent to to the next tables as if
+            followed by <code>next;</code> action.  The next tables will see
+            the changes in the packet caused by the connection tracker.
+          </p>
+          <p>
+            <code>ct_dnat_in_czone(<var>IP</var>)</code> sends the packet
+            through the common NAT zone to change the destination IP address
+            of the packet to the one provided inside the parentheses and
+            commits the connection.  The packet is then automatically sent to
+            the next tables as if followed by <code>next;</code> action.  The
+            next tables will see the changes in the packet caused by the
+            connection tracker.
+          </p>
+        </dd>
+
+        <dt><code>ct_snat_in_czone;</code></dt>
+        <dt><code>ct_snat_in_czone(<var>IP</var>);</code></dt>
+        <dd>
+          <p>
+            <code>ct_snat_in_czone</code> sends the packet through the common
+            NAT zone to unSNAT any packet that was SNATed in the opposite
+            direction.  The packet is automatically sent to the next tables as
+            if followed by the <code>next;</code> action.   The next tables
+            will see the changes in the packet caused by the connection
+            tracker.
+          </p>
+          <p>
+            <code>ct_snat_in_czone(<var>IP</var>)</code> sends the packet\
+            through the common NAT zone to change the source IP address of
+            the packet to the one provided inside the parenthesis and commits
+            the connection.  The packet is then automatically sent to the next
+            tables as if followed by <code>next;</code> action.  The next
+            tables will see the changes in the packet caused by the connection
+            tracker.
+          </p>
+        </dd>
+
         <dt><code>ct_clear;</code></dt>
         <dd>
           Clears connection tracking state.
diff --git a/tests/ovn.at b/tests/ovn.at
index ae832918c..0d606b42f 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1193,6 +1193,40 @@ ct_dnat(192.168.1.2, 1000);
 ct_dnat(192.168.1.2, 1000-100);
     Syntax error at `100' range high should be greater than range low.
 
+# ct_dnat_in_czone
+ct_dnat_in_czone;
+    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
+    has prereqs ip
+ct_dnat_in_czone(192.168.1.2);
+    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
+    has prereqs ip
+ct_dnat_in_czone(fd11::2);
+    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=fd11::2))
+    has prereqs ip
+ct_dnat_in_czone(192.168.1.2, 1-3000);
+    formats as ct_dnat_in_czone(192.168.1.2,1-3000);
+    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2:1-3000))
+    has prereqs ip
+
+ct_dnat_in_czone(192.168.1.2, 192.168.1.3);
+    Syntax error at `192.168.1.3' expecting Integer for port range.
+ct_dnat_in_czone(foo);
+    Syntax error at `foo' expecting IPv4 or IPv6 address.
+ct_dnat_in_czone(foo, bar);
+    Syntax error at `foo' expecting IPv4 or IPv6 address.
+ct_dnat_in_czone();
+    Syntax error at `)' expecting IPv4 or IPv6 address.
+ct_dnat_in_czone(192.168.1.2, foo);
+    Syntax error at `foo' expecting Integer for port range.
+ct_dnat_in_czone(192.168.1.2, 1000-foo);
+    Syntax error at `foo' expecting Integer for port range.
+ct_dnat_in_czone(192.168.1.2, 1000);
+    formats as ct_dnat_in_czone(192.168.1.2,1000);
+    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2:1000))
+    has prereqs ip
+ct_dnat_in_czone(192.168.1.2, 1000-100);
+    Syntax error at `100' range high should be greater than range low.
+
 # ct_snat
 ct_snat;
     encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat)
@@ -1226,6 +1260,41 @@ ct_snat(192.168.1.2, 1000);
     has prereqs ip
 ct_snat(192.168.1.2, 1000-100);
     Syntax error at `100' range high should be greater than range low.
+
+# ct_snat_in_czone
+ct_snat_in_czone;
+    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
+    has prereqs ip
+ct_snat_in_czone(192.168.1.2);
+    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=192.168.1.2))
+    has prereqs ip
+ct_snat_in_czone(fd11::2);
+    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=fd11::2))
+    has prereqs ip
+ct_snat_in_czone(192.168.1.2, 1-3000);
+    formats as ct_snat_in_czone(192.168.1.2,1-3000);
+    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=192.168.1.2:1-3000))
+    has prereqs ip
+
+ct_snat_in_czone(192.168.1.2, 192.168.1.3);
+    Syntax error at `192.168.1.3' expecting Integer for port range.
+ct_snat_in_czone(foo);
+    Syntax error at `foo' expecting IPv4 or IPv6 address.
+ct_snat_in_czone(foo, bar);
+    Syntax error at `foo' expecting IPv4 or IPv6 address.
+ct_snat_in_czone();
+    Syntax error at `)' expecting IPv4 or IPv6 address.
+ct_snat_in_czone(192.168.1.2, foo);
+    Syntax error at `foo' expecting Integer for port range.
+ct_snat_in_czone(192.168.1.2, 1000-foo);
+    Syntax error at `foo' expecting Integer for port range.
+ct_snat_in_czone(192.168.1.2, 1000);
+    formats as ct_snat_in_czone(192.168.1.2,1000);
+    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=192.168.1.2:1000))
+    has prereqs ip
+ct_snat_in_czone(192.168.1.2, 1000-100);
+    Syntax error at `100' range high should be greater than range low.
+
 # ct_clear
 ct_clear;
     encodes as ct_clear
diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
index 65a1822ea..617ad834c 100644
--- a/utilities/ovn-trace.c
+++ b/utilities/ovn-trace.c
@@ -2286,7 +2286,10 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat,
                const struct ovntrace_datapath *dp, struct flow *uflow,
                enum ovnact_pipeline pipeline, struct ovs_list *super)
 {
-    bool is_dst = ct_nat->ovnact.type == OVNACT_CT_DNAT;
+    bool is_dst = (ct_nat->ovnact.type == OVNACT_CT_DNAT ||
+                   ct_nat->ovnact.type == OVNACT_CT_DNAT_IN_CZONE);
+    bool nat_in_czone = (ct_nat->ovnact.type == OVNACT_CT_DNAT_IN_CZONE ||
+                         ct_nat->ovnact.type == OVNACT_CT_SNAT_IN_CZONE);
     if (!is_dst && dp->has_local_l3gateway && ct_nat->family == AF_UNSPEC) {
         /* "ct_snat;" has no visible effect in a gateway router. */
         return;
@@ -2297,7 +2300,8 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat,
      * and figure out the changes if any. */
     struct flow ct_flow = *uflow;
     struct ds s = DS_EMPTY_INITIALIZER;
-    ds_put_format(&s, "ct_%cnat", direction[0]);
+    ds_put_format(&s, "ct_%cnat%s", direction[0],
+                  nat_in_czone ? "in_czone" : "");
     if (ct_nat->family != AF_UNSPEC) {
         if (ct_nat->family == AF_INET) {
             ds_put_format(&s, "(ip4.%s="IP_FMT")", direction,
@@ -2610,6 +2614,16 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
             execute_ct_nat(ovnact_get_CT_SNAT(a), dp, uflow, pipeline, super);
             break;
 
+        case OVNACT_CT_DNAT_IN_CZONE:
+            execute_ct_nat(ovnact_get_CT_DNAT_IN_CZONE(a), dp, uflow,
+                           pipeline, super);
+            break;
+
+        case OVNACT_CT_SNAT_IN_CZONE:
+            execute_ct_nat(ovnact_get_CT_SNAT_IN_CZONE(a), dp, uflow,
+                           pipeline, super);
+            break;
+
         case OVNACT_CT_LB:
             execute_ct_lb(ovnact_get_CT_LB(a), dp, uflow, pipeline, super);
             break;
-- 
2.33.1



More information about the dev mailing list