@@ -1,7 +1,7 @@
{
"name": "OVN_Northbound",
- "version": "5.16.0",
- "cksum": "923459061 23095",
+ "version": "5.17.0",
+ "cksum": "1128988054 23237",
"tables": {
"NB_Global": {
"columns": {
@@ -345,6 +345,8 @@
"snat",
"dnat_and_snat"
]]}}},
+ "options": {"type": {"key": "string", "value": "string",
+ "min": 0, "max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
@@ -2254,6 +2254,11 @@
</p>
</column>
+ <column name="options" key="is_stateless">
+ Indicates if a dnat_and_snat rule should lead to connection
+ tracking state or not.
+ </column>
+
<group title="Common Columns">
<column name="external_ids">
See <em>External IDs</em> at the beginning of this document.
@@ -516,6 +516,31 @@ dnat_and_snat 30.0.0.2 192.168.1.3
snat 30.0.0.1 192.168.1.0/24
])
+AT_CHECK([ovn-nbctl --bare --columns=options list nat | grep is_stateless=true| wc -l], [0],
+[0
+])
+AT_CHECK([ovn-nbctl --stateless lr-nat-add lr0 dnat_and_snat 40.0.0.2 192.168.1.4])
+AT_CHECK([ovn-nbctl --bare --columns=options list nat | grep is_stateless=true| wc -l], [0],
+[1
+])
+AT_CHECK([ovn-nbctl --stateless lr-nat-add lr0 dnat 40.0.0.2 192.168.1.4], [1], [],
+[ovn-nbctl: is_stateless is not applicable to dnat or snat types
+])
+AT_CHECK([ovn-nbctl --stateless lr-nat-add lr0 snat 40.0.0.2 192.168.1.4], [1], [],
+[ovn-nbctl: is_stateless is not applicable to dnat or snat types
+])
+AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 40.0.0.2 192.168.1.5], [1], [],
+[ovn-nbctl: 40.0.0.2, 192.168.1.5: External ip cannot be shared across stateless and stateful NATs
+])
+AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 40.0.0.2 192.168.1.5], [1], [],
+[ovn-nbctl: 40.0.0.2, 192.168.1.5: External ip cannot be shared across stateless and stateful NATs
+])
+
+AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 40.0.0.3 192.168.1.6])
+AT_CHECK([ovn-nbctl --stateless lr-nat-add lr0 dnat_and_snat 40.0.0.3 192.168.1.7], [1], [],
+[ovn-nbctl: 40.0.0.3, 192.168.1.7: External ip cannot be shared across stateless and stateful NATs
+])
+
dnl Deletes the NATs
AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.3], [1], [],
[ovn-nbctl: no matching NAT with the type (dnat_and_snat) and external_ip (30.0.0.3)
@@ -533,14 +558,18 @@ AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
TYPE EXTERNAL_IP LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
dnat 30.0.0.1 192.168.1.2
dnat_and_snat 30.0.0.2 192.168.1.3
+dnat_and_snat 40.0.0.2 192.168.1.4
snat 30.0.0.1 192.168.1.0/24
+snat 40.0.0.3 192.168.1.6
])
AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
TYPE EXTERNAL_IP LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
dnat_and_snat 30.0.0.2 192.168.1.3
+dnat_and_snat 40.0.0.2 192.168.1.4
snat 30.0.0.1 192.168.1.0/24
+snat 40.0.0.3 192.168.1.6
])
AT_CHECK([ovn-nbctl lr-nat-del lr0])
@@ -665,7 +665,7 @@
<h1>NAT Commands</h1>
<dl>
- <dt>[<code>--may-exist</code>] <code>lr-nat-add</code> <var>router</var> <var>type</var> <var>external_ip</var> <var>logical_ip</var> [<var>logical_port</var> <var>external_mac</var>]</dt>
+ <dt>[<code>--may-exist</code>] [<code>--stateless</code>]<code>lr-nat-add</code> <var>router</var> <var>type</var> <var>external_ip</var> <var>logical_ip</var> [<var>logical_port</var> <var>external_mac</var>]</dt>
<dd>
<p>
Adds the specified NAT to <var>router</var>.
@@ -681,8 +681,18 @@
The <var>logical_port</var> is the name of an existing logical
switch port where the <var>logical_ip</var> resides.
The <var>external_mac</var> is an Ethernet address.
+ The <var>--stateless</var>
</p>
<p>
+ When <code>--stateless</code> is specified then it implies that
+ we will be not use connection tracker, i.e internal ip and external
+ ip are 1:1 mapped. This implies that <code>--stateless</code> is
+ applicable only to dnat_and_snat type NAT rules.
+ An external ip with <code>--stateless</code> NAT cannot be shared
+ with any other NAT rule.
+ </p>
+
+ <p>
When <var>type</var> is <code>dnat</code>, the externally
visible IP address <var>external_ip</var> is DNATted to the
IP address <var>logical_ip</var> in the logical space.
@@ -691,6 +691,7 @@ Policy commands:\n\
lr-policy-list ROUTER print policies for ROUTER\n\
\n\
NAT commands:\n\
+ [--stateless]\n\
lr-nat-add ROUTER TYPE EXTERNAL_IP LOGICAL_IP [LOGICAL_PORT EXTERNAL_MAC]\n\
add a NAT to ROUTER\n\
lr-nat-del ROUTER [TYPE [IP]]\n\
@@ -3926,6 +3927,13 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
}
bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
+ bool is_stateless = shash_find(&ctx->options, "--stateless") != NULL;
+
+ if (strcmp(nat_type, "dnat_and_snat") && is_stateless) {
+ ctl_error(ctx, "is_stateless is not applicable to dnat or snat types");
+ return;
+ }
+
int is_snat = !strcmp("snat", nat_type);
for (size_t i = 0; i < lr->n_nat; i++) {
const struct nbrec_nat *nat = lr->nat[i];
@@ -3957,10 +3965,25 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
return;
}
}
+
+ }
+ if (!strcmp(nat_type, "dnat_and_snat") ||
+ !strcmp(nat->type, "dnat_and_snat")) {
+
+ if (!strcmp(nat->external_ip, external_ip)) {
+ struct smap nat_options = SMAP_INITIALIZER(&nat_options);
+ if (!strcmp(smap_get(&nat->options, "is_stateless"),
+ "true") || is_stateless) {
+ ctl_error(ctx, "%s, %s: External ip cannot be shared "
+ "across stateless and stateful NATs",
+ external_ip, new_logical_ip);
+ }
+ }
}
}
/* Create the NAT. */
+ struct smap nat_options = SMAP_INITIALIZER(&nat_options);
struct nbrec_nat *nat = nbrec_nat_insert(ctx->txn);
nbrec_nat_set_type(nat, nat_type);
nbrec_nat_set_external_ip(nat, external_ip);
@@ -3969,7 +3992,12 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
nbrec_nat_set_logical_port(nat, logical_port);
nbrec_nat_set_external_mac(nat, external_mac);
}
+
+ smap_add(&nat_options, "is_stateless", is_stateless ? "true":"false");
+ nbrec_nat_set_options(nat, &nat_options);
+
free(new_logical_ip);
+ smap_destroy(&nat_options);
/* Insert the NAT into the logical router. */
nbrec_logical_router_verify_nat(lr);
@@ -5689,7 +5717,7 @@ static const struct ctl_command_syntax nbctl_commands[] = {
/* NAT commands. */
{ "lr-nat-add", 4, 6,
"ROUTER TYPE EXTERNAL_IP LOGICAL_IP [LOGICAL_PORT EXTERNAL_MAC]", NULL,
- nbctl_lr_nat_add, NULL, "--may-exist", RW },
+ nbctl_lr_nat_add, NULL, "--may-exist,--stateless", RW },
{ "lr-nat-del", 1, 3, "ROUTER [TYPE [IP]]", NULL,
nbctl_lr_nat_del, NULL, "--if-exists", RW },
{ "lr-nat-list", 1, 1, "ROUTER", NULL, nbctl_lr_nat_list, NULL, "", RO },
Adding ovn-nbctl to mark a dnat_and_snat rule as stateless. This configuration will added to "options" column of NAT table. Signed-off-by: Ankur Sharma <ankur.sharma@nutanix.com> --- ovn-nb.ovsschema | 6 ++++-- ovn-nb.xml | 5 +++++ tests/ovn-nbctl.at | 29 +++++++++++++++++++++++++++++ utilities/ovn-nbctl.8.xml | 12 +++++++++++- utilities/ovn-nbctl.c | 30 +++++++++++++++++++++++++++++- 5 files changed, 78 insertions(+), 4 deletions(-)