@@ -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) \
@@ -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). */
@@ -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")) {
@@ -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.
@@ -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
@@ -2281,7 +2281,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;
@@ -2292,7 +2295,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,
@@ -2599,6 +2603,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;