From patchwork Wed Jun 24 16:12:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1316381 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=whitealder.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=BfbnNDhg; dkim-atps=neutral Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49sSpx5Hzvz9sRR for ; Thu, 25 Jun 2020 02:12:41 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 0E1A48765D; Wed, 24 Jun 2020 16:12:40 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TTCsXZY5vE-F; Wed, 24 Jun 2020 16:12:35 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id D4791876C3; Wed, 24 Jun 2020 16:12:31 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BD1E3C0888; Wed, 24 Jun 2020 16:12:31 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 7A3CFC016F for ; Wed, 24 Jun 2020 16:12:31 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 70A652046D for ; Wed, 24 Jun 2020 16:12:31 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id dRn2+48zoBZF for ; Wed, 24 Jun 2020 16:12:24 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by silver.osuosl.org (Postfix) with ESMTPS id 6CC81203B8 for ; Wed, 24 Jun 2020 16:12:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1593015142; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KChtUT/XGroWJmo6QUlluFvTI0Nuq3gMk+sRziL40N4=; b=BfbnNDhgd6vQdoGahKJdn1AzYT/UywVRnA08wFJ4CNJGDwsSQayQyowdZ/ouK7AXPEKTMy eZQk9Ga2p03XR5plwf6U2si5xfcSHygF7j5RGBSTpXD3zk8QlKe0s5bilq00bHLmt3kOnW GiITzh/MHWblLZbeuirrkeeicuhQwUc= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-279-uqi6wm4ZM3uA3zEoA9kw-A-1; Wed, 24 Jun 2020 12:12:20 -0400 X-MC-Unique: uqi6wm4ZM3uA3zEoA9kw-A-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3588618A8220 for ; Wed, 24 Jun 2020 16:12:19 +0000 (UTC) Received: from monae.redhat.com (ovpn-117-53.rdu2.redhat.com [10.10.117.53]) by smtp.corp.redhat.com (Postfix) with ESMTP id E8F991C8 for ; Wed, 24 Jun 2020 16:12:17 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Wed, 24 Jun 2020 12:12:09 -0400 Message-Id: <20200624161211.1559878-4-mmichels@redhat.com> In-Reply-To: <20200624161211.1559878-1-mmichels@redhat.com> References: <20200624161211.1559878-1-mmichels@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH v3 ovn 4/6] Use normalized IP addreses in `ovn-nbctl lr-nat-add` X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Signed-off-by: Mark Michelson --- tests/ovn.at | 11 ++++ utilities/ovn-nbctl.c | 143 +++++++++++++++++++++--------------------- 2 files changed, 82 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 2e5253d4e..1b3027d52 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,65 @@ 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 +4337,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 +4346,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