From patchwork Thu May 18 20:10:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Garver X-Patchwork-Id: 764174 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3wTMpj1d1Fz9s4q for ; Fri, 19 May 2017 06:14:21 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B5759BDA; Thu, 18 May 2017 20:10:46 +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 DEA05BCA for ; Thu, 18 May 2017 20:10:38 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 45E84151 for ; Thu, 18 May 2017 20:10:38 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BC6C5C057FA8 for ; Thu, 18 May 2017 20:10:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com BC6C5C057FA8 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=erig.me Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=none smtp.mailfrom=e@erig.me DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com BC6C5C057FA8 Received: from dev-rhel7.localdomain (wsfd-netdev-vmhost.ntdv.lab.eng.bos.redhat.com [10.19.17.17]) by smtp.corp.redhat.com (Postfix) with ESMTP id 78C4518207 for ; Thu, 18 May 2017 20:10:37 +0000 (UTC) From: Eric Garver To: dev@openvswitch.org Date: Thu, 18 May 2017 16:10:33 -0400 Message-Id: <20170518201033.13092-8-e@erig.me> In-Reply-To: <20170518201033.13092-1-e@erig.me> References: <20170518201033.13092-1-e@erig.me> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 18 May 2017 20:10:37 +0000 (UTC) X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 v5 7/7] dpif-netlink: Probe for out-of-tree tunnels, decides used interface 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 On dpif init, probe for whether tunnels are created using in-tree (upstream linux) or out-of-tree (OVS). This is done by probing for the existence of "ovs_geneve" via rtnetlink. This is used to determine how to create the tunnel devices. For out-of-tree tunnels, only try genetlink/compat. For in-tree kernel tunnels, try rtnetlink then fallback to genetlink. Signed-off-by: Eric Garver --- NEWS | 3 +++ lib/dpif-netlink-rtnl.c | 46 ++++++++++++++++++++++++++++++++++++++++++ lib/dpif-netlink-rtnl.h | 8 ++++++++ lib/dpif-netlink.c | 53 ++++++++++++++++++++++++++++++++++--------------- 4 files changed, 94 insertions(+), 16 deletions(-) diff --git a/NEWS b/NEWS index 7a2b185bbd84..da9863966617 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,9 @@ Post-v2.7.0 - Tunnels: * Added support to set packet mark for tunnel endpoint using `egress_pkt_mark` OVSDB option. + * When using Linux kernel datapath tunnels may be created using rtnetlink. + This will allow us to take advantage of new tunnel features without + having to make changes to the vport modules. - EMC insertion probability is reduced to 1% and is configurable via the new 'other_config:emc-insert-inv-prob' option. - DPDK: diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c index 2061564436df..7faad5248037 100644 --- a/lib/dpif-netlink-rtnl.c +++ b/lib/dpif-netlink-rtnl.c @@ -419,3 +419,49 @@ dpif_netlink_rtnl_port_destroy(const char *name, const char *type) } return 0; } + +/** + * Probe for whether the modules are out-of-tree (openvswitch) or in-tree + * (upstream kernel). + * + * We probe for "ovs_geneve" via rtnetlink. As long as this returns something + * other than EOPNOTSUPP we know that the module in use is the out-of-tree one. + * This will be used to determine which netlink interface to use when creating + * ports; rtnetlink or compat/genetlink. + * + * See ovs_tunnels_out_of_tree + */ +bool +dpif_netlink_rtnl_probe_oot_tunnels(void) +{ + char namebuf[NETDEV_VPORT_NAME_BUFSIZE]; + struct netdev *netdev = NULL; + bool out_of_tree = false; + const char *name; + int error; + + error = netdev_open("ovs-system-probe", "geneve", &netdev); + if (!error) { + const struct netdev_tunnel_config *tnl_cfg; + + tnl_cfg = netdev_get_tunnel_config(netdev); + if (!tnl_cfg) { + return true; + } + + name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf); + error = dpif_netlink_rtnl_create(tnl_cfg, name, OVS_VPORT_TYPE_GENEVE, + "ovs_geneve", + (NLM_F_REQUEST | NLM_F_ACK + | NLM_F_CREATE)); + if (error != EOPNOTSUPP) { + if (!error) { + dpif_netlink_rtnl_destroy(name); + } + out_of_tree = true; + } + netdev_close(netdev); + } + + return out_of_tree; +} diff --git a/lib/dpif-netlink-rtnl.h b/lib/dpif-netlink-rtnl.h index 952c0d4187e5..5c790e0bc06f 100644 --- a/lib/dpif-netlink-rtnl.h +++ b/lib/dpif-netlink-rtnl.h @@ -25,6 +25,8 @@ int dpif_netlink_rtnl_port_create(struct netdev *netdev); int dpif_netlink_rtnl_port_destroy(const char *name, const char *type); +bool dpif_netlink_rtnl_probe_oot_tunnels(void); + #ifndef __linux__ /* Dummy implementations for non Linux builds. */ @@ -41,6 +43,12 @@ dpif_netlink_rtnl_port_destroy(const char *name OVS_UNUSED, return EOPNOTSUPP; } +static inline bool +dpif_netlink_rtnl_probe_oot_tunnels(void) +{ + return true; +} + #endif #endif /* DPIF_NETLINK_RTNL_H */ diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 52d28fb39e7b..503fe33eb161 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -62,9 +62,6 @@ VLOG_DEFINE_THIS_MODULE(dpif_netlink); #ifdef _WIN32 #include "wmi.h" enum { WINDOWS = 1 }; -static int dpif_netlink_port_query__(const struct dpif_netlink *dpif, - odp_port_t port_no, const char *port_name, - struct dpif_port *dpif_port); #else enum { WINDOWS = 0 }; #endif @@ -215,6 +212,12 @@ static int ovs_packet_family; * Initialized by dpif_netlink_init(). */ static unsigned int ovs_vport_mcgroup; +/* If true, tunnel devices are created using OVS compat/genetlink. + * If false, tunnel devices are created with rtnetlink and using light weight + * tunnels. If we fail to create the tunnel the rtnetlink+LWT, then we fallback + * to using the compat interface. */ +static bool ovs_tunnels_out_of_tree = true; + static int dpif_netlink_init(void); static int open_dpif(const struct dpif_netlink_dp *, struct dpif **); static uint32_t dpif_netlink_port_get_pid(const struct dpif *, @@ -226,6 +229,9 @@ static void dpif_netlink_vport_to_ofpbuf(const struct dpif_netlink_vport *, struct ofpbuf *); static int dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *, const struct ofpbuf *); +static int dpif_netlink_port_query__(const struct dpif_netlink *dpif, + odp_port_t port_no, const char *port_name, + struct dpif_port *dpif_port); static struct dpif_netlink * dpif_netlink_cast(const struct dpif *dpif) @@ -948,7 +954,7 @@ dpif_netlink_port_add_compat(struct dpif_netlink *dpif, struct netdev *netdev, } -static int OVS_UNUSED +static int dpif_netlink_rtnl_port_create_and_add(struct dpif_netlink *dpif, struct netdev *netdev, odp_port_t *port_nop) @@ -982,10 +988,15 @@ dpif_netlink_port_add(struct dpif *dpif_, struct netdev *netdev, odp_port_t *port_nop) { struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); - int error; + int error = EOPNOTSUPP; fat_rwlock_wrlock(&dpif->upcall_lock); - error = dpif_netlink_port_add_compat(dpif, netdev, port_nop); + if (!ovs_tunnels_out_of_tree) { + error = dpif_netlink_rtnl_port_create_and_add(dpif, netdev, port_nop); + } + if (error) { + error = dpif_netlink_port_add_compat(dpif, netdev, port_nop); + } fat_rwlock_unlock(&dpif->upcall_lock); return error; @@ -996,31 +1007,39 @@ dpif_netlink_port_del__(struct dpif_netlink *dpif, odp_port_t port_no) OVS_REQ_WRLOCK(dpif->upcall_lock) { struct dpif_netlink_vport vport; + struct dpif_port dpif_port; int error; + error = dpif_netlink_port_query__(dpif, port_no, NULL, &dpif_port); + if (error) { + return error; + } + dpif_netlink_vport_init(&vport); vport.cmd = OVS_VPORT_CMD_DEL; vport.dp_ifindex = dpif->dp_ifindex; vport.port_no = port_no; #ifdef _WIN32 - struct dpif_port temp_dpif_port; - - error = dpif_netlink_port_query__(dpif, port_no, NULL, &temp_dpif_port); - if (error) { - return error; - } - if (!strcmp(temp_dpif_port.type, "internal")) { - if (!delete_wmi_port(temp_dpif_port.name)){ + if (!strcmp(dpif_port.type, "internal")) { + if (!delete_wmi_port(dpif_port.name)) { VLOG_ERR("Could not delete wmi port with name: %s", - temp_dpif_port.name); + dpif_port.name); }; } - dpif_port_destroy(&temp_dpif_port); #endif error = dpif_netlink_vport_transact(&vport, NULL, NULL); vport_del_channels(dpif, port_no); + if (!error && !ovs_tunnels_out_of_tree) { + error = dpif_netlink_rtnl_port_destroy(dpif_port.name, dpif_port.type); + if (error == EOPNOTSUPP) { + error = 0; + } + } + + dpif_port_destroy(&dpif_port); + return error; } @@ -2549,6 +2568,8 @@ dpif_netlink_init(void) &ovs_vport_mcgroup); } + ovs_tunnels_out_of_tree = dpif_netlink_rtnl_probe_oot_tunnels(); + ovsthread_once_done(&once); }