From patchwork Mon Sep 7 20:56:45 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Ankur Sharma
X-Patchwork-Id: 1359258
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=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=tNCI61jE;
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 4BlgbY0fwDz9sR4
for ; Tue, 8 Sep 2020 06:58:01 +1000 (AEST)
Received: from localhost (localhost [127.0.0.1])
by whitealder.osuosl.org (Postfix) with ESMTP id 4BA398636A;
Mon, 7 Sep 2020 20:57:59 +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 LmW4k0E-wGep; Mon, 7 Sep 2020 20:57:46 +0000 (UTC)
Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])
by whitealder.osuosl.org (Postfix) with ESMTP id 35591866FA;
Mon, 7 Sep 2020 20:57:44 +0000 (UTC)
Received: from lf-lists.osuosl.org (localhost [127.0.0.1])
by lists.linuxfoundation.org (Postfix) with ESMTP id 07EF2C0893;
Mon, 7 Sep 2020 20:57:44 +0000 (UTC)
X-Original-To: ovs-dev@openvswitch.org
Delivered-To: ovs-dev@lists.linuxfoundation.org
Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])
by lists.linuxfoundation.org (Postfix) with ESMTP id C0382C0051
for ; Mon, 7 Sep 2020 20:57:42 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
by fraxinus.osuosl.org (Postfix) with ESMTP id AD8B5861AA
for ; Mon, 7 Sep 2020 20:57:42 +0000 (UTC)
X-Virus-Scanned: amavisd-new at osuosl.org
Received: from fraxinus.osuosl.org ([127.0.0.1])
by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id WsjsCFNgdWvL for ;
Mon, 7 Sep 2020 20:57:41 +0000 (UTC)
X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6
Received: from mx0a-002c1b01.pphosted.com (mx0a-002c1b01.pphosted.com
[148.163.151.68])
by fraxinus.osuosl.org (Postfix) with ESMTPS id 306D085F56
for ; Mon, 7 Sep 2020 20:57:41 +0000 (UTC)
Received: from pps.filterd (m0127837.ppops.net [127.0.0.1])
by mx0a-002c1b01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id
087KqIUO024983
for ; Mon, 7 Sep 2020 13:57:40 -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=NYuK3k0j+CVT9np2ymG7Nuvi9TqaoRSe/Iqq+QjN9Zw=;
b=tNCI61jEamexuY2MF62cjnAQaDV882TNtcReHGcXNkxBUEEytmAbIOX0gWCLUZDd8gh6
T7aCFBiUOd0c2faz+b9cITgaO5ezHCoMtzzYebr1L4svyVpraXbcFIVVg6aBVaLfa6yZ
YioeQywED2DYZNsD6S3tT2jqBRXnfZWSNMJVFD7gM6X7GeOMRw92kpBIxLYFMI5iBWKd
95EvXIjttdlUESEguWS1nIQ/Q8S2vsbe0r+76Q3b3ll+F8WhTKtY5RQ9oNaszBbyRBe2
ozwz//P1E0xfi9+dpTtX8VC82TjjCnHNQ5P2QwNecU6Rr67FuDwcLAESD4vgewLd3/39 XA==
Received: from nam11-co1-obe.outbound.protection.outlook.com
(mail-co1nam11lp2174.outbound.protection.outlook.com [104.47.56.174])
by mx0a-002c1b01.pphosted.com with ESMTP id 33c6k9m98b-1
(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT)
for ; Mon, 07 Sep 2020 13:57:40 -0700
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
b=EezJDW0dcIQQdvLrrwPzrxaDAhOE6U64nRpcqNwjHBGfnuVG2POTZCB4mi3dPNBgZOtDuk85459o8/ZDIj651XdmbLlikkZR7UFF1OMcoGp9gFNKd69OoOmdWOyvyCy0JEfAhU2POTHIE8GaN19Ioo15DbkewU1tR4K86r7/LFg2U904ylKh2oZSNpU4/TuU93xUmPSDUgyNiE80Q2GF8POmD7ecIAduKve/kLkrNeqY3Po/Hy7C7Pg6uiPl2FEG0vZ/aR4eWvxCETNpkGXk6TcPOtdaNmAHa9PsT0UPAtLGS0lwdpZ+aymxXIUTc2lXKNUMbuBDylDhzq2ozbOGAw==
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=NYuK3k0j+CVT9np2ymG7Nuvi9TqaoRSe/Iqq+QjN9Zw=;
b=LF4NI30dw07+hvdHiwHDMsKAURMrP+bb+sPpodPgejMLtsqFTKQFdpy/KCXfDNZG5CeVRvdoWzcvDkImC5crqbcnvXqPuYnkDcIKag29YK3AsqUnPCoWINedPCnywUHXeapPskAtpgsWNMqKirBgJ7uZhrp6WIb/jKvzYNHvBOnU7BqdBhmoxWi2SVNVVpBOdNMjfjI/a8uIs7R1iUyox3s0wVg1DwQd7fE2cgoKiFFh0GG2TUiYddTv0YDNmTO9vyDzDt2qSgpnkODAGcuaxo+Epzpwe3GnyL9fdywTxWNvfsvsFirL+THXdU0U8serYs0wI+wAtZ9jyr1Ws6G1ug==
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:39 +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:39 +0000
From: Ankur Sharma
To: ovs-dev@openvswitch.org
Date: Mon, 7 Sep 2020 13:56:45 -0700
Message-Id: <1599512205-11041-3-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:38 +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: 0b48d5bf-8f4b-4948-9ce2-08d85370a7d4
X-MS-TrafficTypeDiagnostic: BY5PR02MB6706:
X-MS-Exchange-Transport-Forked: True
X-Microsoft-Antispam-PRVS:
x-proofpoint-crosstenant: true
X-MS-Oob-TLC-OOBClassifiers: OLM:1201;
X-MS-Exchange-SenderADCheck: 1
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info:
6ASBvyJpxMsYIS1VQWCpHUxD2t+/m/FdBRP9M2LaLyyl0Oh98zoT0RQbEZtXk3Lbo75z3vInmaYNm1IZaxi0/sm4Y/rO9Lgtr8enVanWKFiyS+fPPrXUbtjBdCIZQZ056wPKTxfeEccmcaShlxSpHXSYCg5M73ZYqHZdl4RRbPSecC9yDIBd03WrtzFhBgKPwtJ3YSP/sdOLEx/iTsQJXJbfxxv1QNfcRrF1GkaOLwd52qL7ERMakC1EwmrNDaLAYL6bWiJmhxgdYHPxhk5rS52hod9MUqy6VgwtCqNXHmaxp0AWnNLUzbz1VyIYQHRQ
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:
EQ05WGSWq68lw1PvQltsT+xw3ftWAyvh1ypX9OoQND4WqaD/hl8UwDqAl7ZcmGLlWI2q7G5Q7o+TeaQ3/Ie/92WOONeEsfFPcLKTi77KJQmu4va+pKhn9MkJ/iX1YizbxLnG4xUbditG+JvZTwyFtLZbZIMM6+JOquE6ObXZHKLizk2UzZJAKpa6XU8V6t2CKhlnIC9z5ghc2SjobzkqFRCajq3FFxZT4Lz0iy4oUT7oIn6EYmA0YrFjkPXf0Kynx6ph/BmxOXsGVlmiHk5ebWAarc/wJeykmfOe+f45EcL32RJAVAuCe4IbXgSNLctICf6JPkFjHZRzPe2/+0jTj4pGkdXorRHDeYC6LsMzjTInUZu94N4TS5pULdJvn5Uq7Mc3M1G+EFgNFFZA0eLTsT3pVTO1paa0OP2y/mlKk3MYlpyRrsnGwhbedMwRG2gkF5H1vHz9p+lUHbzaGBs3OkGUcRebi9PJQ0IM5dz53pIaCcLzCgaigA1pw52B2oFmzySgoeJa4x/8Jc4Z5rV9vJp5G5wv4Lq0rDS/IDjeQFlyTEjTt62drA943ygIYxnidjeu4Amtuq/hvVdTo7/iCPkwMSwW1rRW7W4qDbdOgWiuXgmJcn2xXMv7q4EFer2s8gTkMG8WM3fZmNCrn06G6w==
X-OriginatorOrg: nutanix.com
X-MS-Exchange-CrossTenant-Network-Message-Id:
0b48d5bf-8f4b-4948-9ce2-08d85370a7d4
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:39.1311 (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:
taTyOicNyvUkhUQQIiG2lXyurXuBcmRVTtm8wrAln4qfFIzTDe73Wg1qAElMlWyjGNwjcNbPXShtsqO2AViu0m8hNss4kEcMbS93JZ8UkJE=
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 2/2 ovn] External IP based NAT: NORTHD changes
to use allowed/exempted external ip
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 has northd changes which consumes allowed/exempted external ip
configuration per NAT rule in logical flow.
Allowed external ip range adds an additional match criteria in
snat/dnat logical flow rules.
For example, if an allowed_external_ip address set ("abcd")
is configured for following NAT rule.
TYPE EXTERNAL_IP LOGICAL_IP
snat 10.15.24.135 50.0.0.10
Then logical flow will look like following:
..(lr_out_snat)...match=(ip && .... && ip4.dst == $abcd), action=(ct_snat(...);)
Exempted external ip range adds an additional flow at priority+1
to bypass the NAT pipeline if external ip is in extempted external
ip address set.
For example, if the same NAT rule mentioned aboe has an
exempted_external_ip address set ("efgh"), then
logical flow will look like following:
..(lr_out_snat), priority=162...match=(ip && .... && ip4.dst == $efgh), action=(next;)
..(lr_out_snat), priority=161...match=(ip && ....), action=(ct_snat(10.15.24.135);)
Signed-off-by: Ankur Sharma
---
northd/ovn-northd.8.xml | 67 +++++++++++++++
northd/ovn-northd.c | 102 +++++++++++++++++++++++
tests/ovn-northd.at | 210 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 379 insertions(+)
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index 989e364..d15245a 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -2471,6 +2471,23 @@ icmp6 {
dnat_and_snat and has stateless=true
in the
options, then the action would be ip4/6.dst=
(B)
.
+
+
+ If the NAT rule has allowed_ext_ips
configured, then
+ there is an additional match ip4.src == allowed_ext_ips
+
. Similarly, for IPV6, match would be ip6.src ==
+ allowed_ext_ips
.
+
+
+
+ If the NAT rule has exempted_ext_ips
set, then
+ there is an additional flow configured at priority 101.
+ The flow matches if source ip is an exempted_ext_ip
+ and the action is next;
. This flow is used to
+ bypass the ct_dnat action for a packet originating from
+ exempted_ext_ips
.
+
+
@@ -2516,6 +2533,22 @@ icmp6 {
+ If the NAT rule has allowed_ext_ips
configured, then
+ there is an additional match ip4.src == allowed_ext_ips
+
. Similarly, for IPV6, match would be ip6.src ==
+ allowed_ext_ips
.
+
+
+
+ If the NAT rule has exempted_ext_ips
set, then
+ there is an additional flow configured at priority 101.
+ The flow matches if source ip is an exempted_ext_ip
+ and the action is next;
. This flow is used to
+ bypass the ct_dnat action for a packet originating from
+ exempted_ext_ips
.
+
+
+
A priority-0 logical flow with match 1
has actions
next;
.
@@ -3301,6 +3334,23 @@ nd_ns {
options, then the action would be ip4/6.src=
(B)
.
+
+
+ If the NAT rule has allowed_ext_ips
configured, then
+ there is an additional match ip4.dst == allowed_ext_ips
+
. Similarly, for IPV6, match would be ip6.dst ==
+ allowed_ext_ips
.
+
+
+
+ If the NAT rule has exempted_ext_ips
set, then
+ there is an additional flow configured at the priority + 1 of
+ corresponding NAT rule. The flow matches if destination ip
+ is an exempted_ext_ip
and the action is next;
+
. This flow is used to bypass the ct_snat action for a packet
+ which is destinted to exempted_ext_ips
.
+
+
A priority-0 logical flow with match 1
has actions
next;
.
@@ -3343,6 +3393,23 @@ nd_ns {
A in the NAT rule. This allows upstream MAC
learning to point to the correct chassis.
+
+
+ If the NAT rule has allowed_ext_ips
configured, then
+ there is an additional match ip4.dst == allowed_ext_ips
+
. Similarly, for IPV6, match would be ip6.dst ==
+ allowed_ext_ips
.
+
+
+
+ If the NAT rule has exempted_ext_ips
set, then
+ there is an additional flow configured at the priority + 1 of
+ corresponding NAT rule. The flow matches if destination ip
+ is an exempted_ext_ip
and the action is next;
+
. This flow is used to bypass the ct_snat action for a flow
+ which is destinted to exempted_ext_ips
.
+
+
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 3de7161..8cfeb3a 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -8282,6 +8282,76 @@ lrouter_nat_is_stateless(const struct nbrec_nat *nat)
return false;
}
+/* Handles the match criteria and actions in logical flow
+ * based on external ip based NAT rule filter.
+ *
+ * For ALLOWED_EXT_IPs, we will add an additional match criteria
+ * of comparing ip*.src/dst with the allowed external ip address set.
+ *
+ * For EXEMPTED_EXT_IPs, we will have an additional logical flow
+ * where we compare ip*.src/dst with the exempted external ip address set
+ * and action says "next" instead of ct*.
+ */
+static inline void
+lrouter_nat_add_ext_ip_match(struct ovn_datapath *od,
+ struct hmap *lflows, struct ds *match,
+ const struct nbrec_nat *nat,
+ bool is_v6, bool is_src, ovs_be32 mask)
+{
+ struct nbrec_address_set *allowed_ext_ips = nat->allowed_ext_ips;
+ struct nbrec_address_set *exempted_ext_ips = nat->exempted_ext_ips;
+ bool is_gw_router = !od->l3dgw_port;
+
+ ovs_assert(allowed_ext_ips || exempted_ext_ips);
+
+ if (allowed_ext_ips) {
+ ds_put_format(match, " && ip%s.%s == $%s",
+ is_v6 ? "6" : "4",
+ is_src ? "src" : "dst",
+ allowed_ext_ips->name);
+ } else if (exempted_ext_ips) {
+ struct ds match_exempt = DS_EMPTY_INITIALIZER;
+ enum ovn_stage stage = is_src ? S_ROUTER_IN_DNAT : S_ROUTER_OUT_SNAT;
+ uint16_t priority;
+
+ /* Priority of logical flows corresponding to exempted_ext_ips is
+ * +1 of the corresponding regulr NAT rule.
+ * For example, if we have following NAT rule and we associate
+ * exempted external ips to it:
+ * "ovn-nbctl lr-nat-add router dnat_and_snat 10.15.24.139 50.0.0.11"
+ *
+ * And now we associate exempted external ip address set to it.
+ * Now corresponding to above rule we will have following logical
+ * flows:
+ * lr_out_snat...priority=162, match=(..ip4.dst == $exempt_range),
+ * action=(next;)
+ * lr_out_snat...priority=161, match=(..), action=(ct_snat(....);)
+ *
+ */
+ if (is_src) {
+ /* S_ROUTER_IN_DNAT uses priority 100 */
+ priority = 100 + 1;
+ } else {
+ /* S_ROUTER_OUT_SNAT uses priority (mask + 1 + 128 + 1) */
+ priority = count_1bits(ntohl(mask)) + 2;
+
+ if (!is_gw_router)
+ priority += 128;
+ }
+
+ ds_clone(&match_exempt, match);
+ ds_put_format(&match_exempt, " && ip%s.%s == $%s",
+ is_v6 ? "6" : "4",
+ is_src ? "src" : "dst",
+ exempted_ext_ips->name);
+
+ ovn_lflow_add_with_hint(lflows, od, stage, priority,
+ ds_cstr(&match_exempt), "next;",
+ &nat->header_);
+ ds_destroy(&match_exempt);
+ }
+}
+
/* Builds the logical flow that replies to ARP requests for an 'ip_address'
* owned by the router. The flow is inserted in table S_ROUTER_IN_IP_INPUT
* with the given priority.
@@ -9343,6 +9413,18 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
struct in6_addr ipv6, mask_v6, v6_exact = IN6ADDR_EXACT_INIT;
bool is_v6 = false;
bool stateless = lrouter_nat_is_stateless(nat);
+ struct nbrec_address_set *allowed_ext_ips =
+ nat->allowed_ext_ips;
+ struct nbrec_address_set *exempted_ext_ips =
+ nat->exempted_ext_ips;
+
+ if (allowed_ext_ips && exempted_ext_ips) {
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+ VLOG_WARN_RL(&rl, "NAT rule: "UUID_FMT" not applied, since"
+ "both allowed and exempt external ips set",
+ UUID_ARGS(&(nat->header_.uuid)));
+ continue;
+ }
char *error = ip_parse_masked(nat->external_ip, &ip, &mask);
if (error || mask != OVS_BE32_MAX) {
@@ -9488,6 +9570,11 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
is_v6 ? "6" : "4",
nat->external_ip);
ds_clear(&actions);
+ if (allowed_ext_ips || exempted_ext_ips) {
+ lrouter_nat_add_ext_ip_match(od, lflows, &match, nat,
+ is_v6, true, mask);
+ }
+
if (dnat_force_snat_ip) {
/* Indicate to the future tables that a DNAT has taken
* place and a force SNAT needs to be done in the
@@ -9531,6 +9618,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
od->l3redirect_port->json_key);
}
ds_clear(&actions);
+ if (allowed_ext_ips || exempted_ext_ips) {
+ lrouter_nat_add_ext_ip_match(od, lflows, &match, nat,
+ is_v6, true, mask);
+ }
if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
ds_put_format(&actions, "ip%s.dst=%s; next;",
@@ -9642,6 +9733,11 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
nat->logical_ip);
ds_clear(&actions);
+ if (allowed_ext_ips || exempted_ext_ips) {
+ lrouter_nat_add_ext_ip_match(od, lflows, &match, nat,
+ is_v6, false, mask);
+ }
+
if (!strcmp(nat->type, "dnat_and_snat") && stateless) {
ds_put_format(&actions, "ip%s.src=%s; next;",
is_v6 ? "6" : "4", nat->external_ip);
@@ -9681,6 +9777,12 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
od->l3redirect_port->json_key);
}
ds_clear(&actions);
+
+ if (allowed_ext_ips || exempted_ext_ips) {
+ lrouter_nat_add_ext_ip_match(od, lflows, &match, nat,
+ is_v6, false, mask);
+ }
+
if (distributed) {
ds_put_format(&actions, "eth.src = "ETH_ADDR_FMT"; ",
ETH_ADDR_ARGS(mac));
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 8344c7f..c6d9ae11 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -1140,6 +1140,216 @@ ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1
AT_CLEANUP
+AT_SETUP([ovn -- check allowed/disallowed external dnat, snat and dnat_and_snat rules])
+ovn_start
+
+# Logical network:
+# 2 LRs - CR and DR
+# CR ==> Centralized router
+# DR ==> Distributed router
+#
+# DR is connected to S1 and CR is connected to S2
+
+ovn-sbctl chassis-add gw1 geneve 127.0.0.1
+
+ovn-nbctl lr-add DR
+ovn-nbctl lrp-add DR DR-S1 02:ac:10:01:00:01 172.16.1.1/24
+
+cr_uuid=$(ovn-nbctl create Logical_Router name=CR)
+ovn-nbctl lrp-add CR CR-S2 02:ac:10:01:00:01 172.16.1.1/24
+
+ovn-nbctl ls-add S1
+ovn-nbctl lsp-add S1 S1-DR
+ovn-nbctl lsp-set-type S1-DR router
+ovn-nbctl lsp-set-addresses S1-DR router
+ovn-nbctl --wait=sb lsp-set-options S1-DR router-port=DR-S1
+
+ovn-nbctl ls-add S2
+ovn-nbctl lsp-add S2 S2-CR
+ovn-nbctl lsp-set-type S2-CR router
+ovn-nbctl lsp-set-addresses S2-CR router
+ovn-nbctl --wait=sb lsp-set-options S2-CR router-port=CR-S2
+
+ovn-nbctl lrp-set-gateway-chassis DR-S1 gw1
+
+uuid=`ovn-sbctl --columns=_uuid --bare find Port_Binding logical_port=cr-DR-S1`
+echo "CR-LRP UUID is: " $uuid
+
+ovn-nbctl set Logical_Router $cr_uuid options:chassis=gw1
+ovn-nbctl --wait=hv sync
+
+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\"
+
+# SNAT with ALLOWED_IPs
+ovn-nbctl lr-nat-add DR snat 172.16.1.1 50.0.0.11
+ovn-nbctl lr-nat-update-ext-ip DR snat 50.0.0.11 allowed_range
+
+ovn-nbctl lr-nat-add CR snat 172.16.1.1 50.0.0.11
+ovn-nbctl lr-nat-update-ext-ip CR snat 50.0.0.11 allowed_range
+
+OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | wc -l`])
+OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | wc -l`])
+
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1
+])
+
+# SNAT with DISALLOWED_IPs
+ovn-nbctl lr-nat-del DR snat 50.0.0.11
+ovn-nbctl lr-nat-del CR snat 50.0.0.11
+
+ovn-nbctl lr-nat-add DR snat 172.16.1.1 50.0.0.11
+ovn-nbctl lr-nat-add CR snat 172.16.1.1 50.0.0.11
+
+ovn-nbctl --is-exempted lr-nat-update-ext-ip DR snat 50.0.0.11 disallowed_range
+ovn-nbctl --is-exempted lr-nat-update-ext-ip CR snat 50.0.0.11 disallowed_range
+
+ovn-sbctl dump-flows DR
+ovn-sbctl dump-flows CR
+
+OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \
+wc -l`])
+OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \
+wc -l`])
+
+ovn-nbctl show DR
+ovn-sbctl dump-flows DR
+
+ovn-nbctl show CR
+ovn-sbctl dump-flows CR
+
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "priority=161" | wc -l], [0], [1
+])
+
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "priority=33" | wc -l], [0], [1
+])
+
+# Stateful FIP with ALLOWED_IPs
+ovn-nbctl lr-nat-del DR snat 50.0.0.11
+ovn-nbctl lr-nat-del CR snat 50.0.0.11
+
+ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11
+ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11
+
+ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range
+ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range
+
+ovn-nbctl show DR
+ovn-sbctl dump-flows DR
+ovn-nbctl show CR
+ovn-sbctl dump-flows CR
+
+OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \
+wc -l`])
+OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \
+wc -l`])
+
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1
+])
+
+# Stateful FIP with DISALLOWED_IPs
+ovn-nbctl lr-nat-del DR dnat_and_snat 172.16.1.2
+ovn-nbctl lr-nat-del CR dnat_and_snat 172.16.1.2
+
+ovn-nbctl lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11
+ovn-nbctl lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11
+
+ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range
+ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range
+
+ovn-nbctl show DR
+ovn-sbctl dump-flows DR
+ovn-nbctl show CR
+ovn-sbctl dump-flows CR
+
+OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \
+wc -l`])
+OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \
+wc -l`])
+
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1
+])
+
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1
+])
+
+# Stateless FIP with DISALLOWED_IPs
+ovn-nbctl lr-nat-del DR dnat_and_snat 172.16.1.2
+ovn-nbctl lr-nat-del CR dnat_and_snat 172.16.1.2
+
+ovn-nbctl --stateless lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11
+ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11
+
+ovn-nbctl lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 allowed_range
+ovn-nbctl lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 allowed_range
+
+ovn-nbctl show DR
+ovn-sbctl dump-flows DR
+
+ovn-nbctl show CR
+ovn-sbctl dump-flows CR
+
+OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \
+wc -l`])
+OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \
+wc -l`])
+
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $allowed_range" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $allowed_range" | wc -l], [0], [1
+])
+
+# Stateful FIP with DISALLOWED_IPs
+ovn-nbctl lr-nat-del DR dnat_and_snat 172.16.1.2
+ovn-nbctl lr-nat-del CR dnat_and_snat 172.16.1.2
+
+ovn-nbctl --stateless lr-nat-add DR dnat_and_snat 172.16.1.2 50.0.0.11
+ovn-nbctl --stateless lr-nat-add CR dnat_and_snat 172.16.1.2 50.0.0.11
+
+ovn-nbctl --is-exempted lr-nat-update-ext-ip DR dnat_and_snat 172.16.1.2 disallowed_range
+ovn-nbctl --is-exempted lr-nat-update-ext-ip CR dnat_and_snat 172.16.1.2 disallowed_range
+
+ovn-nbctl show DR
+ovn-sbctl dump-flows DR
+ovn-nbctl show CR
+ovn-sbctl dump-flows CR
+
+OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows DR | grep lr_out_snat | \
+wc -l`])
+OVS_WAIT_UNTIL([test 4 = `ovn-sbctl dump-flows CR | grep lr_out_snat | \
+wc -l`])
+
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=162" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows DR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_out_snat | grep "ip4.src == 50.0.0.11" | grep "ip4.dst == $disallowed_range" | grep "priority=34" | wc -l], [0], [1
+])
+AT_CHECK([ovn-sbctl dump-flows CR | grep lr_in_dnat | grep "ip4.dst == 172.16.1.2" | grep "ip4.src == $disallowed_range" | grep "priority=101" | wc -l], [0], [1
+])
+
+AT_CLEANUP
+
AT_SETUP([ovn -- check Load balancer health check and Service Monitor sync])
AT_SKIP_IF([test $HAVE_PYTHON = no])
ovn_start