From patchwork Wed Aug 28 17:49:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yifeng Sun X-Patchwork-Id: 1154707 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="fsVhcv8N"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46JYDb3kYkz9sDB for ; Thu, 29 Aug 2019 03:50:23 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 3A46234B5; Wed, 28 Aug 2019 17:50:21 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 9816B2A49 for ; Wed, 28 Aug 2019 17:50:09 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg1-f195.google.com (mail-pg1-f195.google.com [209.85.215.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 987C713A for ; Wed, 28 Aug 2019 17:50:07 +0000 (UTC) Received: by mail-pg1-f195.google.com with SMTP id m3so100890pgv.13 for ; Wed, 28 Aug 2019 10:50:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=N7x49fPQcvtOTpk8jMBJzs82tYgd0cN77GVPueXMWrE=; b=fsVhcv8N0+3qT5A4ZqTyD9ZTxWqQAwU9Ub0p2mnBNv4wyooYgHu90YwO7ELXaWmV7A usNgoDgZ5MogSMksl0Pw1u1wNAOFUgUJYXwYHfYm8qfwO87QAteDY5q0JBObt9H/0jZG 8okLxH/jRERBonEV/VDXSK7tLeImGDmg22FBz/3WPNtp8Jw08WWBV2cBuj15QjeNh043 8OEQY5w+s4f8iu3k9etfNC/WEmlJLXQT1jPx4VjfM6SBwBQ5/xqYwqC22iPo7KfVh2zF ipdjpQGmQOss/oWUxwIWgBQKjQ+JnF6u5eNLc0FY215p6UF1uPzJMA6qDesO9W0W/Q8Z KR/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=N7x49fPQcvtOTpk8jMBJzs82tYgd0cN77GVPueXMWrE=; b=A+gaTOjl9XiSj+fK5eedDvEbLLd/Bhd5au8z8yORlSfQt2ifcVjs4GLwGkhXoukZyN 6UVhAFCr5iPH20+Cp4RGLMcGrw3MB+CbiA06diyvb5OCRcayZ6cwhwaXcN0sXba4hN4r /ABSc5Ux/dBbLESDXpA59MD+8CqkA4BqRo/irtnZXJiH6Q/+VxYPrHBd8UCkgY/0ahTN rfa18XD3lC/DMiJdgmLbuwR1dY7Xoein/FqDANLTUgJVfEOG6bv/y3VSYRvIQLqYfDLa HrOksMCRoksxMXERd1RGy0b6oT2qpzCoJSZFAOO0FLikOQd/ki8lhMeVF9Y4IrOtaPA8 T12w== X-Gm-Message-State: APjAAAUaGmdgaEhlHhi/DzYRRWGDnmFojGtsHGRyvOshemzvK/S26bWN /dor/3OLY+LolEyZfYDWg2qfBdPRjBA= X-Google-Smtp-Source: APXvYqz++1vvLjtv0W8aKPB6mxkA5ApgGHPr7QzncUIj19Qk8tJ79LRt/F4fZA/M4Ef7hIcybpB5SQ== X-Received: by 2002:a17:90a:8906:: with SMTP id u6mr5667490pjn.70.1567014606759; Wed, 28 Aug 2019 10:50:06 -0700 (PDT) Received: from kern417.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id c23sm2692952pgj.62.2019.08.28.10.50.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 28 Aug 2019 10:50:06 -0700 (PDT) From: Yifeng Sun To: dev@openvswitch.org, zoltan.balogh@ericsson.com Date: Wed, 28 Aug 2019 10:49:59 -0700 Message-Id: <1567014599-32423-1-git-send-email-pkusunyifeng@gmail.com> X-Mailer: git-send-email 2.7.4 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v3] userspace: Enable non-bridge port as tunnel endpoint. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org For userspace datapath, currently only the bridge itself, the LOCAL port, can be the tunnel endpoint to encap/decap tunnel packets. This patch enables non-bridge port as tunnel endpoint. One use case is for users to create a bridge and a vtep port as tap, and configure underlay IP at vtep port as the tunnel endpoint. This patch causes failure for test "ptap - L3 over patch port". This is because this test is already using non-bridge port gre1 as tunnel endpoint. In this test, an extra flow is added to support this, as shown below: ovs-ofctl add-flow br1 in_port=p1,actions=output=gre1 It later generates a datapath flow which matches an extra eth field: - recirc_id(0),...,eth_type(0x0800),... + recirc_id(0),...,eth(dst=1e:2c:e9:2a:66:9e),eth_type(0x0800),... With this patch, the above flow is no longer needed. Signed-off-by: William Tu Co-authored-by: William Tu Signed-off-by: Yifeng Sun --- v1->v2: Fixed an error pointed out by Ben. v2->v3: Fixed a test failure, thanks Ben for review and testing! ofproto/ofproto-dpif-xlate.c | 56 +++++++++++++++++++++++++++++++++++--------- tests/packet-type-aware.at | 1 - tests/tunnel-push-pop.at | 55 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 12 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 02a2a4535542..290924634f36 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -3410,6 +3410,19 @@ tnl_route_lookup_flow(const struct xlate_ctx *ctx, } } } + + /* If tunnel IP isn't configured on bridges, then we search all ports. */ + HMAP_FOR_EACH (xbridge, hmap_node, &ctx->xcfg->xbridges) { + struct xport *port; + + HMAP_FOR_EACH (port, ofp_node, &xbridge->xports) { + if (!strncmp(netdev_get_name(port->netdev), + out_dev, IFNAMSIZ)) { + *out_port = port; + return 0; + } + } + } return -ENOENT; } @@ -3972,6 +3985,16 @@ is_nd_dst_correct(const struct flow *flow, const struct in6_addr *ipv6_addr) IN6_ARE_ADDR_EQUAL(&flow->ipv6_dst, ipv6_addr); } +static bool +is_neighbor_reply_matched(const struct flow *flow, struct in6_addr *ip_addr) +{ + return ((IN6_IS_ADDR_V4MAPPED(ip_addr) && + flow->dl_type == htons(ETH_TYPE_ARP) && + in6_addr_get_mapped_ipv4(ip_addr) == flow->nw_dst) || + (!IN6_IS_ADDR_V4MAPPED(ip_addr) && + is_nd_dst_correct(flow, ip_addr))); +} + /* Function verifies if the ARP reply or Neighbor Advertisement represented by * 'flow' addresses the 'xbridge' of 'ctx'. Returns true if the ARP TA or * neighbor discovery destination is in the list of configured IP addresses of @@ -3986,11 +4009,7 @@ is_neighbor_reply_correct(const struct xlate_ctx *ctx, const struct flow *flow) /* Verify if 'nw_dst' of ARP or 'ipv6_dst' of ICMPV6 is in the list. */ for (i = 0; xbridge_addr && i < xbridge_addr->n_addr; i++) { struct in6_addr *ip_addr = &xbridge_addr->addr[i]; - if ((IN6_IS_ADDR_V4MAPPED(ip_addr) && - flow->dl_type == htons(ETH_TYPE_ARP) && - in6_addr_get_mapped_ipv4(ip_addr) == flow->nw_dst) || - (!IN6_IS_ADDR_V4MAPPED(ip_addr) && - is_nd_dst_correct(flow, ip_addr))) { + if (is_neighbor_reply_matched(flow, ip_addr)) { /* Found a match. */ ret = true; break; @@ -3998,20 +4017,35 @@ is_neighbor_reply_correct(const struct xlate_ctx *ctx, const struct flow *flow) } xbridge_addr_unref(xbridge_addr); + + /* If not found in bridge's IPs, search in its ports. */ + if (!ret) { + struct in6_addr *ip_addr, *mask; + struct xport *port; + int error, n_in6; + + HMAP_FOR_EACH (port, ofp_node, &ctx->xbridge->xports) { + error = netdev_get_addr_list(port->netdev, &ip_addr, + &mask, &n_in6); + if (!error && is_neighbor_reply_matched(flow, ip_addr)) { + /* Found a match. */ + ret = true; + break; + } + } + } return ret; } static bool -terminate_native_tunnel(struct xlate_ctx *ctx, ofp_port_t ofp_port, - struct flow *flow, struct flow_wildcards *wc, - odp_port_t *tnl_port) +terminate_native_tunnel(struct xlate_ctx *ctx, struct flow *flow, + struct flow_wildcards *wc, odp_port_t *tnl_port) { *tnl_port = ODPP_NONE; /* XXX: Write better Filter for tunnel port. We can use in_port * in tunnel-port flow to avoid these checks completely. */ - if (ofp_port == OFPP_LOCAL && - ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) { + if (ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) { *tnl_port = tnl_port_map_lookup(flow, wc); /* If no tunnel port was found and it's about an ARP or ICMPv6 packet, @@ -4155,7 +4189,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, native_tunnel_output(ctx, xport, flow, odp_port, truncate); flow->tunnel = flow_tnl; /* Restore tunnel metadata */ - } else if (terminate_native_tunnel(ctx, ofp_port, flow, wc, + } else if (terminate_native_tunnel(ctx, flow, wc, &odp_tnl_port)) { /* Intercept packet to be received on native tunnel port. */ nl_msg_put_odp_port(ctx->odp_actions, OVS_ACTION_ATTR_TUNNEL_POP, diff --git a/tests/packet-type-aware.at b/tests/packet-type-aware.at index e169709a906b..1ea81eb4936e 100644 --- a/tests/packet-type-aware.at +++ b/tests/packet-type-aware.at @@ -697,7 +697,6 @@ AT_CHECK([ ovs-ofctl del-flows br1 && ovs-ofctl del-flows br2 && ovs-ofctl add-flow br0 in_port=n0,actions=decap,output=p0 -OOpenFlow13 && - ovs-ofctl add-flow br1 in_port=p1,actions=output=gre1 && ovs-ofctl add-flow br2 in_port=LOCAL,actions=output=n2 ], [0]) diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index f7172433ee63..5056b971256a 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -601,3 +601,58 @@ NXST_FLOW reply: OVS_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([tunnel_push_pop - use non-local port as tunnel endpoint]) + +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1]) +AT_CHECK([ovs-vsctl add-port br0 vtep0 -- set int vtep0 type=dummy], [0]) +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) +AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=gre \ + options:remote_ip=1.1.2.92 ofport_request=3], [0]) + +AT_CHECK([ovs-appctl dpif/show], [0], [dnl +dummy@ovs-dummy: hit:0 missed:0 + br0: + br0 65534/100: (dummy-internal) + p0 1/1: (dummy) + vtep0 2/2: (dummy) + int-br: + int-br 65534/3: (dummy-internal) + t1 3/4: (gre: remote_ip=1.1.2.92) +]) + +AT_CHECK([ovs-appctl netdev-dummy/ip4addr vtep0 1.1.2.88/24], [0], [OK +]) +AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 vtep0], [0], [OK +]) +AT_CHECK([ovs-ofctl add-flow br0 action=normal]) +AT_CHECK([ovs-ofctl add-flow int-br action=normal]) + +dnl Use arp request and reply to achieve tunnel next hop mac binding +dnl By default, vtep0's MAC address is aa:55:aa:55:00:03 +AT_CHECK([ovs-appctl netdev-dummy/receive vtep0 'recirc_id(0),in_port(2),eth(dst=ff:ff:ff:ff:ff:ff,src=aa:55:aa:55:00:03),eth_type(0x0806),arp(tip=1.1.2.92,sip=1.1.2.88,op=1,sha=aa:55:aa:55:00:03,tha=00:00:00:00:00:00)']) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:03),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=aa:55:aa:55:00:03)']) + +AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl +1.1.2.92 f8:bc:12:44:34:b6 br0 +]) + +AT_CHECK([ovs-appctl ovs/route/show | tail -n+2 | sort], [0], [dnl +User: 1.1.2.0/24 dev vtep0 SRC 1.1.2.88 +]) + +dnl Check GRE tunnel pop +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:03),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) + +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: tnl_pop(4) +]) + +dnl Check GRE tunnel push +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(dst=f9:bc:12:44:34:b6,src=af:55:aa:55:00:03),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.92,proto=1,tos=0,ttl=64,frag=no)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: clone(tnl_push(tnl_port(4),header(size=38,type=3,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:03,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=47,tos=0,ttl=64,frag=0x4000),gre((flags=0x0,proto=0x6558))),out_port(2)),1) +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP