From patchwork Mon Sep 7 20:56:44 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Ankur Sharma
X-Patchwork-Id: 1359259
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.136; helo=silver.osuosl.org;
envelope-from=ovs-dev-bounces@openvswitch.org; receiver=)
Authentication-Results: ozlabs.org;
dmarc=fail (p=none dis=none) header.from=nutanix.com
Authentication-Results: ozlabs.org;
dkim=fail reason="signature verification failed" (2048-bit key;
unprotected) header.d=nutanix.com header.i=@nutanix.com header.a=rsa-sha256
header.s=proofpoint20171006 header.b=jQQTS7ev;
dkim-atps=neutral
Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 4Blgbk0DR8z9sTK
for ; Tue, 8 Sep 2020 06:58:10 +1000 (AEST)
Received: from localhost (localhost [127.0.0.1])
by silver.osuosl.org (Postfix) with ESMTP id 009E223115;
Mon, 7 Sep 2020 20:58:04 +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 C59HTcvGvW7k; Mon, 7 Sep 2020 20:57:45 +0000 (UTC)
Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])
by silver.osuosl.org (Postfix) with ESMTP id 73A05228B0;
Mon, 7 Sep 2020 20:57:43 +0000 (UTC)
Received: from lf-lists.osuosl.org (localhost [127.0.0.1])
by lists.linuxfoundation.org (Postfix) with ESMTP id 4FDEDC0052;
Mon, 7 Sep 2020 20:57:43 +0000 (UTC)
X-Original-To: ovs-dev@openvswitch.org
Delivered-To: ovs-dev@lists.linuxfoundation.org
Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])
by lists.linuxfoundation.org (Postfix) with ESMTP id 68839C0052
for ; Mon, 7 Sep 2020 20:57:41 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
by whitealder.osuosl.org (Postfix) with ESMTP id 517C98620B
for ; Mon, 7 Sep 2020 20:57:41 +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 WZ5Yy-iMD4-f for ;
Mon, 7 Sep 2020 20:57:40 +0000 (UTC)
X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6
Received: from mx0b-002c1b01.pphosted.com (mx0b-002c1b01.pphosted.com
[148.163.155.12])
by whitealder.osuosl.org (Postfix) with ESMTPS id DF61486005
for ; Mon, 7 Sep 2020 20:57:39 +0000 (UTC)
Received: from pps.filterd (m0127841.ppops.net [127.0.0.1])
by mx0b-002c1b01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id
087KsugZ010092
for ; Mon, 7 Sep 2020 13:57:38 -0700
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com;
h=from : to : cc :
subject : date : message-id : in-reply-to : references : content-type :
mime-version; s=proofpoint20171006;
bh=NrGsLoO+OS4j+q44yEJ6+W6rMG3q5hkBh891DkmOZ+o=;
b=jQQTS7evDaNLHhAnF7b4lDw1is6InQnQrEz+mq9rlDNCPU2BE4HzWwzPA5lSQaYoMvGd
oV5ZLVznASFFoQFz9O+q2yp97CnuwVryW5WaRSbfgWY0yqSfJe5KzM0eN24KbpTD8Vo9
d/4LWHdJO1aggCaOlpjyIhfFjAntROmnmSI3X3cBN7+PMpo7e/5uwTi1tZQmxEVibkKS
p/rlboKefFfQ2nsIafXxbEceaMoWB2vRJnVp/YUjKbsRULfbZKXB7ksYalABTmEJ9dmn
UAjaV8COrvPLSQ5jzHg/dJk9hJm+XfDjYRM/JsLsMRebOVh6L7+HqTASArYK2OoaEkR9 QQ==
Received: from nam11-co1-obe.outbound.protection.outlook.com
(mail-co1nam11lp2169.outbound.protection.outlook.com [104.47.56.169])
by mx0b-002c1b01.pphosted.com with ESMTP id 33c879v3f1-2
(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT)
for ; Mon, 07 Sep 2020 13:57:38 -0700
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
b=nQBgGImB0b7sfHG44334F0H71IUq0rRaLfq0Y2z3SxoKLaxj9UQwO0UQEZIwV3mdQf4S34SciHyja5x/cAVnSf+Q6AHoqhOxwzOSmvyYZRGIUQ3LkcekHiidwdctkv+PdLBMTulnsh8/Ll+RaYC3q7+I7xG3J2dgK7gPY/8Oq8Zft05QBN7iuFeVOt//I5h/Zup6YLrWSqmvW/RLyEOPh7p/wMO8ncfJw67DV5MvDI9sgKbMEvtXonHdAAo9HyqkPusfRbaAzaykbdkUCitsvMluLjZ3IcK5ZtrE1ryX07bS8Sot6i9T5eVJigNTvqZByye7iyoL4EqXpvVn5+DBag==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
s=arcselector9901;
h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
bh=NrGsLoO+OS4j+q44yEJ6+W6rMG3q5hkBh891DkmOZ+o=;
b=MmDcpYia6ZWG/VRcAUaWWPjXXb6v5b/yQpejrm7cvkYzhD+e27myufXagVUKf5nn4KmIkpBqwxkzwVCDbEtAUFXGs/+0REquFTBWh/YcMzRePGmNBxFyS89j6+Mh0VXxlF5IoWNKz+pAjmeQtVj6DKGxD/mscoHWOytEbTBEyrOeL7CCnkG1HBdgsjXaexSN/jKZW3LdlXoftfKtsCr/i6YGTr8bCu57p4jNKPMzLdyzP8qdYIRn1cnvW06rUz8PJFSwkUqOYwy5kzYcPY1REpYlVw3+J40oAUMYT7h7pF0Fts2p0AQ69pDvGWgSUmLBbNH+motk113EAN1WgIWB/A==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
smtp.mailfrom=nutanix.com; dmarc=pass action=none header.from=nutanix.com;
dkim=pass header.d=nutanix.com; arc=none
Authentication-Results: openvswitch.org; dkim=none (message not signed)
header.d=none;openvswitch.org; dmarc=none action=none
header.from=nutanix.com;
Received: from BY5PR02MB6881.namprd02.prod.outlook.com (2603:10b6:a03:21d::10)
by BY5PR02MB6706.namprd02.prod.outlook.com (2603:10b6:a03:208::22)
with Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3348.15; Mon, 7 Sep
2020 20:57:36 +0000
Received: from BY5PR02MB6881.namprd02.prod.outlook.com
([fe80::bce2:ddd2:1359:8bb0]) by BY5PR02MB6881.namprd02.prod.outlook.com
([fe80::bce2:ddd2:1359:8bb0%8]) with mapi id 15.20.3348.019; Mon, 7 Sep 2020
20:57:36 +0000
From: Ankur Sharma
To: ovs-dev@openvswitch.org
Date: Mon, 7 Sep 2020 13:56:44 -0700
Message-Id: <1599512205-11041-2-git-send-email-svc.mail.git@nutanix.com>
X-Mailer: git-send-email 1.8.3.1
In-Reply-To: <1599512205-11041-1-git-send-email-svc.mail.git@nutanix.com>
References: <1599512205-11041-1-git-send-email-svc.mail.git@nutanix.com>
X-ClientProxiedBy: BYAPR07CA0102.namprd07.prod.outlook.com
(2603:10b6:a03:12b::43) To BY5PR02MB6881.namprd02.prod.outlook.com
(2603:10b6:a03:21d::10)
MIME-Version: 1.0
X-MS-Exchange-MessageSentRepresentingType: 1
Received: from northd.localdomain (192.146.154.98) by
BYAPR07CA0102.namprd07.prod.outlook.com (2603:10b6:a03:12b::43) with
Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3348.15 via Frontend
Transport; Mon, 7 Sep 2020 20:57:36 +0000
X-Mailer: git-send-email 1.8.3.1
X-Originating-IP: [192.146.154.98]
X-MS-PublicTrafficType: Email
X-MS-Office365-Filtering-Correlation-Id: 423fba7f-838a-44d3-8b74-08d85370a673
X-MS-TrafficTypeDiagnostic: BY5PR02MB6706:
X-MS-Exchange-Transport-Forked: True
X-Microsoft-Antispam-PRVS:
x-proofpoint-crosstenant: true
X-MS-Oob-TLC-OOBClassifiers: OLM:595;
X-MS-Exchange-SenderADCheck: 1
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info:
bvvTAe8hmDDHwBB8VB/JIEmHRiykal1M89CnVoaAMYe9P+Rf/zHPNSw8hbHmQ6slM0dWFS2X2gchDE3Xo08unC9mJ42fZYBhC1UJKMAIpc0PrN8/d3+tySHGnmQn0gCH+Z9tBaflbdTR+m0EUUFB5ZHkbP5XYk171g5ugnj5PFOnzE/LgvSzlEo3rc9T9Ht2uof+BduXnKe4O69VwSq2WCBCBEh/k2G5ZgTMZul2MH/Fd1oeZJih1nBIF6rNFcL20asvS9wfIR5ZQ8m9v77JURMmyye8jW7Hk1fnYJBXdPFcdezXzO5Sj4qVbwNYsueskGBIuzHk7CVrc+cyZaO/ag==
X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;
IPV:NLI; SFV:NSPM; H:BY5PR02MB6881.namprd02.prod.outlook.com; PTR:; CAT:NONE;
SFS:(39860400002)(136003)(366004)(396003)(346002)(376002)(52116002)(36756003)(26005)(6506007)(478600001)(5660300002)(4326008)(316002)(186003)(6666004)(16526019)(30864003)(6916009)(66476007)(66946007)(107886003)(2616005)(956004)(2906002)(8936002)(66556008)(8676002)(83380400001)(6486002)(6512007)(86362001)(66574015);
DIR:OUT; SFP:1102;
X-MS-Exchange-AntiSpam-MessageData:
6V7eDvdvldGq+nkWCgPy/pxFipFCw9lzyVQl1mC4VPoXLvFlL1ndyMp86zOAvN6oO6YqF0Fps91c1TLdryQKPIPRF9OCk1a/Tqa5Rjzpo1A+8YKDQvvjeZopTtjErGf46F/DXeZtdm/K2D/uXGFl+2xwrWRZRZWjpuYNrT+MhLPg2KIp62B+HH+03SBqNthfX53p/tHjIX2TpSyk+7JsBATKxJGpXFsBd1dQFGUOG/wqi1tsvs3ojzNy7BjDNl4yxRZE14zXqMC1yhEgkJmPPfds7TWLs9SVzTzEzkP5YkJXv6nSfcXdzhMzdaxUiBLMowW51UjvUqaiSH4eQsfpnzplf0vCWDIx1FcRNNs4o+c2OvLzWeVYNJ65V+YCKkt9mUDAWB+F22QWS/mRVwbMRFmAXZnz4GBjHodPtnlp8o9RCBda4FTHCWT631IOFvX+q+/Mhm5RtpFbE47jb15RYPSdHxcNFg8cjmZMsa3gnrR8wuqb56iftg8BM7e0+IJ0cFB9xFH30V3ODLLsYbfp1esdWWGqOq9pW6UiyBxPl5fTnGlj8oR8tdrLqSzjFAdW9WkbuP4+MMWxBAODuIfIhQQgvWiHSWu3e26XmYl2VbT4yWO39YPpItBam4BnAPmvMnBqu0tDiDE2K0J8+Rg3Gg==
X-OriginatorOrg: nutanix.com
X-MS-Exchange-CrossTenant-Network-Message-Id:
423fba7f-838a-44d3-8b74-08d85370a673
X-MS-Exchange-CrossTenant-AuthSource: BY5PR02MB6881.namprd02.prod.outlook.com
X-MS-Exchange-CrossTenant-AuthAs: Internal
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Sep 2020 20:57:36.8381 (UTC)
X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted
X-MS-Exchange-CrossTenant-Id: bb047546-786f-4de1-bd75-24e5b6f79043
X-MS-Exchange-CrossTenant-MailboxType: HOSTED
X-MS-Exchange-CrossTenant-UserPrincipalName:
l86M7PwOwG1IGiI0qI0oSlYSw6k0ktHejIslzznxha5cmKmZNvQRmTGp6pOT3Q8yXXL3UwUFHt75mBApDXqzSEpmPiHTjuVQqWiH2vvYt+0=
X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR02MB6706
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.235, 18.0.687
definitions=2020-09-07_11:2020-09-07,
2020-09-07 signatures=0
X-Proofpoint-Spam-Reason: safe
Subject: [ovs-dev] [PATCH v6 1/2 ovn] External IP based NAT: Add Columns and
CLI
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"
From: Ankur Sharma
This patch adds following columns to NAT table.
a. allowed_ext_ips:
Represents Address Set of External IPs for which
a NAT rule is applicable.
b. exempted_ext_ips:
Represents Address Set of External IPs for which
a NAT rule is NOT applicable.
Additionally, patch adds nbctl cli to set these column values.
ovn-nbctl [--is-exempted] lr-nat-update-ext-ip
Signed-off-by: Ankur Sharma
---
ovn-nb.ovsschema | 14 +++++-
ovn-nb.xml | 48 +++++++++++++++++++++
tests/ovn-nbctl.at | 44 ++++++++++++++++++-
utilities/ovn-nbctl.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 218 insertions(+), 4 deletions(-)
diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
index 0c939b7..62abf15 100644
--- a/ovn-nb.ovsschema
+++ b/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
{
"name": "OVN_Northbound",
- "version": "5.25.0",
- "cksum": "1354137211 26116",
+ "version": "5.26.0",
+ "cksum": "1072595492 26575",
"tables": {
"NB_Global": {
"columns": {
@@ -403,6 +403,16 @@
"snat",
"dnat_and_snat"
]]}}},
+ "allowed_ext_ips": {"type": {
+ "key": {"type": "uuid", "refTable": "Address_Set",
+ "refType": "strong"},
+ "min": 0,
+ "max": 1}},
+ "exempted_ext_ips": {"type": {
+ "key": {"type": "uuid", "refTable": "Address_Set",
+ "refType": "strong"},
+ "min": 0,
+ "max": 1}},
"options": {"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"external_ids": {
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 1f2dbb9..09beae9 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -2716,6 +2716,54 @@
+
+ It represents Address Set of external ips that NAT rule is applicable to.
+ For SNAT type NAT rules, this refers to destination addresses.
+ For DNAT type NAT rules, this refers to source addresses.
+
+
+ This configuration overrides the default NAT behavior of applying a
+ rule solely based on internal IP. Without this configuration, NAT
+ happens without considering the external IP (i.e dest/source for
+ snat/dnat type rule). With this configuration NAT rule is applied
+ ONLY if external ip is in the input Address Set.
+
+
+
+
+ It represents Address Set of external ips that NAT rule is NOT
+ applicable to.
+ For SNAT type NAT rules, this refers to destination addresses.
+ For DNAT type NAT rules, this refers to source addresses.
+
+
+ This configuration overrides the default NAT behavior of applying a
+ rule solely based on internal IP. Without this configuration, NAT
+ happens without considering the external IP (i.e dest/source for
+ snat/dnat type rule). With this configuration NAT rule is NOT applied
+ if external ip is in the input Address Set.
+
+
+
+ If there are NAT rules in a logical router with overlapping IP prefixes
+ (including /32), then usage of exempted_ext_ips should be
+ avoided in following scenario.
+ a. SNAT rule (let us say RULE1) with logical_ip PREFIX/MASK
+ (let us say 50.0.0.0/24).
+ b. SNAT rule (let us say RULE2) with logical_ip PREFIX/MASK+1
+ (let us say 50.0.0.0/25).
+ c. Now, if exempted_ext_ips is associated with RULE2, then a logical
+ ip which matches both 50.0.0.0/24 and 50.0.0.0/25 may get the RULE2
+ applied to it instead of RULE1.
+
+
+
+ allowed_ext_ips and exempted_ext_ips are mutually
+ exclusive to each other. If both Address Sets are set for a rule,
+ then the NAT rule is not considered.
+
+
+
Indicates if a dnat_and_snat rule should lead to connection
tracking state or not.
diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
index 619051d..baf7a87 100644
--- a/tests/ovn-nbctl.at
+++ b/tests/ovn-nbctl.at
@@ -685,7 +685,49 @@ snat 40.0.0.3 21-65535 192.168.1.6
AT_CHECK([ovn-nbctl lr-nat-del lr0])
AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [])
AT_CHECK([ovn-nbctl lr-nat-del lr0])
-AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])])
+AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
+
+AT_CHECK([ovn-nbctl lr-nat-del lr0])
+
+ovn-nbctl create Address_Set name=allowed_range addresses=\"1.1.1.1\"
+ovn-nbctl create Address_Set name=disallowed_range addresses=\"2.2.2.2\"
+AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 40.0.0.3 192.168.1.6])
+AT_CHECK([ovn-nbctl lr-nat-update-ext-ip lr0 snat 192.168.1.6 allowed_range])
+AT_CHECK([ovn-nbctl --is-exempted lr-nat-update-ext-ip lr0 snat 192.168.1.6 disallowed_range])
+AT_CHECK([ovn-nbctl lr-nat-update-ext-ip lr0 snat 192.168.1.6 allowed_range_tmp], [1], [],
+[ovn-nbctl: allowed_range_tmp: Address Set name not found
+])
+AT_CHECK([ovn-nbctl --is-exempted lr-nat-update-ext-ip lr0 snat 192.168.1.6 disallowed_range_tmp], [1], [],
+[ovn-nbctl: disallowed_range_tmp: Address Set name not found
+])
+
+AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 40.0.0.4 192.168.1.7])
+AT_CHECK([ovn-nbctl lr-nat-update-ext-ip lr0 dnat 40.0.0.4 allowed_range])
+AT_CHECK([ovn-nbctl --is-exempted lr-nat-update-ext-ip lr0 dnat 40.0.0.4 disallowed_range])
+AT_CHECK([ovn-nbctl lr-nat-update-ext-ip lr0 dnat 40.0.0.4 allowed_range_tmp], [1], [],
+[ovn-nbctl: allowed_range_tmp: Address Set name not found
+])
+AT_CHECK([ovn-nbctl --is-exempted lr-nat-update-ext-ip lr0 dnat 40.0.0.4 disallowed_range_tmp], [1], [],
+[ovn-nbctl: disallowed_range_tmp: Address Set name not found
+])
+
+AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 40.0.0.5 192.168.1.8])
+AT_CHECK([ovn-nbctl lr-nat-update-ext-ip lr0 dnat_and_snat 40.0.0.5 allowed_range])
+AT_CHECK([ovn-nbctl --is-exempted lr-nat-update-ext-ip lr0 dnat 40.0.0.4 disallowed_range])
+AT_CHECK([ovn-nbctl lr-nat-update-ext-ip lr0 dnat 40.0.0.4 allowed_range_tmp], [1], [],
+[ovn-nbctl: allowed_range_tmp: Address Set name not found
+])
+AT_CHECK([ovn-nbctl --is-exempted lr-nat-update-ext-ip lr0 dnat 40.0.0.4 disallowed_range_tmp], [1], [],
+[ovn-nbctl: disallowed_range_tmp: Address Set name not found
+])
+AT_CHECK([ovn-nbctl lr-nat-update-ext-ip lr0 snat 192.168.1.6], [1], [],
+[ovn-nbctl: 'lr-nat-update-ext-ip' command requires at least 4 arguments
+])
+AT_CHECK([ovn-nbctl lr-nat-update-ext-ip lr0 snat 192.168.16 allowed_range], [1], [],
+[ovn-nbctl: 192.168.16: Invalid IP address or CIDR
+])
+
+AT_CHECK([ovn-nbctl lr-nat-del lr0])])
dnl ---------------------------------------------------------------------
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index 542cbf7..42dcad7 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -839,6 +839,46 @@ lr_by_name_or_uuid(struct ctl_context *ctx, const char *id,
return NULL;
}
+/* Find an Address Set given its id. */
+static char * OVS_WARN_UNUSED_RESULT
+address_set_by_name_or_uuid(struct ctl_context *ctx,
+ const char *id, bool must_exist,
+ const struct nbrec_address_set **addr_set_p)
+{
+ const struct nbrec_address_set *addr_set = NULL;
+ bool is_uuid = false;
+ struct uuid addr_set_uuid;
+
+ *addr_set_p = NULL;
+ if (uuid_from_string(&addr_set_uuid, id)) {
+ is_uuid = true;
+ addr_set = nbrec_address_set_get_for_uuid(ctx->idl, &addr_set_uuid);
+ }
+
+ if (!addr_set) {
+ const struct nbrec_address_set *iter;
+
+ NBREC_ADDRESS_SET_FOR_EACH(iter, ctx->idl) {
+ if (strcmp(iter->name, id)) {
+ continue;
+ }
+ if (addr_set) {
+ return xasprintf("Multiple Address Sets named '%s'. "
+ "Use a UUID.", id);
+ }
+ addr_set = iter;
+ }
+ }
+
+ if (!addr_set && must_exist) {
+ return xasprintf("%s: Address Set %s not found",
+ id, is_uuid ? "UUID" : "name");
+ }
+
+ *addr_set_p = addr_set;
+ return NULL;
+}
+
static char * OVS_WARN_UNUSED_RESULT
ls_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist,
const struct nbrec_logical_switch **ls_p)
@@ -4486,6 +4526,79 @@ nbctl_lr_nat_list(struct ctl_context *ctx)
smap_destroy(&lr_nats);
}
+static void
+nbctl_lr_nat_set_ext_ips(struct ctl_context *ctx)
+{
+ const struct nbrec_logical_router *lr = NULL;
+ const struct nbrec_address_set *addr_set = NULL;
+ bool is_exempted = shash_find(&ctx->options, "--is-exempted");
+ bool nat_found = false;
+
+ if (ctx->argc < 5) {
+ ctl_error(ctx, "Incomplete input, Required arguments are: "
+ "ROUTER TYPE IP ADDRESS_SET");
+ return;
+ }
+
+ char *error = lr_by_name_or_uuid(ctx, ctx->argv[1], true, &lr);
+ if (error) {
+ ctx->error = error;
+ return;
+ }
+
+ const char *nat_type = ctx->argv[2];
+ if (strcmp(nat_type, "dnat") && strcmp(nat_type, "snat")
+ && strcmp(nat_type, "dnat_and_snat")) {
+ ctl_error(ctx, "%s: type must be one of \"dnat\", \"snat\" and "
+ "\"dnat_and_snat\".", nat_type);
+ return;
+ }
+
+ error = address_set_by_name_or_uuid(ctx, ctx->argv[4], true, &addr_set);
+ if (error) {
+ ctx->error = error;
+ return;
+ }
+
+ char *nat_ip = normalize_prefix_str(ctx->argv[3]);
+ if (!nat_ip) {
+ ctl_error(ctx, "%s: Invalid IP address or CIDR", ctx->argv[3]);
+ return;
+ }
+
+ int is_snat = !strcmp("snat", nat_type);
+
+ /* Update the matching NAT. */
+ for (size_t i = 0; i < lr->n_nat; i++) {
+ struct nbrec_nat *nat = lr->nat[i];
+ char *old_ip = normalize_prefix_str(is_snat
+ ? nat->logical_ip
+ : nat->external_ip);
+
+ if (!old_ip) {
+ continue;
+ }
+
+ if (!strcmp(nat_type, nat->type) && !strcmp(nat_ip, old_ip)) {
+ nat_found = true;
+ nbrec_logical_router_verify_nat(lr);
+ if (is_exempted) {
+ nbrec_nat_set_exempted_ext_ips(nat, addr_set);
+ } else {
+ nbrec_nat_set_allowed_ext_ips(nat, addr_set);
+ }
+ return;
+ }
+ }
+
+ if (!nat_found) {
+ ctl_error(ctx, "%s: Could not locate nat rule for: %s.",
+ nat_type, nat_ip);
+ }
+
+ free(nat_ip);
+}
+
static char * OVS_WARN_UNUSED_RESULT
lrp_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist,
@@ -6402,7 +6515,8 @@ static const struct ctl_command_syntax nbctl_commands[] = {
{ "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 },
-
+ { "lr-nat-update-ext-ip", 4, 4, "ROUTER TYPE IP ADDRESS_SET", NULL,
+ nbctl_lr_nat_set_ext_ips, NULL, "--is-exempted", RW},
/* load balancer commands. */
{ "lb-add", 3, 4, "LB VIP[:PORT] IP[:PORT]... [PROTOCOL]", NULL,
nbctl_lb_add, NULL, "--may-exist,--add-duplicate", RW },