[ovs-dev] [PATCH v3 1/2] NAT: Provide port hash in input
Ankur Sharma
svc.mail.git at nutanix.com
Wed Sep 16 00:05:13 UTC 2020
From: Ankur Sharma <ankur.sharma at nutanix.com>
This patch enhances the NB OVSSCHEMA to
add an additional column in NAT table.
external_port_hash: Specifies the hashing mechanism
if port range is specified.
Changes also add corresponding ovn-nbctl cli.
Signed-off-by: Ankur Sharma <ankur.sharma at nutanix.com>
---
ovn-nb.ovsschema | 5 +-
ovn-nb.xml | 15 ++++++
tests/ovn-nbctl.at | 136 +++++++++++++++++++++++++++++++-------------------
utilities/ovn-nbctl.c | 102 ++++++++++++++++++++++++++++---------
4 files changed, 182 insertions(+), 76 deletions(-)
diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
index 092322a..9b8e070 100644
--- a/ovn-nb.ovsschema
+++ b/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
{
"name": "OVN_Northbound",
- "version": "5.27.0",
- "cksum": "3507518247 26773",
+ "version": "5.28.0",
+ "cksum": "2621169942 26831",
"tables": {
"NB_Global": {
"columns": {
@@ -398,6 +398,7 @@
"external_mac": {"type": {"key": "string",
"min": 0, "max": 1}},
"external_port_range": {"type": "string"},
+ "external_port_hash": {"type": "string"},
"logical_ip": {"type": "string"},
"logical_port": {"type": {"key": "string",
"min": 0, "max": 1}},
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 0bfe626..142d934 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -2729,6 +2729,21 @@
</column>
+ <column name="external_port_hash">
+ <p>
+ Hashing algorithm to hash a packet to specified port range
+ </p>
+
+ <p>
+ Applicable only if port range is also specified.
+ </p>
+
+ <p>
+ Takes one of the 2 values "Random" and "Hash"
+ </p>
+
+ </column>
+
<column name="logical_ip">
An IPv4 network (e.g 192.168.1.0/24) or an IPv4 address.
</column>
diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
index baf7a87..6ce1ecf 100644
--- a/tests/ovn-nbctl.at
+++ b/tests/ovn-nbctl.at
@@ -476,15 +476,15 @@ AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat fd01::1 fd11::2])
AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.3 lp0 00:00:00:01:02:03])
AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat fd01::2 fd11::3 lp0 00:00:00:01:02:03])
AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE EXTERNAL_IP EXTERNAL_PORT LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
-dnat 30.0.0.1 192.168.1.2
-dnat fd01::1 fd11::2
-dnat_and_snat 30.0.0.1 192.168.1.2
-dnat_and_snat 30.0.0.2 192.168.1.3 00:00:00:01:02:03 lp0
-dnat_and_snat fd01::1 fd11::2
-dnat_and_snat fd01::2 fd11::3 00:00:00:01:02:03 lp0
-snat 30.0.0.1 192.168.1.0/24
-snat fd01::1 fd11::/64
+TYPE EXTERNAL_IP EXTERNAL_PORT EXTERNAL_PORT_HASH LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
+dnat 30.0.0.1 192.168.1.2
+dnat fd01::1 fd11::2
+dnat_and_snat 30.0.0.1 192.168.1.2
+dnat_and_snat 30.0.0.2 192.168.1.3 00:00:00:01:02:03 lp0
+dnat_and_snat fd01::1 fd11::2
+dnat_and_snat fd01::2 fd11::3 00:00:00:01:02:03 lp0
+snat 30.0.0.1 192.168.1.0/24
+snat fd01::1 fd11::/64
])
AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24], [1], [],
[ovn-nbctl: 30.0.0.1, 192.168.1.0/24: a NAT with this external_ip and logical_ip already exists
@@ -512,28 +512,28 @@ AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.3], [1], [],
])
AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.3 lp0 00:00:00:04:05:06])
AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE EXTERNAL_IP EXTERNAL_PORT LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
-dnat 30.0.0.1 192.168.1.2
-dnat fd01::1 fd11::2
-dnat_and_snat 30.0.0.1 192.168.1.2
-dnat_and_snat 30.0.0.2 192.168.1.3 00:00:00:04:05:06 lp0
-dnat_and_snat fd01::1 fd11::2
-dnat_and_snat fd01::2 fd11::3 00:00:00:01:02:03 lp0
-snat 30.0.0.1 192.168.1.0/24
-snat fd01::1 fd11::/64
+TYPE EXTERNAL_IP EXTERNAL_PORT EXTERNAL_PORT_HASH LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
+dnat 30.0.0.1 192.168.1.2
+dnat fd01::1 fd11::2
+dnat_and_snat 30.0.0.1 192.168.1.2
+dnat_and_snat 30.0.0.2 192.168.1.3 00:00:00:04:05:06 lp0
+dnat_and_snat fd01::1 fd11::2
+dnat_and_snat fd01::2 fd11::3 00:00:00:01:02:03 lp0
+snat 30.0.0.1 192.168.1.0/24
+snat fd01::1 fd11::/64
])
AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.3])
AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat fd01::2 fd11::3])
AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE EXTERNAL_IP EXTERNAL_PORT LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
-dnat 30.0.0.1 192.168.1.2
-dnat fd01::1 fd11::2
-dnat_and_snat 30.0.0.1 192.168.1.2
-dnat_and_snat 30.0.0.2 192.168.1.3
-dnat_and_snat fd01::1 fd11::2
-dnat_and_snat fd01::2 fd11::3
-snat 30.0.0.1 192.168.1.0/24
-snat fd01::1 fd11::/64
+TYPE EXTERNAL_IP EXTERNAL_PORT EXTERNAL_PORT_HASH LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
+dnat 30.0.0.1 192.168.1.2
+dnat fd01::1 fd11::2
+dnat_and_snat 30.0.0.1 192.168.1.2
+dnat_and_snat 30.0.0.2 192.168.1.3
+dnat_and_snat fd01::1 fd11::2
+dnat_and_snat fd01::2 fd11::3
+snat 30.0.0.1 192.168.1.0/24
+snat fd01::1 fd11::/64
])
AT_CHECK([ovn-nbctl --bare --columns=options list nat | grep stateless=true| wc -l], [0],
@@ -584,26 +584,26 @@ AT_CHECK([ovn-nbctl --if-exists lr-nat-del lr0 snat 192.168.10.0/24])
AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.1])
AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat fd01::1])
AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE EXTERNAL_IP EXTERNAL_PORT LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
-dnat 30.0.0.1 192.168.1.2
-dnat fd01::1 fd11::2
-dnat_and_snat 30.0.0.2 192.168.1.3
-dnat_and_snat 40.0.0.2 192.168.1.4
-dnat_and_snat fd01::2 fd11::3
-snat 30.0.0.1 192.168.1.0/24
-snat 40.0.0.3 192.168.1.6
-snat fd01::1 fd11::/64
+TYPE EXTERNAL_IP EXTERNAL_PORT EXTERNAL_PORT_HASH LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
+dnat 30.0.0.1 192.168.1.2
+dnat fd01::1 fd11::2
+dnat_and_snat 30.0.0.2 192.168.1.3
+dnat_and_snat 40.0.0.2 192.168.1.4
+dnat_and_snat fd01::2 fd11::3
+snat 30.0.0.1 192.168.1.0/24
+snat 40.0.0.3 192.168.1.6
+snat fd01::1 fd11::/64
])
AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE EXTERNAL_IP EXTERNAL_PORT 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
-dnat_and_snat fd01::2 fd11::3
-snat 30.0.0.1 192.168.1.0/24
-snat 40.0.0.3 192.168.1.6
-snat fd01::1 fd11::/64
+TYPE EXTERNAL_IP EXTERNAL_PORT EXTERNAL_PORT_HASH 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
+dnat_and_snat fd01::2 fd11::3
+snat 30.0.0.1 192.168.1.0/24
+snat 40.0.0.3 192.168.1.6
+snat fd01::1 fd11::/64
])
AT_CHECK([ovn-nbctl lr-nat-del lr0])
@@ -613,10 +613,10 @@ AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat 40.0.0.5 192.168.1.10 1])
AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.5 192.168.1.8 1-3000])
AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.6 192.168.1.9 lp0 00:00:00:04:05:06 1-3000])
AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.6 192.168.1.9 lp0 1-3000], [1], [],
-[ovn-nbctl: lr-nat-add with logical_port must also specify external_mac.
+[ovn-nbctl: invalid port range lp0.
])
AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.6 192.168.1.9 00:00:00:04:05:06 1-3000], [1], [],
-[ovn-nbctl: lr-nat-add with logical_port must also specify external_mac.
+[ovn-nbctl: invalid port range 00:00:00:04:05:06.
])
AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.7 192.168.1.10 0], [1], [],
@@ -674,12 +674,46 @@ AT_CHECK([ovn-nbctl show lr0 | grep -C2 'external port(s): "1"' | uuidfilt], [0]
])
AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE EXTERNAL_IP EXTERNAL_PORT LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
-dnat 40.0.0.4 1-3000 192.168.1.7
-dnat 40.0.0.5 1 192.168.1.10
-dnat_and_snat 40.0.0.5 1-3000 192.168.1.8
-dnat_and_snat 40.0.0.6 1-3000 192.168.1.9 00:00:00:04:05:06 lp0
-snat 40.0.0.3 21-65535 192.168.1.6
+TYPE EXTERNAL_IP EXTERNAL_PORT EXTERNAL_PORT_HASH LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
+dnat 40.0.0.4 1-3000 192.168.1.7
+dnat 40.0.0.5 1 192.168.1.10
+dnat_and_snat 40.0.0.5 1-3000 192.168.1.8
+dnat_and_snat 40.0.0.6 1-3000 192.168.1.9 00:00:00:04:05:06 lp0
+snat 40.0.0.3 21-65535 192.168.1.6
+])
+
+AT_CHECK([ovn-nbctl lr-nat-del lr0])
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 snat 40.0.0.3 192.168.1.6 21-65535 hash])
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat 40.0.0.4 192.168.1.7 1-3000 random])
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat 40.0.0.5 192.168.1.10 1 hash])
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.5 192.168.1.8 1-3000])
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.6 192.168.1.9 lp0 00:00:00:04:05:06 1-3000])
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.6 192.168.1.9 lp0 1-3000 hash], [1], [],
+[ovn-nbctl: invalid mac address 1-3000.
+])
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.6 192.168.1.9 00:00:00:04:05:06 1-3000 hash], [1], [],
+[ovn-nbctl: 00:00:00:04:05:06: port name not found
+])
+
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.7 192.168.1.10 0 random], [1], [],
+[ovn-nbctl: invalid port range 0.
+])
+
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.7 192.168.1.10 1-300 abcd], [1], [],
+[ovn-nbctl: invalid port hash abcd.
+])
+
+AT_CHECK([ovn-nbctl --portrange lr-nat-add lr0 dnat_and_snat 40.0.0.7 192.168.1.10 abcd], [1], [],
+[ovn-nbctl: invalid port range abcd.
+])
+
+AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
+TYPE EXTERNAL_IP EXTERNAL_PORT EXTERNAL_PORT_HASH LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
+dnat 40.0.0.4 1-3000 random 192.168.1.7
+dnat 40.0.0.5 1 hash 192.168.1.10
+dnat_and_snat 40.0.0.5 1-3000 192.168.1.8
+dnat_and_snat 40.0.0.6 1-3000 192.168.1.9 00:00:00:04:05:06 lp0
+snat 40.0.0.3 21-65535 hash 192.168.1.6
])
AT_CHECK([ovn-nbctl lr-nat-del lr0])
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index c54e639..3a1b158 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -1088,6 +1088,11 @@ print_lr(const struct nbrec_logical_router *lr, struct ds *s)
if (nat->external_port_range[0]) {
ds_put_cstr(s, " external port(s): ");
ds_put_format(s, "\"%s\"\n", nat->external_port_range);
+
+ if (nat->external_port_hash[0]) {
+ ds_put_cstr(s, " external port_hash: ");
+ ds_put_format(s, "\"%s\"\n", nat->external_port_hash);
+ }
}
ds_put_cstr(s, " logical ip: ");
ds_put_format(s, "\"%s\"\n", nat->logical_ip);
@@ -4129,6 +4134,16 @@ out:
free(nexthop);
}
+static inline bool
+is_valid_port_hash(const char *port_hash)
+{
+ if (!strcmp(port_hash, "hash") || !strcmp(port_hash, "random")) {
+ return true;
+ }
+
+ return false;
+}
+
static bool
is_valid_port_range(const char *port_range)
{
@@ -4246,6 +4261,7 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
const char *logical_port = NULL;
const char *external_mac = NULL;
const char *port_range = NULL;
+ const char *port_hash = NULL;
if (ctx->argc == 6) {
if (!is_portrange) {
@@ -4259,19 +4275,46 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
goto cleanup;
}
- } else if (ctx->argc >= 7) {
- if (strcmp(nat_type, "dnat_and_snat")) {
- ctl_error(ctx, "logical_port and external_mac are only valid when "
- "type is \"dnat_and_snat\".");
- goto cleanup;
- }
+ } else if (ctx->argc == 7) {
+ if (is_portrange) {
+ port_range = ctx->argv[5];
+ if (!is_valid_port_range(port_range)) {
+ ctl_error(ctx, "invalid port range %s.", port_range);
+ goto cleanup;
+ }
- if (ctx->argc == 7 && is_portrange) {
- ctl_error(ctx, "lr-nat-add with logical_port "
- "must also specify external_mac.");
- goto cleanup;
+ /* No need to validate the hash value, NBDB set will fail,
+ * If value is not valid */
+ port_hash = ctx->argv[6];
+ if (!is_valid_port_hash(port_hash)) {
+ ctl_error(ctx, "invalid port hash %s.", port_hash);
+ goto cleanup;
+ }
+ } else {
+ if (strcmp(nat_type, "dnat_and_snat")) {
+ ctl_error(ctx, "logical_port and external_mac are only valid "
+ "when type is \"dnat_and_snat\".");
+ goto cleanup;
+ }
+
+ logical_port = ctx->argv[5];
+ const struct nbrec_logical_switch_port *lsp;
+ error = lsp_by_name_or_uuid(ctx, logical_port, true, &lsp);
+ if (error) {
+ ctx->error = error;
+ goto cleanup;
+ }
+
+ external_mac = ctx->argv[6];
+ struct eth_addr ea;
+ if (!eth_addr_from_string(external_mac, &ea)) {
+ ctl_error(ctx, "invalid mac address %s.", external_mac);
+ goto cleanup;
+ }
}
+ } else if (ctx->argc >= 8) {
+
logical_port = ctx->argv[5];
const struct nbrec_logical_switch_port *lsp;
error = lsp_by_name_or_uuid(ctx, logical_port, true, &lsp);
@@ -4286,11 +4329,17 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
ctl_error(ctx, "invalid mac address %s.", external_mac);
goto cleanup;
}
-
- if (ctx->argc > 7) {
- port_range = ctx->argv[7];
- if (!is_valid_port_range(port_range)) {
- ctl_error(ctx, "invalid port range %s.", port_range);
+ port_range = ctx->argv[7];
+ if (!is_valid_port_range(port_range)) {
+ ctl_error(ctx, "invalid port range %s.", port_range);
+ goto cleanup;
+ }
+ if (ctx->argc > 8) {
+ /* No need to validate the hash value, NBDB set will fail,
+ * If value is not valid */
+ port_hash = ctx->argv[8];
+ if (!is_valid_port_hash(port_hash)) {
+ ctl_error(ctx, "invalid port hash %s.", port_hash);
goto cleanup;
}
}
@@ -4299,6 +4348,7 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
port_range = NULL;
logical_port = NULL;
external_mac = NULL;
+ port_hash = NULL;
}
bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
@@ -4387,6 +4437,9 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
if (port_range) {
nbrec_nat_set_external_port_range(nat, port_range);
+ if (port_hash) {
+ nbrec_nat_set_external_port_hash(nat, port_hash);
+ }
}
smap_add(&nat_options, "stateless", stateless ? "true":"false");
@@ -4507,13 +4560,15 @@ nbctl_lr_nat_list(struct ctl_context *ctx)
const struct nbrec_nat *nat = lr->nat[i];
char *key = xasprintf("%-17.13s%s", nat->type, nat->external_ip);
if (nat->external_mac && nat->logical_port) {
- smap_add_format(&lr_nats, key, "%-17.13s%-22.18s%-21.17s%s",
- nat->external_port_range,
+ smap_add_format(&lr_nats, key, "%-17.13s%-22.18s%-"
+ "22.18s%-21.17s%s",nat->external_port_range,
+ nat->external_port_hash,
nat->logical_ip, nat->external_mac,
nat->logical_port);
} else {
- smap_add_format(&lr_nats, key, "%-17.13s%s",
+ smap_add_format(&lr_nats, key, "%-17.13s%-22.18s%s",
nat->external_port_range,
+ nat->external_port_hash,
nat->logical_ip);
}
free(key);
@@ -4522,9 +4577,9 @@ nbctl_lr_nat_list(struct ctl_context *ctx)
const struct smap_node **nodes = smap_sort(&lr_nats);
if (nodes) {
ds_put_format(&ctx->output,
- "%-17.13s%-19.15s%-17.13s%-22.18s%-21.17s%s\n",
- "TYPE", "EXTERNAL_IP", "EXTERNAL_PORT", "LOGICAL_IP",
- "EXTERNAL_MAC", "LOGICAL_PORT");
+ "%-17.13s%-19.15s%-17.13s%-22.18s%-22.18s%-21.17s%s\n",
+ "TYPE", "EXTERNAL_IP", "EXTERNAL_PORT", "EXTERNAL_PORT_HASH",
+ "LOGICAL_IP","EXTERNAL_MAC", "LOGICAL_PORT");
for (size_t i = 0; i < smap_count(&lr_nats); i++) {
const struct smap_node *node = nodes[i];
ds_put_format(&ctx->output, "%-36.32s%s\n",
@@ -6538,8 +6593,9 @@ static const struct ctl_command_syntax nbctl_commands[] = {
/* NAT commands. */
{ "lr-nat-add", 4, 7,
"ROUTER TYPE EXTERNAL_IP LOGICAL_IP"
- "[LOGICAL_PORT EXTERNAL_MAC] [EXTERNAL_PORT_RANGE]", NULL,
- nbctl_lr_nat_add, NULL, "--may-exist,--stateless,--portrange", RW },
+ "[LOGICAL_PORT EXTERNAL_MAC] [EXTERNAL_PORT_RANGE EXTERNAL_PORT_HASH]",
+ NULL, nbctl_lr_nat_add, NULL, "--may-exist,--stateless,--portrange",
+ 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 },
--
1.8.3.1
More information about the dev
mailing list