From patchwork Fri Nov 4 08:18:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Musil X-Patchwork-Id: 1699386 X-Patchwork-Delegate: mmichels@redhat.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: legolas.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=TB+41CUD; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4N3YS63TP4z1yqS for ; Fri, 4 Nov 2022 19:19:02 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 43F5081FEF; Fri, 4 Nov 2022 08:18:59 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 43F5081FEF Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=TB+41CUD X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aPU__41IJPnG; Fri, 4 Nov 2022 08:18:58 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 1C0F98200C; Fri, 4 Nov 2022 08:18:57 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 1C0F98200C Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id C72D7C0070; Fri, 4 Nov 2022 08:18:56 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 76B1DC0033 for ; Fri, 4 Nov 2022 08:18:55 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 42D764189A for ; Fri, 4 Nov 2022 08:18:55 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 42D764189A Authentication-Results: smtp4.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=TB+41CUD X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id rtEww0gXsS7I for ; Fri, 4 Nov 2022 08:18:53 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org B66974187D Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp4.osuosl.org (Postfix) with ESMTPS id B66974187D for ; Fri, 4 Nov 2022 08:18:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1667549932; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xIxf1hWc9CsVkO1TRnsBVBn93dnN0m3mKOneSBR8Zek=; b=TB+41CUDJbrXeqQPTAGkz3iSsCxUoEz96ulD+WYnlI97en9EDpWE62kDRKae+89xFH77Jl tWVPb5KlJsQ/S12qn1S0/2Qkq/P98MpNQ6v1WofuTdXfYaLZJgx6QtT+9mZpxRF0uta4jK pt6i4pgzs7ho0OIYqYFcmRu13kp1/14= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-519-CsDHfdNTPx-Jirad_lvuRw-1; Fri, 04 Nov 2022 04:18:50 -0400 X-MC-Unique: CsDHfdNTPx-Jirad_lvuRw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4874A800B23 for ; Fri, 4 Nov 2022 08:18:50 +0000 (UTC) Received: from amusil.redhat.com (ovpn-192-80.brq.redhat.com [10.40.192.80]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8A03540C83EB; Fri, 4 Nov 2022 08:18:49 +0000 (UTC) From: Ales Musil To: dev@openvswitch.org Date: Fri, 4 Nov 2022 09:18:46 +0100 Message-Id: <20221104081847.281045-2-amusil@redhat.com> In-Reply-To: <20221104081847.281045-1-amusil@redhat.com> References: <20221104081847.281045-1-amusil@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn v2 1/2] actions: Add new action called ct_commit_nat 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" Add action called ct_commit_nat, that performs NAT while committing the connection. This is useful for related traffic on which we need to perform NAT, mainly ICMP. We need to commit due to design decision of OvS[0]: "Connections identified as rel are separate from the originating connection and must be committed separately." [0] http://www.openvswitch.org/support/dist-docs/ovs-fields.7.txt Reported-at: https://bugzilla.redhat.com/2126083 Signed-off-by: Ales Musil Acked-by: Mark Michelson --- include/ovn/actions.h | 3 +++ lib/actions.c | 42 +++++++++++++++++++++++++++++++++++++++++- ovn-sb.xml | 12 ++++++++++++ tests/ovn.at | 5 +++++ utilities/ovn-trace.c | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index d7ee84dac..5814a34aa 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -74,6 +74,7 @@ struct ovn_extend_table; OVNACT(CT_LB_MARK, ovnact_ct_lb) \ OVNACT(SELECT, ovnact_select) \ OVNACT(CT_CLEAR, ovnact_null) \ + OVNACT(CT_COMMIT_NAT, ovnact_ct_nat) \ OVNACT(CLONE, ovnact_nest) \ OVNACT(ARP, ovnact_nest) \ OVNACT(ICMP4, ovnact_nest) \ @@ -275,6 +276,8 @@ struct ovnact_ct_nat { uint16_t port_hi; } port_range; + bool commit; /* Explicit commit action. */ + uint8_t ltable; /* Logical table ID of next table. */ }; diff --git a/lib/actions.c b/lib/actions.c index adbb42db4..91bbabc0e 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -920,6 +920,7 @@ parse_ct_nat(struct action_context *ctx, const char *name, return; } cn->ltable = ctx->pp->cur_ltable + 1; + cn->commit = false; if (lexer_match(ctx->lexer, LEX_T_LPAREN)) { if (ctx->lexer->token.type != LEX_T_INTEGER @@ -929,9 +930,11 @@ parse_ct_nat(struct action_context *ctx, const char *name, return; } if (ctx->lexer->token.format == LEX_F_IPV4) { + cn->commit = true; cn->family = AF_INET; cn->ipv4 = ctx->lexer->token.value.ipv4; } else if (ctx->lexer->token.format == LEX_F_IPV6) { + cn->commit = true; cn->family = AF_INET6; cn->ipv6 = ctx->lexer->token.value.ipv6; } @@ -1004,6 +1007,24 @@ parse_CT_SNAT_IN_CZONE(struct action_context *ctx) ovnact_put_CT_SNAT_IN_CZONE(ctx->ovnacts)); } +static void +parse_CT_COMMIT_NAT(struct action_context *ctx) +{ + add_prerequisite(ctx, "ip"); + + if (ctx->pp->cur_ltable >= ctx->pp->n_tables) { + lexer_error(ctx->lexer, + "\"ct_commit_related\" action not allowed in last table."); + return; + } + + struct ovnact_ct_nat *cn = ovnact_put_CT_COMMIT_NAT(ctx->ovnacts); + cn->commit = true; + cn->ltable = ctx->pp->cur_ltable + 1; + cn->family = AF_UNSPEC; + cn->port_range.exists = false; +} + static void format_ct_nat(const struct ovnact_ct_nat *cn, const char *name, struct ds *s) { @@ -1053,6 +1074,12 @@ 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 +format_CT_COMMIT_NAT(const struct ovnact_ct_nat *cn OVS_UNUSED, struct ds *s) +{ + ds_put_cstr(s, "ct_commit_nat;"); +} + static void encode_ct_nat(const struct ovnact_ct_nat *cn, const struct ovnact_encode_params *ep, @@ -1104,7 +1131,7 @@ encode_ct_nat(const struct ovnact_ct_nat *cn, ofpacts->header = ofpbuf_push_uninit(ofpacts, nat_offset); ct = ofpacts->header; - if (cn->family == AF_INET || cn->family == AF_INET6) { + if (cn->commit) { ct->flags |= NX_CT_F_COMMIT; } ofpact_finish(ofpacts, &ct->ofpact); @@ -1143,6 +1170,17 @@ encode_CT_SNAT_IN_CZONE(const struct ovnact_ct_nat *cn, encode_ct_nat(cn, ep, true, ep->common_nat_ct_zone, ofpacts); } +static void +encode_CT_COMMIT_NAT(const struct ovnact_ct_nat *cn, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + enum mf_field_id zone = ep->is_switch + ? MFF_LOG_CT_ZONE + : MFF_LOG_DNAT_ZONE; + encode_ct_nat(cn, ep, false, zone, ofpacts); +} + static void ovnact_ct_nat_free(struct ovnact_ct_nat *ct_nat OVS_UNUSED) { @@ -4732,6 +4770,8 @@ parse_action(struct action_context *ctx) parse_ct_lb_action(ctx, true); } else if (lexer_match_id(ctx->lexer, "ct_clear")) { ovnact_put_CT_CLEAR(ctx->ovnacts); + } else if (lexer_match_id(ctx->lexer, "ct_commit_nat")) { + parse_CT_COMMIT_NAT(ctx); } else if (lexer_match_id(ctx->lexer, "clone")) { parse_CLONE(ctx); } else if (lexer_match_id(ctx->lexer, "arp")) { diff --git a/ovn-sb.xml b/ovn-sb.xml index 315d60853..75becdaf3 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -1467,6 +1467,18 @@ Clears connection tracking state. +
ct_commit_nat;
+
+

+ Applies NAT and commits the connection to the CT. Automatically + moves on to the next table, as if followed by + next. + This is very useful for connections that are in related state for + already existing connections and allows the NAT to be applied + to them as well. +

+
+
clone { action; ... };
Makes a copy of the packet being processed and executes each diff --git a/tests/ovn.at b/tests/ovn.at index f8b8db4df..65edb7812 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1418,6 +1418,11 @@ ct_snat_in_czone(192.168.1.2, 1000-100); ct_clear; encodes as ct_clear +# ct_commit_nat +ct_commit_nat; + encodes as ct(commit,table=19,zone=NXM_NX_REG13[0..15],nat) + has prereqs ip + # clone clone { ip4.dst = 255.255.255.255; output; }; next; encodes as clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,19) diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 6fa5137d9..200b7507b 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -2438,6 +2438,35 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat, * flow, not ct_flow. */ } +static void +execute_ct_commit_nat(const struct ovnact_ct_nat *ct_nat, + const struct ovntrace_datapath *dp, struct flow *uflow, + enum ovnact_pipeline pipeline, struct ovs_list *super) +{ + struct flow ct_flow = *uflow; + struct ds s = DS_EMPTY_INITIALIZER; + + ds_put_cstr(&s, "ct_commit_nat /* assuming no" + " un-nat entry, so no change */"); + + /* ct(nat) implies ct(). */ + if (!(ct_flow.ct_state & CS_TRACKED)) { + ct_flow.ct_state |= next_ct_state(&s); + } + + struct ovntrace_node *node = ovntrace_node_append( + super, OVNTRACE_NODE_TRANSFORMATION, "%s", ds_cstr(&s)); + ds_destroy(&s); + + /* Trace the actions in the next table. */ + trace__(dp, &ct_flow, ct_nat->ltable, pipeline, &node->subs); + + /* Upon return, we will trace the actions following the ct action in the + * original table. The pipeline forked, so we're using the original + * flow, not ct_flow. */ +} + + static void execute_ct_lb(const struct ovnact_ct_lb *ct_lb, const struct ovntrace_datapath *dp, struct flow *uflow, @@ -3095,6 +3124,11 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, flow_clear_conntrack(uflow); break; + case OVNACT_CT_COMMIT_NAT: + execute_ct_commit_nat(ovnact_get_CT_COMMIT_NAT(a), dp, uflow, + pipeline, super); + break; + case OVNACT_CLONE: execute_clone(ovnact_get_CLONE(a), dp, uflow, table_id, pipeline, super);