From patchwork Fri Nov 19 16:32:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Numan Siddique X-Patchwork-Id: 1557298 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=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Hwhz45ZWCz9sVc for ; Sat, 20 Nov 2021 03:32:32 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 6694761C3B; Fri, 19 Nov 2021 16:32:30 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id L6c73-9dJUT2; Fri, 19 Nov 2021 16:32:29 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id 0D98F61BEB; Fri, 19 Nov 2021 16:32:28 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id D1926C001E; Fri, 19 Nov 2021 16:32:27 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id F1AAEC0012 for ; Fri, 19 Nov 2021 16:32:25 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id DE44E40956 for ; Fri, 19 Nov 2021 16:32:25 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aTnjQ-mt-rw8 for ; Fri, 19 Nov 2021 16:32:24 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by smtp2.osuosl.org (Postfix) with ESMTPS id 14099400F3 for ; Fri, 19 Nov 2021 16:32:23 +0000 (UTC) Received: (Authenticated sender: numans@ovn.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 0551620009; Fri, 19 Nov 2021 16:32:19 +0000 (UTC) From: numans@ovn.org To: dev@openvswitch.org Date: Fri, 19 Nov 2021 11:32:08 -0500 Message-Id: <20211119163208.240670-1-numans@ovn.org> X-Mailer: git-send-email 2.33.1 MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v3 1/2] actions: Add new actions - ct_dnat_in_czone and ct_snat_in_czone. 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: Numan Siddique These actions are very similar to ct_dnat and ct_snat respectively with one difference. These new actions use the same zone id for natting. Upcoming patch will make use of these actions. Acked-by: Mark Michelson Signed-off-by: Numan Siddique --- v2 -> v3 ---- * Added Mark's Ack v1 -> v2 ---- * No changes. include/ovn/actions.h | 2 ++ include/ovn/logical-fields.h | 2 ++ lib/actions.c | 59 +++++++++++++++++++++++++----- ovn-sb.xml | 44 +++++++++++++++++++++++ tests/ovn.at | 69 ++++++++++++++++++++++++++++++++++++ utilities/ovn-trace.c | 18 ++++++++-- 6 files changed, 184 insertions(+), 10 deletions(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index f023a37b9..ede5eb93c 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -66,6 +66,8 @@ struct ovn_extend_table; OVNACT(CT_COMMIT_V2, ovnact_nest) \ OVNACT(CT_DNAT, ovnact_ct_nat) \ OVNACT(CT_SNAT, ovnact_ct_nat) \ + OVNACT(CT_DNAT_IN_CZONE, ovnact_ct_nat) \ + OVNACT(CT_SNAT_IN_CZONE, ovnact_ct_nat) \ OVNACT(CT_LB, ovnact_ct_lb) \ OVNACT(SELECT, ovnact_select) \ OVNACT(CT_CLEAR, ovnact_null) \ diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h index ef97117b9..c9675f81c 100644 --- a/include/ovn/logical-fields.h +++ b/include/ovn/logical-fields.h @@ -36,6 +36,8 @@ enum ovn_controller_event { * (32 bits). */ #define MFF_LOG_SNAT_ZONE MFF_REG12 /* conntrack snat zone for gateway router * (32 bits). */ +#define MFF_LOG_NAT_ZONE MFF_LOG_DNAT_ZONE /* conntrack zone for both snat + * and dnat. */ #define MFF_LOG_CT_ZONE MFF_REG13 /* Logical conntrack zone for lports * (32 bits). */ #define MFF_LOG_INPORT MFF_REG14 /* Logical input port (32 bits). */ diff --git a/lib/actions.c b/lib/actions.c index 7cf6be308..6b9a426ae 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -917,6 +917,20 @@ parse_CT_SNAT(struct action_context *ctx) parse_ct_nat(ctx, "ct_snat", ovnact_put_CT_SNAT(ctx->ovnacts)); } +static void +parse_CT_DNAT_IN_CZONE(struct action_context *ctx) +{ + parse_ct_nat(ctx, "ct_dnat_in_czone", + ovnact_put_CT_DNAT_IN_CZONE(ctx->ovnacts)); +} + +static void +parse_CT_SNAT_IN_CZONE(struct action_context *ctx) +{ + parse_ct_nat(ctx, "ct_snat_in_czone", + ovnact_put_CT_SNAT_IN_CZONE(ctx->ovnacts)); +} + static void format_ct_nat(const struct ovnact_ct_nat *cn, const char *name, struct ds *s) { @@ -954,21 +968,30 @@ format_CT_SNAT(const struct ovnact_ct_nat *cn, struct ds *s) format_ct_nat(cn, "ct_snat", s); } +static void +format_CT_DNAT_IN_CZONE(const struct ovnact_ct_nat *cn, struct ds *s) +{ + format_ct_nat(cn, "ct_dnat_in_czone", s); +} + +static void +format_CT_SNAT_IN_CZONE(const struct ovnact_ct_nat *cn, struct ds *s) +{ + format_ct_nat(cn, "ct_snat_in_czone", s); +} + static void encode_ct_nat(const struct ovnact_ct_nat *cn, const struct ovnact_encode_params *ep, - bool snat, struct ofpbuf *ofpacts) + bool snat, enum mf_field_id zone_src, + struct ofpbuf *ofpacts) { const size_t ct_offset = ofpacts->size; ofpbuf_pull(ofpacts, ct_offset); struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts); ct->recirc_table = cn->ltable + first_ptable(ep, ep->pipeline); - if (snat) { - ct->zone_src.field = mf_from_id(MFF_LOG_SNAT_ZONE); - } else { - ct->zone_src.field = mf_from_id(MFF_LOG_DNAT_ZONE); - } + ct->zone_src.field = mf_from_id(zone_src); ct->zone_src.ofs = 0; ct->zone_src.n_bits = 16; ct->flags = 0; @@ -1020,7 +1043,7 @@ encode_CT_DNAT(const struct ovnact_ct_nat *cn, const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { - encode_ct_nat(cn, ep, false, ofpacts); + encode_ct_nat(cn, ep, false, MFF_LOG_DNAT_ZONE, ofpacts); } static void @@ -1028,7 +1051,23 @@ encode_CT_SNAT(const struct ovnact_ct_nat *cn, const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { - encode_ct_nat(cn, ep, true, ofpacts); + encode_ct_nat(cn, ep, true, MFF_LOG_SNAT_ZONE, ofpacts); +} + +static void +encode_CT_DNAT_IN_CZONE(const struct ovnact_ct_nat *cn, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_ct_nat(cn, ep, false, MFF_LOG_NAT_ZONE, ofpacts); +} + +static void +encode_CT_SNAT_IN_CZONE(const struct ovnact_ct_nat *cn, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_ct_nat(cn, ep, true, MFF_LOG_NAT_ZONE, ofpacts); } static void @@ -4017,6 +4056,10 @@ parse_action(struct action_context *ctx) parse_CT_DNAT(ctx); } else if (lexer_match_id(ctx->lexer, "ct_snat")) { parse_CT_SNAT(ctx); + } else if (lexer_match_id(ctx->lexer, "ct_dnat_in_czone")) { + parse_CT_DNAT_IN_CZONE(ctx); + } else if (lexer_match_id(ctx->lexer, "ct_snat_in_czone")) { + parse_CT_SNAT_IN_CZONE(ctx); } else if (lexer_match_id(ctx->lexer, "ct_lb")) { parse_ct_lb_action(ctx); } else if (lexer_match_id(ctx->lexer, "ct_clear")) { diff --git a/ovn-sb.xml b/ovn-sb.xml index 150051f26..9ddacdf09 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -1383,6 +1383,50 @@

+
ct_dnat_in_czone;
+
ct_dnat_in_czone(IP);
+
+

+ ct_dnat_in_czone sends the packet through the common + NAT zone (used for both DNAT and SNAT) in connection tracking table + to unDNAT any packet that was DNATed in the opposite direction. + The packet is then automatically sent to to the next tables as if + followed by next; action. The next tables will see + the changes in the packet caused by the connection tracker. +

+

+ ct_dnat_in_czone(IP) sends the packet + through the common NAT zone to change the destination IP address + of the packet to the one provided inside the parentheses and + commits the connection. The packet is then automatically sent to + the next tables as if followed by next; action. The + next tables will see the changes in the packet caused by the + connection tracker. +

+
+ +
ct_snat_in_czone;
+
ct_snat_in_czone(IP);
+
+

+ ct_snat_in_czone sends the packet through the common + NAT zone to unSNAT any packet that was SNATed in the opposite + direction. The packet is automatically sent to the next tables as + if followed by the next; action. The next tables + will see the changes in the packet caused by the connection + tracker. +

+

+ ct_snat_in_czone(IP) sends the packet\ + through the common NAT zone to change the source IP address of + the packet to the one provided inside the parenthesis and commits + the connection. The packet is then automatically sent to the next + tables as if followed by next; action. The next + tables will see the changes in the packet caused by the connection + tracker. +

+
+
ct_clear;
Clears connection tracking state. diff --git a/tests/ovn.at b/tests/ovn.at index ae832918c..0d606b42f 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1193,6 +1193,40 @@ ct_dnat(192.168.1.2, 1000); ct_dnat(192.168.1.2, 1000-100); Syntax error at `100' range high should be greater than range low. +# ct_dnat_in_czone +ct_dnat_in_czone; + encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat) + has prereqs ip +ct_dnat_in_czone(192.168.1.2); + encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2)) + has prereqs ip +ct_dnat_in_czone(fd11::2); + encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=fd11::2)) + has prereqs ip +ct_dnat_in_czone(192.168.1.2, 1-3000); + formats as ct_dnat_in_czone(192.168.1.2,1-3000); + encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2:1-3000)) + has prereqs ip + +ct_dnat_in_czone(192.168.1.2, 192.168.1.3); + Syntax error at `192.168.1.3' expecting Integer for port range. +ct_dnat_in_czone(foo); + Syntax error at `foo' expecting IPv4 or IPv6 address. +ct_dnat_in_czone(foo, bar); + Syntax error at `foo' expecting IPv4 or IPv6 address. +ct_dnat_in_czone(); + Syntax error at `)' expecting IPv4 or IPv6 address. +ct_dnat_in_czone(192.168.1.2, foo); + Syntax error at `foo' expecting Integer for port range. +ct_dnat_in_czone(192.168.1.2, 1000-foo); + Syntax error at `foo' expecting Integer for port range. +ct_dnat_in_czone(192.168.1.2, 1000); + formats as ct_dnat_in_czone(192.168.1.2,1000); + encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2:1000)) + has prereqs ip +ct_dnat_in_czone(192.168.1.2, 1000-100); + Syntax error at `100' range high should be greater than range low. + # ct_snat ct_snat; encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat) @@ -1226,6 +1260,41 @@ ct_snat(192.168.1.2, 1000); has prereqs ip ct_snat(192.168.1.2, 1000-100); Syntax error at `100' range high should be greater than range low. + +# ct_snat_in_czone +ct_snat_in_czone; + encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat) + has prereqs ip +ct_snat_in_czone(192.168.1.2); + encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=192.168.1.2)) + has prereqs ip +ct_snat_in_czone(fd11::2); + encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=fd11::2)) + has prereqs ip +ct_snat_in_czone(192.168.1.2, 1-3000); + formats as ct_snat_in_czone(192.168.1.2,1-3000); + encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=192.168.1.2:1-3000)) + has prereqs ip + +ct_snat_in_czone(192.168.1.2, 192.168.1.3); + Syntax error at `192.168.1.3' expecting Integer for port range. +ct_snat_in_czone(foo); + Syntax error at `foo' expecting IPv4 or IPv6 address. +ct_snat_in_czone(foo, bar); + Syntax error at `foo' expecting IPv4 or IPv6 address. +ct_snat_in_czone(); + Syntax error at `)' expecting IPv4 or IPv6 address. +ct_snat_in_czone(192.168.1.2, foo); + Syntax error at `foo' expecting Integer for port range. +ct_snat_in_czone(192.168.1.2, 1000-foo); + Syntax error at `foo' expecting Integer for port range. +ct_snat_in_czone(192.168.1.2, 1000); + formats as ct_snat_in_czone(192.168.1.2,1000); + encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=192.168.1.2:1000)) + has prereqs ip +ct_snat_in_czone(192.168.1.2, 1000-100); + Syntax error at `100' range high should be greater than range low. + # ct_clear ct_clear; encodes as ct_clear diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 65a1822ea..617ad834c 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -2286,7 +2286,10 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat, const struct ovntrace_datapath *dp, struct flow *uflow, enum ovnact_pipeline pipeline, struct ovs_list *super) { - bool is_dst = ct_nat->ovnact.type == OVNACT_CT_DNAT; + bool is_dst = (ct_nat->ovnact.type == OVNACT_CT_DNAT || + ct_nat->ovnact.type == OVNACT_CT_DNAT_IN_CZONE); + bool nat_in_czone = (ct_nat->ovnact.type == OVNACT_CT_DNAT_IN_CZONE || + ct_nat->ovnact.type == OVNACT_CT_SNAT_IN_CZONE); if (!is_dst && dp->has_local_l3gateway && ct_nat->family == AF_UNSPEC) { /* "ct_snat;" has no visible effect in a gateway router. */ return; @@ -2297,7 +2300,8 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat, * and figure out the changes if any. */ struct flow ct_flow = *uflow; struct ds s = DS_EMPTY_INITIALIZER; - ds_put_format(&s, "ct_%cnat", direction[0]); + ds_put_format(&s, "ct_%cnat%s", direction[0], + nat_in_czone ? "in_czone" : ""); if (ct_nat->family != AF_UNSPEC) { if (ct_nat->family == AF_INET) { ds_put_format(&s, "(ip4.%s="IP_FMT")", direction, @@ -2610,6 +2614,16 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, execute_ct_nat(ovnact_get_CT_SNAT(a), dp, uflow, pipeline, super); break; + case OVNACT_CT_DNAT_IN_CZONE: + execute_ct_nat(ovnact_get_CT_DNAT_IN_CZONE(a), dp, uflow, + pipeline, super); + break; + + case OVNACT_CT_SNAT_IN_CZONE: + execute_ct_nat(ovnact_get_CT_SNAT_IN_CZONE(a), dp, uflow, + pipeline, super); + break; + case OVNACT_CT_LB: execute_ct_lb(ovnact_get_CT_LB(a), dp, uflow, pipeline, super); break;