[ovs-dev] [PATCH v4 ovn 4/6] Use normalized IP addreses in `ovn-nbctl lr-nat-add`
Mark Michelson
mmichels at redhat.com
Wed Jun 24 19:21:12 UTC 2020
Signed-off-by: Mark Michelson <mmichels at redhat.com>
---
tests/ovn.at | 11 ++++
utilities/ovn-nbctl.c | 144 +++++++++++++++++++++---------------------
2 files changed, 83 insertions(+), 72 deletions(-)
diff --git a/tests/ovn.at b/tests/ovn.at
index d54a4d707..66e6024e1 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -19729,3 +19729,14 @@ ovn-nbctl lrp-add r1 rp1 CC:DD:EE:EE:DD:CC AEF0::1/64 BEF0::1/64
AT_CHECK([ovn-nbctl --may-exist lrp-add r1 rp1 cc:dd:ee:ee:dd:cc bef0:0000:0000:0000::1/64 aef0::1/64])
AT_CLEANUP
+
+AT_SETUP([ovn -- normalized lr-nat-add])
+ovn_start
+
+ovn-nbctl lr-add r1
+ovn-nbctl lr-nat-add r1 snat AEF0::1 BEEF::/64
+ovn-nbctl lr-nat-add r1 dnat AEF0::1 BEEF::1
+
+AT_CHECK([ovn-nbctl --may-exist lr-nat-add r1 snat aef0:0000::1 beef:0000::/ffff:ffff:ffff:ffff::0])
+AT_CHECK([ovn-nbctl --may-exist lr-nat-add r1 dnat aef0:0000:00::1 beef::0001])
+AT_CLEANUP
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index fd761a0a2..4e10052fd 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -4138,6 +4138,7 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
const char *external_ip = ctx->argv[3];
const char *logical_ip = ctx->argv[4];
char *new_logical_ip = NULL;
+ char *new_external_ip = NULL;
bool is_portrange = shash_find(&ctx->options, "--portrange") != NULL;
char *error = lr_by_name_or_uuid(ctx, ctx->argv[1], true, &lr);
@@ -4153,55 +4154,41 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
return;
}
- ovs_be32 ipv4 = 0;
- unsigned int plen;
- struct in6_addr ipv6;
bool is_v6 = false;
- if (!ip_parse(external_ip, &ipv4)) {
- if (ipv6_parse(external_ip, &ipv6)) {
- is_v6 = true;
- } else {
- ctl_error(ctx, "%s: Not a valid IPv4 or IPv6 address.",
- external_ip);
- return;
- }
+
+ new_external_ip = normalize_ipv4_addr_str(external_ip);
+ if (!new_external_ip) {
+ new_external_ip = normalize_ipv6_addr_str(external_ip);
+ is_v6 = true;
+ }
+ if (!new_external_ip) {
+ ctl_error(ctx, "%s: Not a valid IPv4 or IPv6 address.",
+ external_ip);
+ return;
}
if (strcmp("snat", nat_type)) {
- if (is_v6) {
- if (!ipv6_parse(logical_ip, &ipv6)) {
- ctl_error(ctx, "%s: Not a valid IPv6 address.", logical_ip);
- return;
- }
- } else {
- if (!ip_parse(logical_ip, &ipv4)) {
- ctl_error(ctx, "%s: Not a valid IPv4 address.", logical_ip);
- return;
- }
+ new_logical_ip = is_v6
+ ? normalize_ipv6_addr_str(logical_ip)
+ : normalize_ipv4_addr_str(logical_ip);
+ if (!new_logical_ip) {
+ ctl_error(ctx, "%s: Not a valid %s address.", logical_ip,
+ is_v6 ? "IPv6" : "IPv4");
}
- new_logical_ip = xstrdup(logical_ip);
} else {
- if (is_v6) {
- error = ipv6_parse_cidr(logical_ip, &ipv6, &plen);
- if (error) {
- free(error);
- ctl_error(ctx, "%s: should be an IPv6 address or network.",
- logical_ip);
- return;
- }
- new_logical_ip = normalize_ipv6_prefix(ipv6, plen);
- } else {
- error = ip_parse_cidr(logical_ip, &ipv4, &plen);
- if (error) {
- free(error);
- ctl_error(ctx, "%s: should be an IPv4 address or network.",
- logical_ip);
- return;
- }
- new_logical_ip = normalize_ipv4_prefix(ipv4, plen);
+ new_logical_ip = is_v6
+ ? normalize_ipv6_prefix_str(logical_ip)
+ : normalize_ipv4_prefix_str(logical_ip);
+ if (!new_logical_ip) {
+ ctl_error(ctx, "%s: should be an %s address or network.",
+ logical_ip, is_v6 ? "IPv6" : "IPv4");
}
}
+ if (!new_logical_ip) {
+ goto cleanup;
+ }
+
const char *logical_port = NULL;
const char *external_mac = NULL;
const char *port_range = NULL;
@@ -4210,29 +4197,25 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
if (!is_portrange) {
ctl_error(ctx, "lr-nat-add with logical_port "
"must also specify external_mac.");
- free(new_logical_ip);
- return;
+ goto cleanup;
}
port_range = ctx->argv[5];
if (!is_valid_port_range(port_range)) {
ctl_error(ctx, "invalid port range %s.", port_range);
- free(new_logical_ip);
- return;
+ 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\".");
- free(new_logical_ip);
- return;
+ goto cleanup;
}
if (ctx->argc == 7 && is_portrange) {
ctl_error(ctx, "lr-nat-add with logical_port "
"must also specify external_mac.");
- free(new_logical_ip);
- return;
+ goto cleanup;
}
logical_port = ctx->argv[5];
@@ -4240,24 +4223,21 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
error = lsp_by_name_or_uuid(ctx, logical_port, true, &lsp);
if (error) {
ctx->error = error;
- free(new_logical_ip);
- return;
+ 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);
- free(new_logical_ip);
- return;
+ 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);
- free(new_logical_ip);
- return;
+ goto cleanup;
}
}
@@ -4278,49 +4258,66 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
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];
+
+ char *old_external_ip;
+ char *old_logical_ip;
+ bool should_return = false;
+ old_external_ip = normalize_prefix_str(nat->external_ip);
+ if (!old_external_ip) {
+ continue;
+ }
+ old_logical_ip = normalize_prefix_str(nat->logical_ip);
+ if (!old_logical_ip) {
+ free(old_external_ip);
+ continue;
+ }
+
if (!strcmp(nat_type, nat->type)) {
- if (!strcmp(is_snat ? new_logical_ip : external_ip,
- is_snat ? nat->logical_ip : nat->external_ip)) {
- if (!strcmp(is_snat ? external_ip : new_logical_ip,
- is_snat ? nat->external_ip : nat->logical_ip)) {
+ if (!strcmp(is_snat ? new_logical_ip : new_external_ip,
+ is_snat ? old_logical_ip : old_external_ip)) {
+ if (!strcmp(is_snat ? new_external_ip : new_logical_ip,
+ is_snat ? old_external_ip : old_logical_ip)) {
if (may_exist) {
nbrec_nat_verify_logical_port(nat);
nbrec_nat_verify_external_mac(nat);
nbrec_nat_set_logical_port(nat, logical_port);
nbrec_nat_set_external_mac(nat, external_mac);
- free(new_logical_ip);
- return;
+ should_return = true;
+ } else {
+ ctl_error(ctx, "%s, %s: a NAT with this "
+ "external_ip and logical_ip already "
+ "exists", new_external_ip,
+ new_logical_ip);
+ should_return = true;
}
- ctl_error(ctx, "%s, %s: a NAT with this external_ip "
- "and logical_ip already exists",
- external_ip, new_logical_ip);
- free(new_logical_ip);
- return;
} else {
ctl_error(ctx, "a NAT with this type (%s) and %s (%s) "
"already exists",
nat_type,
is_snat ? "logical_ip" : "external_ip",
- is_snat ? new_logical_ip : external_ip);
- free(new_logical_ip);
- return;
+ is_snat ? new_logical_ip : new_external_ip);
+ should_return = true;
}
}
-
}
if (!strcmp(nat_type, "dnat_and_snat") ||
!strcmp(nat->type, "dnat_and_snat")) {
- if (!strcmp(nat->external_ip, external_ip)) {
+ if (!strcmp(old_external_ip, new_external_ip)) {
struct smap nat_options = SMAP_INITIALIZER(&nat_options);
if (!strcmp(smap_get(&nat->options, "stateless"),
"true") || stateless) {
ctl_error(ctx, "%s, %s: External ip cannot be shared "
"across stateless and stateful NATs",
- external_ip, new_logical_ip);
+ new_external_ip, new_logical_ip);
}
}
}
+ free(old_external_ip);
+ free(old_logical_ip);
+ if (should_return) {
+ goto cleanup;
+ }
}
/* Create the NAT. */
@@ -4341,7 +4338,6 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
smap_add(&nat_options, "stateless", 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. */
@@ -4351,6 +4347,10 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
new_nats[lr->n_nat] = nat;
nbrec_logical_router_set_nat(lr, new_nats, lr->n_nat + 1);
free(new_nats);
+
+cleanup:
+ free(new_logical_ip);
+ free(new_external_ip);
}
static void
--
2.25.4
More information about the dev
mailing list