From patchwork Wed Jun 22 15:47:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thadeu Lima de Souza Cascardo X-Patchwork-Id: 639251 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3rZTXG5GNpz9t1C for ; Thu, 23 Jun 2016 01:48:30 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id E52C010900; Wed, 22 Jun 2016 08:48:07 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e3.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id 9952B108F8 for ; Wed, 22 Jun 2016 08:48:05 -0700 (PDT) Received: from bar5.cudamail.com (localhost [127.0.0.1]) by mx1e3.cudamail.com (Postfix) with ESMTPS id 206EF420453 for ; Wed, 22 Jun 2016 09:48:05 -0600 (MDT) X-ASG-Debug-ID: 1466610484-09eadd08b413be0001-byXFYA Received: from mx1-pf2.cudamail.com ([192.168.24.2]) by bar5.cudamail.com with ESMTP id 8yCErxnkA7bOhCB0 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 22 Jun 2016 09:48:04 -0600 (MDT) X-Barracuda-Envelope-From: cascardo@redhat.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.2 Received: from unknown (HELO mx1.redhat.com) (209.132.183.28) by mx1-pf2.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 22 Jun 2016 15:48:04 -0000 Received-SPF: pass (mx1-pf2.cudamail.com: SPF record at _spf1.redhat.com designates 209.132.183.28 as permitted sender) X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-Barracuda-RBL-IP: 209.132.183.28 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 60C3AC05B1EF for ; Wed, 22 Jun 2016 15:48:03 +0000 (UTC) Received: from indiana.gru.redhat.com (ovpn-116-114.phx2.redhat.com [10.3.116.114]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5MFlrdK014082 for ; Wed, 22 Jun 2016 11:48:02 -0400 X-CudaMail-Envelope-Sender: cascardo@redhat.com From: Thadeu Lima de Souza Cascardo To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-E2-621037362 X-CudaMail-DTE: 062216 X-CudaMail-Originating-IP: 209.132.183.28 Date: Wed, 22 Jun 2016 12:47:41 -0300 X-ASG-Orig-Subj: [##CM-E2-621037362##][PATCH v3 4/5] dpif-netlink: add GRE creation support Message-Id: <1466610462-32116-5-git-send-email-cascardo@redhat.com> In-Reply-To: <1466610462-32116-1-git-send-email-cascardo@redhat.com> References: <1466610462-32116-1-git-send-email-cascardo@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 22 Jun 2016 15:48:03 +0000 (UTC) X-Barracuda-Connect: UNKNOWN[192.168.24.2] X-Barracuda-Start-Time: 1466610484 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 Subject: [ovs-dev] [PATCH v3 4/5] dpif-netlink: add GRE creation support X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" Creates GRE devices using rtnetlink and tunnel metadata. If the kernel does not support tunnel metadata, it will return EEXIST because of the fallback tunnel. However, on kernels between v3.10 and v3.12, it will not. So, we need to verify the created tunnel has the tunnel metadata attribute. This was tested on kernels 4.2.3, 4.3.6, 4.4.9, 4.5.5 and RHEL 3.10 based. All of them worked with the system traffic test "datapath - ping over gre tunnel". Also tested on a 3.10 based kernel without the fix for the existing fallback tunnel. That is, the kernel would not return EEXIST. Yet, the test works fine. Signed-off-by: Thadeu Lima de Souza Cascardo --- lib/dpif-netlink.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index b8b908f..5f1b867 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -963,6 +964,12 @@ netdev_vxlan_destroy(const char *name) return netdev_linux_destroy(name); } +static int +netdev_gre_destroy(const char *name) +{ + return netdev_linux_destroy(name); +} + /* * On some older systems, these enums are not defined. */ @@ -977,6 +984,10 @@ netdev_vxlan_destroy(const char *name) #define IFLA_VXLAN_COLLECT_METADATA 25 #endif +#if IFLA_GRE_MAX < 18 +#define IFLA_GRE_COLLECT_METADATA 18 +#endif + static int netdev_vxlan_create(struct netdev *netdev) { @@ -1031,6 +1042,115 @@ netdev_vxlan_create(struct netdev *netdev) return err; } +/* + * On some Linux versions, creating the device with IFLA_GRE_COLLECT_METADATA + * will succeed, even though that attribute is not supported. We need to verify + * the device has been created with that attribute. In case it has not, we + * destroy it and use the compat code. + */ +static int +netdev_gre_verify(const char *name) +{ + int err; + struct ofpbuf request, *reply; + struct ifinfomsg *ifmsg; + + static const struct nl_policy rtlink_policy[] = { + [IFLA_LINKINFO] = { .type = NL_A_NESTED }, + }; + static const struct nl_policy linkinfo_policy[] = { + [IFLA_INFO_KIND] = { .type = NL_A_STRING }, + [IFLA_INFO_DATA] = { .type = NL_A_NESTED }, + }; + static const struct nl_policy gre_policy[] = { + [IFLA_GRE_COLLECT_METADATA] = { .type = NL_A_FLAG }, + }; + + ofpbuf_init(&request, 0); + nl_msg_put_nlmsghdr(&request, 0, RTM_GETLINK, + NLM_F_REQUEST); + ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg)); + nl_msg_put_string(&request, IFLA_IFNAME, name); + + err = nl_transact(NETLINK_ROUTE, &request, &reply); + if (!err) { + struct nlattr *rtlink[ARRAY_SIZE(rtlink_policy)]; + struct nlattr *linkinfo[ARRAY_SIZE(linkinfo_policy)]; + struct nlattr *gre[ARRAY_SIZE(gre_policy)]; + + err = EINVAL; + ifmsg = ofpbuf_at(reply, NLMSG_HDRLEN, sizeof *ifmsg); + if (nl_policy_parse(reply, NLMSG_HDRLEN + sizeof *ifmsg, + rtlink_policy, rtlink, ARRAY_SIZE(rtlink_policy))) { + if (nl_parse_nested(rtlink[IFLA_LINKINFO], linkinfo_policy, + linkinfo, ARRAY_SIZE(linkinfo_policy)) && + !strcmp(nl_attr_get_string(linkinfo[IFLA_INFO_KIND]), + "gretap")) { + if (nl_parse_nested(linkinfo[IFLA_INFO_DATA], gre_policy, gre, + ARRAY_SIZE(gre_policy)) && + nl_attr_get_flag(gre[IFLA_GRE_COLLECT_METADATA])) { + err = 0; + } + } + } + ofpbuf_uninit(reply); + } + ofpbuf_uninit(&request); + return err; +} + +static int +netdev_gre_create(struct netdev *netdev) +{ + int err; + struct ofpbuf request, *reply; + size_t linkinfo_off, infodata_off; + char namebuf[NETDEV_VPORT_NAME_BUFSIZE]; + const char *name = netdev_vport_get_dpif_port(netdev, + namebuf, sizeof namebuf); + struct ifinfomsg *ifinfo; + const struct netdev_tunnel_config *tnl_cfg; + tnl_cfg = netdev_get_tunnel_config(netdev); + if (!tnl_cfg) { /* or assert? */ + return EINVAL; + } + + ofpbuf_init(&request, 0); + nl_msg_put_nlmsghdr(&request, 0, RTM_NEWLINK, + NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE); + ifinfo = ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg)); + ifinfo->ifi_change = ifinfo->ifi_flags = IFF_UP; + nl_msg_put_string(&request, IFLA_IFNAME, name); + nl_msg_put_u32(&request, IFLA_MTU, UINT16_MAX); + linkinfo_off = nl_msg_start_nested(&request, IFLA_LINKINFO); + nl_msg_put_string(&request, IFLA_INFO_KIND, "gretap"); + infodata_off = nl_msg_start_nested(&request, IFLA_INFO_DATA); + nl_msg_put_flag(&request, IFLA_GRE_COLLECT_METADATA); + nl_msg_end_nested(&request, infodata_off); + nl_msg_end_nested(&request, linkinfo_off); + + err = nl_transact(NETLINK_ROUTE, &request, &reply); + + if (!err) { + ofpbuf_uninit(reply); + } + + if (!err && (err = netdev_gre_verify(name))) { + netdev_gre_destroy(name); + } + + /* + * If tunnel metadata is not supported, EEXIST will be returned for zero + * addresses tunnel. We still need to verify metadata has been set as above. + */ + if (err == EINVAL || err == EEXIST) { + err = EOPNOTSUPP; + } + + ofpbuf_uninit(&request); + return err; +} + #else static int @@ -1040,11 +1160,23 @@ netdev_vxlan_create(struct netdev *netdev OVS_UNUSED) } static int +netdev_gre_create(struct netdev *netdev OVS_UNUSED) +{ + return EOPNOTSUPP; +} + +static int netdev_vxlan_destroy(const char *name OVS_UNUSED) { return EOPNOTSUPP; } +static int +netdev_gre_destroy(const char *name OVS_UNUSED) +{ + return EOPNOTSUPP; +} + #endif static int @@ -1058,6 +1190,7 @@ dpif_netlink_port_create(struct netdev *netdev) case OVS_VPORT_TYPE_VXLAN: return netdev_vxlan_create(netdev); case OVS_VPORT_TYPE_GRE: + return netdev_gre_create(netdev); case OVS_VPORT_TYPE_GENEVE: case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: @@ -1078,6 +1211,7 @@ dpif_netlink_port_destroy(const char *name, const char *type) case OVS_VPORT_TYPE_VXLAN: return netdev_vxlan_destroy(name); case OVS_VPORT_TYPE_GRE: + return netdev_gre_destroy(name); case OVS_VPORT_TYPE_GENEVE: case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: