From patchwork Wed Apr 14 20:54:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1466414 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::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) 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=cNH1KX0O; 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 RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FLF8k5NNZz9sVw for ; Thu, 15 Apr 2021 06:54:46 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 6ACD58467D; Wed, 14 Apr 2021 20:54:43 +0000 (UTC) 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 2E4cbTfAZNRX; Wed, 14 Apr 2021 20:54:41 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTP id 57B1384602; Wed, 14 Apr 2021 20:54:40 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 021D0C0019; Wed, 14 Apr 2021 20:54:40 +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 667E2C000A for ; Wed, 14 Apr 2021 20:54:38 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 23398401D2 for ; Wed, 14 Apr 2021 20:54:38 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp2.osuosl.org (amavisd-new); dkim=pass (1024-bit key) header.d=redhat.com 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 bNbOwQ2BLF1D for ; Wed, 14 Apr 2021 20:54:37 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by smtp2.osuosl.org (Postfix) with ESMTPS id 1F8EE40118 for ; Wed, 14 Apr 2021 20:54:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1618433676; 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=pgI40cR1Xz6METnqtf1G2klvENHWcBTMx7ypAj8Dy70=; b=cNH1KX0Ohc5Ps5Ksabd7suGK7h/7r74Za9f9sxUKKZF+fC4EsFAbejBPuOaFgCCNoO2IFv UJwDgydR8ZL+24Buex2RVQmGYgY9QF4ef4BnQVte2g5M1gRm5TbuURVTTc0IIT3FZQrFDM p5UibrBBhgeG8zN63e9qkh3HHI1WKLg= 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-441-o2M7BISwOqy3ifQZxEAFiA-1; Wed, 14 Apr 2021 16:54:33 -0400 X-MC-Unique: o2M7BISwOqy3ifQZxEAFiA-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1B0BD801814 for ; Wed, 14 Apr 2021 20:54:32 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-114-115.rdu2.redhat.com [10.10.114.115]) by smtp.corp.redhat.com (Postfix) with ESMTP id BDF2D5D6BA for ; Wed, 14 Apr 2021 20:54:31 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Wed, 14 Apr 2021 16:54:25 -0400 Message-Id: <20210414205429.3074290-2-mmichels@redhat.com> In-Reply-To: <20210414205429.3074290-1-mmichels@redhat.com> References: <20210414205429.3074290-1-mmichels@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=mmichels@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn v4 1/5] northd: Swap src and dst eth addresses in router egress loop. 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" When a hairpin scenario is detected (i.e. egressing on gateway router port to a NAT external address), we loop back to the ingress router pipeline and swap the inport and outport. This is intended to allow for the traffic to get DNATted. In practice, though, the ethernet destination has not been updated to be the distributed gateway port's address, and so the packet is immediately dropped. This fixes the issue by swapping source and dest eth addressses when doing the hairpin redirection. This way, the packet appears to be arriving on the gateway port, and it gets handled as expected. Reported at: https://bugzilla.redhat.com/show_bug.cgi?id=1929901 Signed-off-by: Mark Michelson Acked-by: Numan Siddique --- northd/ovn-northd.c | 1 + northd/ovn_northd.dl | 1 + tests/system-ovn.at | 111 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 94fae5648..d8ee65a5f 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -11734,6 +11734,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, ds_put_format(actions, "clone { ct_clear; " "inport = outport; outport = \"\"; " + "eth.dst <-> eth.src; " "flags = 0; flags.loopback = 1; "); for (int j = 0; j < MFF_N_LOG_REGS; j++) { ds_put_format(actions, "reg%d = 0; ", j); diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 4558dbdb5..afadac99a 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -5900,6 +5900,7 @@ for (r in &Router(.lr = lr, var actions = "clone { ct_clear; " "inport = outport; outport = \"\"; " + "eth.dst <-> eth.src; " "flags = 0; flags.loopback = 1; " ++ regs.join("") ++ "${rEGBIT_EGRESS_LOOPBACK()} = 1; " diff --git a/tests/system-ovn.at b/tests/system-ovn.at index 4885303d1..36b469c30 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -5903,3 +5903,114 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d /.*terminating with signal 15.*/d"]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP(ovn -- DNAT LR hairpin IPv4) +AT_KEYWORDS(hairpin) + +ovn_start + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-int]) + +# Set external-ids in br-int needed for ovn-controller +ovs-vsctl \ + -- set Open_vSwitch . external-ids:system-id=hv1 \ + -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true + +start_daemon ovn-controller + +# Logical network: +# Two VMs +# * VM1 with IP address 192.168.100.5 +# * VM2 with IP address 192.168.100.6 +# The VMs connect to logical switch ls1. +# +# An external router with IP address 172.18.1.2. We simulate this with a network namespace. +# There will be no traffic going here in this test. +# The external router connects to logical switch ls-pub +# +# One logical router (lr1) connects to ls1 and ls-pub. The router port connected to ls-pub is +# a gateway port. +# * The subnet connected to ls1 is 192.168.100.0/24. The Router IP address is 192.168.100.1 +# * The subnet connected to ls-pub is 172.18.1.0/24. The Router IP address is 172.168.1.1 +# lr1 has the following attributes: +# * It has a "default" static route that sends traffic out the gateway router port. +# * It has a DNAT rule that translates 172.18.2.10 to 192.168.100.6 (VM2) +# +# In this test, we want to ensure that a ping from VM1 to IP address 172.18.2.10 reaches VM2. + +ovn-nbctl ls-add ls1 +ovn-nbctl lsp-add ls1 vm1 -- lsp-set-addresses vm1 "00:00:00:00:00:05 192.168.100.5" +ovn-nbctl lsp-add ls1 vm2 -- lsp-set-addresses vm2 "00:00:00:00:00:06 192.168.100.6" + +ovn-nbctl ls-add ls-pub +ovn-nbctl lsp-add ls-pub ext-router -- lsp-set-addresses ext-router "00:00:00:00:01:02 172.18.1.2" + +ovn-nbctl lr-add lr1 +ovn-nbctl lrp-add lr1 lr1-ls1 00:00:00:00:00:01 192.168.100.1/24 +ovn-nbctl lsp-add ls1 ls1-lr1 \ + -- lsp-set-type ls1-lr1 router \ + -- lsp-set-addresses ls1-lr1 00:00:00:00:00:01 \ + -- lsp-set-options ls1-lr1 router-port=lr1-ls1 + +ovn-nbctl lrp-add lr1 lr1-ls-pub 00:00:00:00:01:01 172.18.1.1/24 +ovn-nbctl lrp-set-gateway-chassis lr1-ls-pub hv1 +ovn-nbctl lsp-add ls-pub ls-pub-lr1 \ + -- lsp-set-type ls-pub-lr1 router \ + -- lsp-set-addresses ls-pub-lr1 00:00:00:00:01:01 \ + -- lsp-set-options ls-pub-lr1 router-port=lr1-ls-pub + +ovn-nbctl lr-nat-add lr1 snat 172.18.1.1 192.168.100.0/24 +ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.18.2.10 192.168.100.6 +ovn-nbctl lr-route-add lr1 0.0.0.0/0 172.18.1.2 + +#ls1_uuid=$(fetch_column Port_Binding datapath logical_port=vm1) +#ovn-sbctl create MAC_Binding ip=172.18.2.10 datapath=$ls1_uuid logical_port=vm2 mac="00:00:00:00:00:06" + +OVN_POPULATE_ARP +ovn-nbctl --wait=hv sync + +ADD_NAMESPACES(vm1) +ADD_VETH(vm1, vm1, br-int, "192.168.100.5/24", "00:00:00:00:00:05", \ + "192.168.100.1") + +ADD_NAMESPACES(vm2) +ADD_VETH(vm2, vm2, br-int, "192.168.100.6/24", "00:00:00:00:00:06", \ + "192.168.100.1") + +ADD_NAMESPACES(ext-router) +ADD_VETH(ext-router, ext-router, br-int, "172.18.1.2/24", "00:00:00:00:01:02", \ + "172.18.1.1") + +# Let's take a quick look at the logical flows +ovn-sbctl lflow-list + +# Let's check what ovn-trace says... +ovn-trace ls1 'inport == "vm1" && eth.src == 00:00:00:00:00:05 && ip4.src == 192.168.100.5 && eth.dst == 00:00:00:00:00:01 && ip4.dst == 172.18.2.10 && ip.ttl == 32' + +# A ping from vm1 should hairpin in lr1 and successfully DNAT to vm2 +NS_CHECK_EXEC([vm1], [ping -q -c 3 -i 0.3 -w 2 172.18.2.10 | FORMAT_PING], \ +[0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) +kill $(pidof ovn-controller) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d +/.*terminating with signal 15.*/d"]) + +AT_CLEANUP +])