From patchwork Sat Oct 28 00:09:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831549 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="whWymj9l"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1N11Sx5z9t4b for ; Sat, 28 Oct 2017 11:10:09 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751286AbdJ1AKC (ORCPT ); Fri, 27 Oct 2017 20:10:02 -0400 Received: from mail-pf0-f193.google.com ([209.85.192.193]:53729 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751164AbdJ1AKB (ORCPT ); Fri, 27 Oct 2017 20:10:01 -0400 Received: by mail-pf0-f193.google.com with SMTP id t188so6003014pfd.10 for ; Fri, 27 Oct 2017 17:10:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=cVXVtQlMnMlQpurQyokgO+EUQtsWaIWfLnLqXorvB08=; b=whWymj9lKxiCLHW7nDcTfSV+Qdnn29WQnhFAIp3YYFAgBMzm/b5xTiyaoe+dPQ1h9P 8M8c8WfGzK9wAaDICX1rcRs3lXpRfjh24YHnhW9N55A1zKY4fA7KJxUx9zfPW0kP6BtY UWXiZ4S/WhmBeDHAQ3EdjEOx2gjTYsBGoTP6n8FEte7Cj62eq/POvk5uWR0drgvPUAnW OP1vcXhRA9gBbZ55R2fD5RDx5xTxvL05qJBAwQPNEEbDIZBJHjzDRKT9IXQ7/rSais+r Gi136OqO+gQbubMyj01PtkRtDSeRPQE1nm1s++bhO+X+OH2Ej7Ju0P+6wHTMMQ4Oal1q EMOg== 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:in-reply-to :references; bh=cVXVtQlMnMlQpurQyokgO+EUQtsWaIWfLnLqXorvB08=; b=b9SvMtgDk+DzhCLPVQQSyjZJyI5EoxEnoeUb28fnKR/hD58l9iD72WsOboxaOHg88y s7ALRf92Ze6578uV0dBpy5dxE4bXxlUYbetPYSchc4s8JhGlYjYeW78HoQDS7qnY463a 1bX+XnQJOmGgJ77BOIhfMQUVsJBaPloBvMiOW8nFQqyRQwuyaqW5gI6CMpHcsKc/3f/a dgTmweMeoCjEEBfocOBZapw3ljIaRIevqxtt8ZKZ8z9PK5DoUgfLbv11Jy4dD3UBsPFZ IegkHG/QlZ0/UT3tH5d5Qx2Zn12kunaIRsX+u1JPAiEkCOJt4tJxoNLjgza4YrpZ8VZL qLCQ== X-Gm-Message-State: AMCzsaXFP12mYWCARYxn2V9EXrVZMPBO3BJQcBJsa1ZNl6i45wvAiFiB XGlJtlXHceipRh4dB+0Rav1owg== X-Google-Smtp-Source: ABhQp+Q2tY3fA32pQCGlDBghYHDpaIeMrOmn+0uRpzVlvWI80kYmLoRwlITCfGqOZXy4OYphIsZwow== X-Received: by 10.101.74.4 with SMTP id s4mr1579887pgq.259.1509149401075; Fri, 27 Oct 2017 17:10:01 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.09.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:00 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 01/13] vxlan: Move gro_cells_init to ndo_init Date: Fri, 27 Oct 2017 17:09:25 -0700 Message-Id: <20171028000937.2631-2-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Move gro_cells_init to ndo_init and properly check return value. Signed-off-by: Tom Herbert Reported-by: Eric Dumazet --- drivers/net/vxlan.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index d7c49cf1d5e9..a54dd3d2a824 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2392,10 +2392,19 @@ static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan, /* Setup stats when device is created */ static int vxlan_init(struct net_device *dev) { + struct vxlan_dev *vxlan = netdev_priv(dev); + int err; + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) return -ENOMEM; + err = gro_cells_init(&vxlan->gro_cells, dev); + if (err) { + free_percpu(dev->tstats); + return err; + } + return 0; } @@ -2653,8 +2662,6 @@ static void vxlan_setup(struct net_device *dev) vxlan->dev = dev; - gro_cells_init(&vxlan->gro_cells, dev); - for (h = 0; h < FDB_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vxlan->fdb_head[h]); } From patchwork Sat Oct 28 00:09:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831550 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="XXbhdTqc"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1N94PRZz9t4X for ; Sat, 28 Oct 2017 11:10:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751393AbdJ1AKK (ORCPT ); Fri, 27 Oct 2017 20:10:10 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:50098 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751164AbdJ1AKE (ORCPT ); Fri, 27 Oct 2017 20:10:04 -0400 Received: by mail-pf0-f195.google.com with SMTP id i5so6013208pfe.6 for ; Fri, 27 Oct 2017 17:10:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9+c6G5cK3b+2NcVRVglsAaFnCDcKz3e3upR5DDBI+DA=; b=XXbhdTqcCfZytKwuICAcdt8gsekTQF/S0NoHo8rr1AUvfNl2ElbQ5GlZy5yzugEQl9 5VXiizo9bqXcQzQd3T9x8V/ZOle4jWPGImNkWgCIXdnkGESWe+j4nKQ/6Yw4mHQq6dvr me0SSSr2M6vEckUXbCnjA7TkPnEBlt1ja+JNET2H5Buwe9671uKzYTN+EZ03Cc1EhaJ5 VqsVCXN92Md6+/NfJl5PFX8bUOi2Drbihfh89fcz6X7ym8dbqKr7/sUkzFPdVHR32L45 IHqQ3KDw4V43n9c9i75bxU9tgRvRyCoBDYiUWfXAthZkGosPO8CSBUYT0/mxhdoqkaTV 6u/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:in-reply-to :references; bh=9+c6G5cK3b+2NcVRVglsAaFnCDcKz3e3upR5DDBI+DA=; b=aXfRD1KnGmJSiawHkdphtsafFx2LM9a4amflS8OOiU1oHltbPuQVzUzALG79PYENrM g663CVXk0ojIQA+qYl/RGsWJHFNsLb+hok8q7TnCjqu3P5L0kxD96ezsqoqLwHEpeqxV lj7bOzkXUlQXVtSxt4/IofbeBbaZEonXQ4mYmAkMANDYNC0VkSjo2e21x0dkefHXz4Og U+acohu82XgSqesFJ9tOukJ1HxJVcz8bH/1fl4WJ5STyncU03ry+gzQNcv9jVSYCdqMH kCcdH4K5a/59M3qRjAIPmeYivoIhRtfJU/RBG6MriSN3fRnG5BNwEbFY3meruqoIyw+M s9OQ== X-Gm-Message-State: AMCzsaUboboB4nzDTJWc41AfEtCKTj0XSrtJVm/Qq0mDSADnWir16uoh HVVx8GGZcNpQWTD3xSjc2t8ooA== X-Google-Smtp-Source: ABhQp+ThTbQVS03/5VYKlqxxAg6bsK1NgDy9KoJqqG2zHh+xAoel3ZaHDmAe4QEVKhT0j5/POiRokQ== X-Received: by 10.99.106.67 with SMTP id f64mr1683792pgc.101.1509149403850; Fri, 27 Oct 2017 17:10:03 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:02 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 02/13] iptunnel: Add common functions to get a tunnel route Date: Fri, 27 Oct 2017 17:09:26 -0700 Message-Id: <20171028000937.2631-3-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org ip_tunnel_get_route and ip6_tnl_get_route are created to return routes for a tunnel. These functions are derived from the VXLAN functions. Signed-off-by: Tom Herbert --- include/net/ip6_tunnel.h | 31 +++++++++++++++++++++++++++++++ include/net/ip_tunnels.h | 32 ++++++++++++++++++++++++++++++++ net/ipv4/ip_tunnel.c | 40 ++++++++++++++++++++++++++++++++++++++++ net/ipv6/ip6_tunnel.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h index 08fbc7f7d8d7..eb7ddc06b5e3 100644 --- a/include/net/ip6_tunnel.h +++ b/include/net/ip6_tunnel.h @@ -142,6 +142,37 @@ __u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr, struct net *ip6_tnl_get_link_net(const struct net_device *dev); int ip6_tnl_get_iflink(const struct net_device *dev); int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu); +struct dst_entry *__ip6_tnl_get_route(struct net_device *dev, + struct sk_buff *skb, struct sock *sk, + u8 proto, int oif, u8 tos, __be32 label, + const struct in6_addr *daddr, + struct in6_addr *saddr, + __be16 dport, __be16 sport, + struct dst_cache *dst_cache, + bool use_cache); + +static inline struct dst_entry *ip6_tnl_get_route(struct net_device *dev, + struct sk_buff *skb, struct sock *sk, u8 proto, + int oif, u8 tos, __be32 label, + const struct in6_addr *daddr, + struct in6_addr *saddr, + __be16 dport, __be16 sport, + struct dst_cache *dst_cache, + const struct ip_tunnel_info *info) +{ + bool use_cache = (ip_tunnel_dst_cache_usable(skb, info) && + (!tos || info)); + + if (use_cache) { + struct dst_entry *ndst = dst_cache_get_ip6(dst_cache, saddr); + + if (ndst) + return ndst; + } + + return __ip6_tnl_get_route(dev, skb, sk, proto, oif, tos, label, daddr, + saddr, dport, sport, dst_cache, use_cache); +} static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, struct net_device *dev) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index b41a1e057fce..2b05ae24f4f6 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -285,6 +285,38 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], struct ip_tunnel_parm *p, __u32 fwmark); void ip_tunnel_setup(struct net_device *dev, unsigned int net_id); +struct rtable *__ip_tunnel_get_route(struct net_device *dev, + struct sk_buff *skb, u8 proto, + int oif, u8 tos, + __be32 daddr, __be32 *saddr, + __be16 dport, __be16 sport, + struct dst_cache *dst_cache, + bool use_cache); + +static inline struct rtable *ip_tunnel_get_route(struct net_device *dev, + struct sk_buff *skb, u8 proto, + int oif, u8 tos, + __be32 daddr, __be32 *saddr, + __be16 dport, __be16 sport, + struct dst_cache *dst_cache, + const struct ip_tunnel_info *info) +{ + bool use_cache = (ip_tunnel_dst_cache_usable(skb, info) && + (!tos || info)); + + if (use_cache) { + struct rtable *rt; + + rt = dst_cache_get_ip4(dst_cache, saddr); + if (rt) + return rt; + } + + return __ip_tunnel_get_route(dev, skb, proto, oif, tos, + daddr, saddr, dport, sport, + dst_cache, use_cache); +} + struct ip_tunnel_encap_ops { size_t (*encap_hlen)(struct ip_tunnel_encap *e); int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e, diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index fe6fee728ce4..c97525d8dff9 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -935,6 +935,46 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) } EXPORT_SYMBOL_GPL(ip_tunnel_ioctl); +struct rtable *__ip_tunnel_get_route(struct net_device *dev, + struct sk_buff *skb, u8 proto, + int oif, u8 tos, + __be32 daddr, __be32 *saddr, + __be16 dport, __be16 sport, + struct dst_cache *dst_cache, + bool use_cache) +{ + struct rtable *rt = NULL; + struct flowi4 fl4; + + memset(&fl4, 0, sizeof(fl4)); + fl4.flowi4_oif = oif; + fl4.flowi4_tos = RT_TOS(tos); + fl4.flowi4_mark = skb->mark; + fl4.flowi4_proto = proto; + fl4.daddr = daddr; + fl4.saddr = *saddr; + fl4.fl4_dport = dport; + fl4.fl4_sport = sport; + + rt = ip_route_output_key(dev_net(dev), &fl4); + if (likely(!IS_ERR(rt))) { + if (rt->dst.dev == dev) { + netdev_dbg(dev, "circular route to %pI4\n", &daddr); + ip_rt_put(rt); + return ERR_PTR(-ELOOP); + } + + *saddr = fl4.saddr; + if (use_cache) + dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr); + } else { + netdev_dbg(dev, "no route to %pI4\n", &daddr); + return ERR_PTR(-ENETUNREACH); + } + return rt; +} +EXPORT_SYMBOL_GPL(__ip_tunnel_get_route); + int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict) { struct ip_tunnel *tunnel = netdev_priv(dev); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 439d65f7e094..89114d4f8756 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1667,6 +1667,48 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; } +struct dst_entry *__ip6_tnl_get_route(struct net_device *dev, + struct sk_buff *skb, struct sock *sk, + u8 proto, int oif, u8 tos, __be32 label, + const struct in6_addr *daddr, + struct in6_addr *saddr, + __be16 dport, __be16 sport, + struct dst_cache *dst_cache, + bool use_cache) +{ + struct dst_entry *ndst; + struct flowi6 fl6; + int err; + + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_oif = oif; + fl6.daddr = *daddr; + fl6.saddr = *saddr; + fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label); + fl6.flowi6_mark = skb->mark; + fl6.flowi6_proto = proto; + fl6.fl6_dport = dport; + fl6.fl6_sport = sport; + + err = ipv6_stub->ipv6_dst_lookup(dev_net(dev), sk, &ndst, &fl6); + if (unlikely(err < 0)) { + netdev_dbg(dev, "no route to %pI6\n", daddr); + return ERR_PTR(-ENETUNREACH); + } + + if (unlikely(ndst->dev == dev)) { + netdev_dbg(dev, "circular route to %pI6\n", daddr); + dst_release(ndst); + return ERR_PTR(-ELOOP); + } + + *saddr = fl6.saddr; + if (use_cache) + dst_cache_set_ip6(dst_cache, ndst, saddr); + return ndst; +} +EXPORT_SYMBOL_GPL(__ip6_tnl_get_route); + /** * ip6_tnl_change_mtu - change mtu manually for tunnel device * @dev: virtual device associated with tunnel From patchwork Sat Oct 28 00:09:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831551 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="1RIUeNEV"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1NB3Jrlz9t4b for ; Sat, 28 Oct 2017 11:10:18 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751465AbdJ1AKM (ORCPT ); Fri, 27 Oct 2017 20:10:12 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:45999 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751326AbdJ1AKH (ORCPT ); Fri, 27 Oct 2017 20:10:07 -0400 Received: by mail-pg0-f65.google.com with SMTP id b192so6419097pga.2 for ; Fri, 27 Oct 2017 17:10:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=KurM9DxJ1gf+MwdiMYfJN00MtSE0BxFlHdI4JpARNqk=; b=1RIUeNEVW6fz+YyXAjuONailxOP77i/X+2QOnNFvioNlMR5dyjFz6WT5t0WnY48NNV kTmnP/T2VuHXQkp2fsoYadbD5J6lKVx5Viabu3mds98vhwbGeFLZ5tbrEqLG6suxV45i KMJKlXzPHP3cacWffyMvlM+m53IYqD/u/1mNwHbe76VRw9Obl3ML8Hx4OFt7PkHmZrJ/ MCVoiD0fMhVGjbx7Ts2XK1KuSP6mwG8aWL652cinp/BLLXGgFFoXXch65riLv+vFr/iU zwX+24hGeOjzFR4GYBCIuJsaNvYaQFR4nytVofhk9l7b9SMrJitALtJqLX+avX+z5+8I 7kuQ== 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:in-reply-to :references; bh=KurM9DxJ1gf+MwdiMYfJN00MtSE0BxFlHdI4JpARNqk=; b=q6DV91b+P9P55Q6gtqhRClZqrWfZs4wDh+9A99bichgUwp2lc+jIaEe2iFIojo2uQA owbeUWQfDWibFKa9wwbbsjqkc7M0bLW9RHU8XLaYzFu23BDvonTfimjEgN0lU7xrslJT 65XG9EV147S7xXZKbTfxRub0hNz+x8ygdnzSP4CwS8/pkOEdiuuAWpeXnzALgLEy9n53 ZKGnHexG0P8sDl9Q2D2oFAlEy2cXmMrtNo0B7gCP9RqdbfLd8mBXMjWHGHIcV7azeSAu B5FQSwuYE0lPKDGimwg6HH+QRJmG6lKcOVifCPQPgOLi6HUqX0YcPhgrdhGhUaG+KaFi n6gg== X-Gm-Message-State: AMCzsaXvEWcKSDVcHBrpIOLlDFEkJV6qnsGqQJRmwnT1VqbevgwccvSJ xJaNSFNG98TnRAEC3SoeueYGpg== X-Google-Smtp-Source: ABhQp+Thl2pNEWc+j06MwXjiZN8m97RAfB/NIdQIUXnxKpS/U0PfJ/ZFDQbq3MAsXOzyCcamBoDL/g== X-Received: by 10.84.177.36 with SMTP id w33mr1594090plb.215.1509149406718; Fri, 27 Oct 2017 17:10:06 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:05 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 03/13] vxlan: Call common functions to get tunnel routes Date: Fri, 27 Oct 2017 17:09:27 -0700 Message-Id: <20171028000937.2631-4-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Call ip_tunnel_get_route and ip6_tnl_get_route to handle getting a route and dealing with the dst_cache. Signed-off-by: Tom Herbert --- drivers/net/vxlan.c | 84 ++++------------------------------------------------- 1 file changed, 5 insertions(+), 79 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a54dd3d2a824..5e5716052a95 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1867,47 +1867,11 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct net_device struct dst_cache *dst_cache, const struct ip_tunnel_info *info) { - bool use_cache = ip_tunnel_dst_cache_usable(skb, info); - struct rtable *rt = NULL; - struct flowi4 fl4; - if (!sock4) return ERR_PTR(-EIO); - if (tos && !info) - use_cache = false; - if (use_cache) { - rt = dst_cache_get_ip4(dst_cache, saddr); - if (rt) - return rt; - } - - memset(&fl4, 0, sizeof(fl4)); - fl4.flowi4_oif = oif; - fl4.flowi4_tos = RT_TOS(tos); - fl4.flowi4_mark = skb->mark; - fl4.flowi4_proto = IPPROTO_UDP; - fl4.daddr = daddr; - fl4.saddr = *saddr; - fl4.fl4_dport = dport; - fl4.fl4_sport = sport; - - rt = ip_route_output_key(vxlan->net, &fl4); - if (likely(!IS_ERR(rt))) { - if (rt->dst.dev == dev) { - netdev_dbg(dev, "circular route to %pI4\n", &daddr); - ip_rt_put(rt); - return ERR_PTR(-ELOOP); - } - - *saddr = fl4.saddr; - if (use_cache) - dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr); - } else { - netdev_dbg(dev, "no route to %pI4\n", &daddr); - return ERR_PTR(-ENETUNREACH); - } - return rt; + return ip_tunnel_get_route(dev, skb, IPPROTO_UDP, oif, tos, daddr, + saddr, dport, sport, dst_cache, info); } #if IS_ENABLED(CONFIG_IPV6) @@ -1922,50 +1886,12 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan, struct dst_cache *dst_cache, const struct ip_tunnel_info *info) { - bool use_cache = ip_tunnel_dst_cache_usable(skb, info); - struct dst_entry *ndst; - struct flowi6 fl6; - int err; - if (!sock6) return ERR_PTR(-EIO); - if (tos && !info) - use_cache = false; - if (use_cache) { - ndst = dst_cache_get_ip6(dst_cache, saddr); - if (ndst) - return ndst; - } - - memset(&fl6, 0, sizeof(fl6)); - fl6.flowi6_oif = oif; - fl6.daddr = *daddr; - fl6.saddr = *saddr; - fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label); - fl6.flowi6_mark = skb->mark; - fl6.flowi6_proto = IPPROTO_UDP; - fl6.fl6_dport = dport; - fl6.fl6_sport = sport; - - err = ipv6_stub->ipv6_dst_lookup(vxlan->net, - sock6->sock->sk, - &ndst, &fl6); - if (unlikely(err < 0)) { - netdev_dbg(dev, "no route to %pI6\n", daddr); - return ERR_PTR(-ENETUNREACH); - } - - if (unlikely(ndst->dev == dev)) { - netdev_dbg(dev, "circular route to %pI6\n", daddr); - dst_release(ndst); - return ERR_PTR(-ELOOP); - } - - *saddr = fl6.saddr; - if (use_cache) - dst_cache_set_ip6(dst_cache, ndst, saddr); - return ndst; + return ip6_tnl_get_route(dev, skb, sock6->sock->sk, IPPROTO_UDP, oif, + tos, label, daddr, saddr, dport, sport, + dst_cache, info); } #endif From patchwork Sat Oct 28 00:09:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831553 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="dC/+y6xD"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1NJ4jhKz9t4X for ; Sat, 28 Oct 2017 11:10:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751617AbdJ1AKT (ORCPT ); Fri, 27 Oct 2017 20:10:19 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:56556 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751381AbdJ1AKJ (ORCPT ); Fri, 27 Oct 2017 20:10:09 -0400 Received: by mail-pf0-f194.google.com with SMTP id b85so5996367pfj.13 for ; Fri, 27 Oct 2017 17:10:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=0Vs249g8KFibi/hTwDBA/hTAfGlB+QSLg+DbDOQBVYE=; b=dC/+y6xDHqnYBExBFAMciULesmZxNfmKTh3BjsXi501tOCr1VAC9fiqFMxNhZ5xW/4 8Dmd6uY88WCKF4Q2rW34xzWAjGi7TauIwDSc4TjBTIEZJOoZ8cSDhMqiQRpi26zMcFfR 1scbph6R5o2+x2lyjSVtTpplgh+/Z9ID9BmoviF6yMoZ+4BZOk/bVnkzXoMLfmVyoCHn kGTL6HMLtdKuFE9Bw2cUWZRKagEJlgh/hAAR+EraFV7Cne3Hnt2gYEiG1yomcxc3Rv8E imBrkcjBFhPy/lYA2XN5HCf3Ak45B/FQkzaq8lxb6IV3Embyj2JBxmiysMu/9xtGRZx0 fcHA== 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:in-reply-to :references; bh=0Vs249g8KFibi/hTwDBA/hTAfGlB+QSLg+DbDOQBVYE=; b=sPhGFnqKhg2olZTww55WPCKTnV5Rk/TGXjFi/0tPvFd56joP3oOSVn0mPf4NNV/28T e1UT7HztIychDhHGlEhGOBTRIJu/MInHdbwMqeQcr/+z8ypanGNgGeIr3cRnR9Jp7lsN tFyALgY26iNRDdH4AePpwFUEXqw8xdVvQGKcLFkcZB5uHEcJzb7YbtAxTr62kDnWOMcK vyT24TtmLjm21+85ALfPmE4p6DCRkbhdww1pHD5ALHUHDlNmPaZ3XNaU0OjaQhKAl6AF cf7UHKTyOh2ToFCoZ+/Vo552UnREPaKsP2XPp+kMLvqpbTyzODRGoAVI92QAXKqBZ08s D1yQ== X-Gm-Message-State: AMCzsaXPy5pkITzs4lpvHa6/wd83KTOmBa/lrRs0eKYlnsfwoXLCyBll b1HG5Zym0mZbRxExal5AA8p8YQ== X-Google-Smtp-Source: ABhQp+QucvwndUFBxd7npcASjWB5JPGMO2h+fZ6tpEx2/8yHMWEb0hbQtpD1M4Qyd4ZbokLkNluQ9g== X-Received: by 10.99.116.22 with SMTP id p22mr607181pgc.372.1509149409034; Fri, 27 Oct 2017 17:10:09 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:08 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 04/13] gtp: Call common functions to get tunnel routes and add dst_cache Date: Fri, 27 Oct 2017 17:09:28 -0700 Message-Id: <20171028000937.2631-5-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Call ip_tunnel_get_route and dst_cache to pdp context which should improve performance by obviating the need to perform a route lookup on every packet. Signed-off-by: Tom Herbert --- drivers/net/gtp.c | 62 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index f38e32a7ec9c..6dabd605607c 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -63,6 +63,8 @@ struct pdp_ctx { atomic_t tx_seq; struct rcu_head rcu_head; + + struct dst_cache dst_cache; }; /* One instance of the GTP device. */ @@ -379,20 +381,6 @@ static void gtp_dev_uninit(struct net_device *dev) free_percpu(dev->tstats); } -static struct rtable *ip4_route_output_gtp(struct flowi4 *fl4, - const struct sock *sk, - __be32 daddr) -{ - memset(fl4, 0, sizeof(*fl4)); - fl4->flowi4_oif = sk->sk_bound_dev_if; - fl4->daddr = daddr; - fl4->saddr = inet_sk(sk)->inet_saddr; - fl4->flowi4_tos = RT_CONN_FLAGS(sk); - fl4->flowi4_proto = sk->sk_protocol; - - return ip_route_output_key(sock_net(sk), fl4); -} - static inline void gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) { int payload_len = skb->len; @@ -479,6 +467,8 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, struct rtable *rt; struct flowi4 fl4; struct iphdr *iph; + struct sock *sk; + __be32 saddr; __be16 df; int mtu; @@ -498,19 +488,30 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, } netdev_dbg(dev, "found PDP context %p\n", pctx); - rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->peer_addr_ip4.s_addr); - if (IS_ERR(rt)) { - netdev_dbg(dev, "no route to SSGN %pI4\n", - &pctx->peer_addr_ip4.s_addr); - dev->stats.tx_carrier_errors++; - goto err; - } + sk = pctx->sk; + saddr = inet_sk(sk)->inet_saddr; - if (rt->dst.dev == dev) { - netdev_dbg(dev, "circular route to SSGN %pI4\n", - &pctx->peer_addr_ip4.s_addr); - dev->stats.collisions++; - goto err_rt; + /* Source address returned by route lookup is ignored since + * we get the address from a socket. + */ + rt = ip_tunnel_get_route(dev, skb, sk->sk_protocol, + sk->sk_bound_dev_if, RT_CONN_FLAGS(sk), + pctx->peer_addr_ip4.s_addr, &saddr, + pktinfo->gtph_port, pktinfo->gtph_port, + &pctx->dst_cache, NULL); + + if (IS_ERR(rt)) { + if (rt == ERR_PTR(-ELOOP)) { + netdev_dbg(dev, "circular route to SSGN %pI4\n", + &pctx->peer_addr_ip4.s_addr); + dev->stats.collisions++; + goto err_rt; + } else { + netdev_dbg(dev, "no route to SSGN %pI4\n", + &pctx->peer_addr_ip4.s_addr); + dev->stats.tx_carrier_errors++; + goto err; + } } skb_dst_drop(skb); @@ -543,7 +544,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, goto err_rt; } - gtp_set_pktinfo_ipv4(pktinfo, pctx->sk, iph, pctx, rt, &fl4, dev); + gtp_set_pktinfo_ipv4(pktinfo, sk, iph, pctx, rt, &fl4, dev); gtp_push_header(skb, pktinfo); return 0; @@ -917,6 +918,7 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk, struct pdp_ctx *pctx; bool found = false; __be32 ms_addr; + int err; ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size; @@ -951,6 +953,12 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk, if (pctx == NULL) return -ENOMEM; + err = dst_cache_init(&pctx->dst_cache, GFP_KERNEL); + if (err) { + kfree(pctx); + return err; + } + sock_hold(sk); pctx->sk = sk; pctx->dev = gtp->dev; From patchwork Sat Oct 28 00:09:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831552 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="mZr9mMfS"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1NF2zRQz9t4X for ; Sat, 28 Oct 2017 11:10:21 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751560AbdJ1AKR (ORCPT ); Fri, 27 Oct 2017 20:10:17 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:46006 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751326AbdJ1AKN (ORCPT ); Fri, 27 Oct 2017 20:10:13 -0400 Received: by mail-pg0-f67.google.com with SMTP id b192so6419232pga.2 for ; Fri, 27 Oct 2017 17:10:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=l7zd9/QVFOoCtjMrUcz5qK+0Oh109N5V5VJJNrKIpaQ=; b=mZr9mMfSCn7sNzQlzsDH6qwqL/vPfACxDW7mBrK+/wgrQGBloJbT1DR7Q6RE6M9F6O pkd35C9KSVJ/kRd7nmIIt8+glLCFRfbn/Ac9BtepHTMjKH0rDdnUkdnuhqzvCmTh1fi/ uqhQM1SWOfXQuh/0k22lNBXkhLQcCo2vBY2D66UoSJYW6IWXCZi6JCXd0gkOr7PwthID j/G3gJoFaRjgvuBLwFqP8bwDaCu8g6vgmPKZCarDlZOYEG/xLLhl5TKF1FwqlyFRnwVJ ReLiVHJyB+sABiCnwEVMkoPTFawMrwf3E4+Pg+fEuNxLxYCadGVVXfokVGldZ/euhzyP 3UkA== 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:in-reply-to :references; bh=l7zd9/QVFOoCtjMrUcz5qK+0Oh109N5V5VJJNrKIpaQ=; b=deCMIQEExjrC9keC1eC1X3MRlNQnNeyzqABbv83T6KEkGoG6l+71CC7ADhAPKtWuyE NoH2TPTI37iYPDCJTNSL5mUMBYcLYgPCdDR+ctX+aiUe567WskqdkhHHLAUvHlvIohLB xX8fqXqMB1r+8gfXGEYTpQBcbJTWKamCJFQvVV4m4wFOyCS2GdTSradJN0RDlqBmTqF1 NsTl3Y6VPmX3chshDJgkk5h+i42UNFHanPdkK9mOArb9wWTWZdorUS7338AfkkJ2vnwv U8tW9wP/4dTWmxomIaDh4RAiOIVCiC1HxRanROzc0o3iD/wGyV365X2N3AUXE7pvXGSU PeOA== X-Gm-Message-State: AMCzsaVT6l98LytK30QL1AcTryqC6rZ1lXVFoAx/e04IfiISTZmQA4s2 NLPUP3pKwBzL9ePGPh+1CEtRag== X-Google-Smtp-Source: ABhQp+SEOCVPxkwRJGqpLb07i69FX2erM9zO0Sn/HL2VuLRVGYKCOyYvflWyxun0shvSwWXFlkFxAg== X-Received: by 10.101.67.200 with SMTP id n8mr1633651pgp.228.1509149412527; Fri, 27 Oct 2017 17:10:12 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:11 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 05/13] iptunnel: Generalize tunnel update pmtu Date: Fri, 27 Oct 2017 17:09:29 -0700 Message-Id: <20171028000937.2631-6-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add __iptunnel_update_pmtu exported function which does not take an iptunnel argument but instead includes the fields from the iptunnel structure as arguments which are needed in the function. iptunnel_update_pmtu was modified to call __iptunnel_update_pmtu. Signed-off-by: Tom Herbert --- include/net/ip_tunnels.h | 4 ++++ net/ipv4/ip_tunnel.c | 30 ++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 2b05ae24f4f6..be675836d35a 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -317,6 +317,10 @@ static inline struct rtable *ip_tunnel_get_route(struct net_device *dev, dst_cache, use_cache); } +int __iptunnel_update_pmtu(struct net_device *dev, struct sk_buff *skb, + struct dst_entry *dst, __be16 df, + const struct iphdr *inner_iph, int hlen, u32 daddr); + struct ip_tunnel_encap_ops { size_t (*encap_hlen)(struct ip_tunnel_encap *e); int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e, diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index c97525d8dff9..0ee84ca76e0f 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -506,17 +506,16 @@ int ip_tunnel_encap_setup(struct ip_tunnel *t, } EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup); -static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, - struct rtable *rt, __be16 df, - const struct iphdr *inner_iph) +int __iptunnel_update_pmtu(struct net_device *dev, struct sk_buff *skb, + struct dst_entry *dst, __be16 df, + const struct iphdr *inner_iph, int hlen, u32 daddr) { - struct ip_tunnel *tunnel = netdev_priv(dev); - int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len; + int pkt_size = skb->len - hlen - dev->hard_header_len; int mtu; if (df) - mtu = dst_mtu(&rt->dst) - dev->hard_header_len - - sizeof(struct iphdr) - tunnel->hlen; + mtu = dst_mtu(dst) - dev->hard_header_len + - sizeof(struct iphdr) - hlen; else mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; @@ -538,8 +537,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, if (rt6 && mtu < dst_mtu(skb_dst(skb)) && mtu >= IPV6_MIN_MTU) { - if ((tunnel->parms.iph.daddr && - !ipv4_is_multicast(tunnel->parms.iph.daddr)) || + if ((daddr && !ipv4_is_multicast(daddr)) || rt6->rt6i_dst.plen == 128) { rt6->rt6i_flags |= RTF_MODIFIED; dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); @@ -555,6 +553,17 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, #endif return 0; } +EXPORT_SYMBOL(__iptunnel_update_pmtu); + +static int iptunnel_update_pmtu(struct net_device *dev, struct sk_buff *skb, + struct rtable *rt, __be16 df, + const struct iphdr *inner_iph) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + + return __iptunnel_update_pmtu(dev, skb, &rt->dst, df, inner_iph, + tunnel->hlen, tunnel->parms.iph.daddr); +} void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, u8 proto) { @@ -739,7 +748,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) { + if (iptunnel_update_pmtu(dev, skb, rt, tnl_params->frag_off, + inner_iph)) { ip_rt_put(rt); goto tx_error; } From patchwork Sat Oct 28 00:09:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831561 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="tHkdvKDf"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1P14RTcz9t5C for ; Sat, 28 Oct 2017 11:11:01 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751975AbdJ1AK7 (ORCPT ); Fri, 27 Oct 2017 20:10:59 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:56563 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751486AbdJ1AKP (ORCPT ); Fri, 27 Oct 2017 20:10:15 -0400 Received: by mail-pf0-f195.google.com with SMTP id b85so5996501pfj.13 for ; Fri, 27 Oct 2017 17:10:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wuq3bDb3erCooDmo140kAxbmG1UYyscgKF8vLIHDcvM=; b=tHkdvKDfYzC5D0YWzI9Gg7tlLB4nV8zuK3ZncIkBabF2HSYmleFBdQYXv0LAf4fd5q n9N3LRGHOGWfRjmtT4rnoFME++yxX/JeNlP+s9VBKh+uRql/H+JJ50klWv8kJso35tZU iM2EaTZJqIhwVJxnUetjz2Yxksd08wQ+W6wr4cXe5ni2owKfnG27HbTHkxDWGsbLGkBK GbB14Tzjw7INq/rFEpV0QbqX5lCfbSnW10T9orGsBbZB7j9Mx86m6tCL5WU8QSeNRlZv nWJYo9yY4R/NuHrOB93ppz2JPT6+64dVZmSFsQX9gQpoPi7iX7ERSC4UQL2/nRZrzJVy iLJQ== 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:in-reply-to :references; bh=wuq3bDb3erCooDmo140kAxbmG1UYyscgKF8vLIHDcvM=; b=dQ/FmbX+9/LtwwyFuI+acgqILqHyZ7XA8QBzc0Ysyotw5SpI78awPzRGF5XZnohBzV xN8F3QmfChJP9rdOKiHhEX92vbG1GNQeSt4IFOwx5WB0rvP5rHG3PnGsKPsF2XGSjNsS rksh1oduePkiJaRis5lkDgwoUWPzfiN+p6DkY2uzYKIM8QaqubC1JYjVAmVGt4Zee0U7 UT/vLxq6ea2mcJz28TOZJ6wpXk9Tda792ArjDwCxiSg0z5UThU1lQSYobSLRq3P8G+bE sDiX/VEPUesoDhwzRucWPe8+JjCQjmoVBM8/S4qYVYyb+7vShR9n6SebncUnTG8YcEgn mT1A== X-Gm-Message-State: AMCzsaVoKgtyr+EnqaTg+bUjF5rQ2wFc/yKjtbLBICRA6a9XhW1cnhfT VtKXier5cPJlCDhdcGFx64Q+miG5 X-Google-Smtp-Source: ABhQp+QVuegJcE0rv6DT487HFEtDywpus8L2vnUlkNU3KG8XyqWmGSJghCgboGjT9q1IPWKbU2H3Ag== X-Received: by 10.98.66.206 with SMTP id h75mr1939934pfd.76.1509149415240; Fri, 27 Oct 2017 17:10:15 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:14 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 06/13] gtp: Change to use gro_cells Date: Fri, 27 Oct 2017 17:09:30 -0700 Message-Id: <20171028000937.2631-7-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Call gro_cells_receive instead of netif_rx. Signed-off-by: Tom Herbert --- drivers/net/Kconfig | 1 + drivers/net/gtp.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 0936da592e12..720c2af0bb88 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -214,6 +214,7 @@ config GTP tristate "GPRS Tunneling Protocol datapath (GTP-U)" depends on INET && NET_UDP_TUNNEL select NET_IP_TUNNEL + select GRO_CELLS ---help--- This allows one to create gtp virtual interfaces that provide the GPRS Tunneling Protocol datapath (GTP-U). This tunneling protocol diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 6dabd605607c..265fa9fdbf3d 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -80,6 +80,8 @@ struct gtp_dev { unsigned int hash_size; struct hlist_head *tid_hash; struct hlist_head *addr_hash; + + struct gro_cells gro_cells; }; static unsigned int gtp_net_id __read_mostly; @@ -189,6 +191,7 @@ static bool gtp_check_ms(struct sk_buff *skb, struct pdp_ctx *pctx, static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen, unsigned int role) { + struct gtp_dev *gtp = netdev_priv(pctx->dev); struct pcpu_sw_netstats *stats; if (!gtp_check_ms(skb, pctx, hdrlen, role)) { @@ -217,7 +220,8 @@ static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, stats->rx_bytes += skb->len; u64_stats_update_end(&stats->syncp); - netif_rx(skb); + gro_cells_receive(>p->gro_cells, skb); + return 0; } @@ -363,6 +367,7 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb) static int gtp_dev_init(struct net_device *dev) { struct gtp_dev *gtp = netdev_priv(dev); + int err; gtp->dev = dev; @@ -370,6 +375,12 @@ static int gtp_dev_init(struct net_device *dev) if (!dev->tstats) return -ENOMEM; + err = gro_cells_init(>p->gro_cells, dev); + if (err) { + free_percpu(dev->tstats); + return err; + } + return 0; } @@ -611,6 +622,8 @@ static const struct net_device_ops gtp_netdev_ops = { static void gtp_link_setup(struct net_device *dev) { + struct gtp_dev *gtp = netdev_priv(dev); + dev->netdev_ops = >p_netdev_ops; dev->needs_free_netdev = true; @@ -630,6 +643,8 @@ static void gtp_link_setup(struct net_device *dev) sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct gtp0_header); + + gro_cells_init(>p->gro_cells, dev); } static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize); @@ -686,6 +701,7 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head) { struct gtp_dev *gtp = netdev_priv(dev); + gro_cells_destroy(>p->gro_cells); gtp_encap_disable(gtp); gtp_hashtable_free(gtp); list_del_rcu(>p->list); From patchwork Sat Oct 28 00:09:31 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831554 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="tLdUysLE"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1NK3wcWz9t4b for ; Sat, 28 Oct 2017 11:10:25 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751654AbdJ1AKV (ORCPT ); Fri, 27 Oct 2017 20:10:21 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:49780 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751561AbdJ1AKS (ORCPT ); Fri, 27 Oct 2017 20:10:18 -0400 Received: by mail-pg0-f65.google.com with SMTP id g6so6410379pgn.6 for ; Fri, 27 Oct 2017 17:10:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Yt7qSl9goI+Lk0qZT13QCDfY6HlvRnvppPd+geOx7Dc=; b=tLdUysLELzweh1AoHn5EVVbl3Rxlbii2zGfsSeNS1sEawlYQbEfsRTauyKr9QK+q9H yn0Ep04IMJx15yg3z2u81NBfGvGA/Tsy7h0U9j2GPJV4zSfGXBa/YXKXfyDO4bv+Q7gD mSGeE9Vu34RsREJsdXEx0n0o/CHWNpPLUUNBtSk3MGVenS+whGy3sfRSTZ6oNg5tE2Ke qokShu2GJCU88ZKL4eoKEGQqXexQmUtRSdUlFd6Nx/XRASEZVhmPfFLbewiGmI/kdMk3 QFDSTB4hH607ESwgvqBNYaMWCzZiROm9/l52LEmcFUsrUVuphNhEfGU8iaIytUgSVGc8 KofA== 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:in-reply-to :references; bh=Yt7qSl9goI+Lk0qZT13QCDfY6HlvRnvppPd+geOx7Dc=; b=J1pS0zJfIGgsbOFZx+dehkN9JkkwCuFBkY4fWc50KiD6jI/N5LtwFQwZMCaTHhTbH0 KphHvnIBuzO1LXlvKYfiUS0teNt3OHI/WcyeqhFXS7YgYHGbgs6PV81448elNwjc5Fa9 iymr77nF+2z9H/Xzj9PV6QG8/kHGgBJPol4Wyql30GH406xgOvrcIQPD7miv3Bwr9Vz5 zUsWia1+a4mP9/d4n7bVgsIXt/SQ3xiNKPULaoNi9hlD+NxYcrI7zt4fJffyS1qIcPGa 5aDMiScN3j+/9+fAI1WQ7SaiBwMtXgmmDaGxIm9hCi7krNOa4un8idJRabNDcfZCn44N NvPA== X-Gm-Message-State: AMCzsaVBO+deW2sSTczh8Tw0op6Fi/mkoW2E3MswQLt7PeyHkoqEqzMJ 0FKHz6BGcHJEIChfIBIzfBxT6w== X-Google-Smtp-Source: ABhQp+R4mSOWqrwcfT6h5nA9WJTySC2s9dlpPT8v8sFyFnp0mXT7GAJ9L2RCY7lCrnQ1wjxIRPRzbg== X-Received: by 10.98.217.138 with SMTP id b10mr1970558pfl.39.1509149417522; Fri, 27 Oct 2017 17:10:17 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:16 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 07/13] gtp: Use goto for exceptions in gtp_udp_encap_recv funcs Date: Fri, 27 Oct 2017 17:09:31 -0700 Message-Id: <20171028000937.2631-8-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Consolidate return logic to make it easier to extend. Signed-off-by: Tom Herbert --- drivers/net/gtp.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 265fa9fdbf3d..2daf434ae543 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -234,23 +234,27 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) struct pdp_ctx *pctx; if (!pskb_may_pull(skb, hdrlen)) - return -1; + goto drop; gtp0 = (struct gtp0_header *)(skb->data + sizeof(struct udphdr)); if ((gtp0->flags >> 5) != GTP_V0) - return 1; + goto pass; if (gtp0->type != GTP_TPDU) - return 1; + goto pass; pctx = gtp0_pdp_find(gtp, be64_to_cpu(gtp0->tid)); if (!pctx) { netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb); - return 1; + goto pass; } return gtp_rx(pctx, skb, hdrlen, gtp->role); +drop: + return -1; +pass: + return 1; } static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) @@ -261,15 +265,15 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) struct pdp_ctx *pctx; if (!pskb_may_pull(skb, hdrlen)) - return -1; + goto drop; gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); if ((gtp1->flags >> 5) != GTP_V1) - return 1; + goto pass; if (gtp1->type != GTP_TPDU) - return 1; + goto pass; /* From 29.060: "This field shall be present if and only if any one or * more of the S, PN and E flags are set.". @@ -282,17 +286,21 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) /* Make sure the header is larger enough, including extensions. */ if (!pskb_may_pull(skb, hdrlen)) - return -1; + goto drop; gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid)); if (!pctx) { netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb); - return 1; + goto drop; } return gtp_rx(pctx, skb, hdrlen, gtp->role); +drop: + return -1; +pass: + return 1; } static void gtp_encap_destroy(struct sock *sk) From patchwork Sat Oct 28 00:09:32 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831560 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="GWtW9plb"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1Nr5lYpz9t4X for ; Sat, 28 Oct 2017 11:10:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751942AbdJ1AKu (ORCPT ); Fri, 27 Oct 2017 20:10:50 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:48828 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751619AbdJ1AKU (ORCPT ); Fri, 27 Oct 2017 20:10:20 -0400 Received: by mail-pf0-f195.google.com with SMTP id b79so6013880pfk.5 for ; Fri, 27 Oct 2017 17:10:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qoCGDf3ctS2CDmiVBF+2MRogivB+qCk+Rv/eD7ptuh0=; b=GWtW9plbveOxeIUZul5h3jbn+5t/G69hsKqJd4xMNZURBK5oDqpKnuC52lQre7XvpT LRi77/ycIYJ9CgaL4p4PbSR9CGL1TlnRkUw2OEBiHDnjgP6uOvgqJq4j8GAKLB2hvPXD KinTI/njk4qKONZXwD52yv/oYD/oTR6nNF3q1LbLUPgzPgFNeiiWvwi6irpb80u7ryca GQrCvGQL4G7Jvl2/XzvR6E2xjtA086m96e1i/NdqQx47mkFZJIHZIK9OvYspFEJ+Efr1 dURAR1RTPRjWREWcoAckc141S/Q51To0R67IMIGey2cFlayMfbYAhKDg2VuybhD4qFzw 3gxQ== 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:in-reply-to :references; bh=qoCGDf3ctS2CDmiVBF+2MRogivB+qCk+Rv/eD7ptuh0=; b=NDht06ypWrtVKriPkZnwyr5pGcBaFLLtlXWND1M5eAAqmZgrRKN71RO9awvD1iqh7/ GGT0pkf2L+KIx7RTaxPXw9MdkP+c6O+mGwEZHHkv9OClaYHyGl09ULafdh/M6I7xfo5X C9WalGEwXgtkVSC0hM74sMRVzpMOQfKt14XUZ9n0FqHNp7OGclwajWoMP+59O2KqdxNs iO1zyEyDx3emxFJ+bzl7aKts+xiB0vWSx0iBK1mgMtBU54vyw9WXovrg8bq+VYKnhT74 T3qakvKBhKaUYQLrZu1ZLKLlx44u8oWoALxAF3JyIKjmqNFBBHYNugoD6JxT3YugvlKQ 6O3Q== X-Gm-Message-State: AMCzsaVey2Mf6wpfkCE7rloE8zo7seKqQ3lDx7kGjrEBhxYsz7cMWght BNqBxec17S7Z1p3pW3xUYju5Q29x X-Google-Smtp-Source: ABhQp+SdXdhJFLB+ZetJobtQReaqnCLUtOaSkUPw4N9RgmNAiy/Y5fCh9Gmeo1F3kJPjebC/8UviXg== X-Received: by 10.98.192.6 with SMTP id x6mr1903815pff.170.1509149420006; Fri, 27 Oct 2017 17:10:20 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:19 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 08/13] gtp: udp recv clean up Date: Fri, 27 Oct 2017 17:09:32 -0700 Message-Id: <20171028000937.2631-9-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Create separate UDP receive functions for GTP version 0 and version 1. Set encap_rcv appropriately when configuring a socket. Signed-off-by: Tom Herbert --- drivers/net/gtp.c | 100 ++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 51 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 2daf434ae543..8b7014aa45c2 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -225,14 +225,20 @@ static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, return 0; } -/* 1 means pass up to the stack, -1 means drop and 0 means decapsulated. */ -static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) +/* UDP encapsulation receive handler for GTPv0-U . See net/ipv4/udp.c. + * Return codes: 0: success, <0: error, >0: pass up to userspace UDP socket. + */ +static int gtp0_udp_encap_recv(struct sock *sk, struct sk_buff *skb) { + struct gtp_dev *gtp = rcu_dereference_sk_user_data(sk); unsigned int hdrlen = sizeof(struct udphdr) + sizeof(struct gtp0_header); struct gtp0_header *gtp0; struct pdp_ctx *pctx; + if (!gtp) + goto pass; + if (!pskb_may_pull(skb, hdrlen)) goto drop; @@ -244,26 +250,41 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) if (gtp0->type != GTP_TPDU) goto pass; + netdev_dbg(gtp->dev, "received GTP0 packet\n"); + pctx = gtp0_pdp_find(gtp, be64_to_cpu(gtp0->tid)); if (!pctx) { netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb); goto pass; } - return gtp_rx(pctx, skb, hdrlen, gtp->role); + if (!gtp_rx(pctx, skb, hdrlen, gtp->role)) { + /* Successfully received */ + return 0; + } + drop: - return -1; + kfree_skb(skb); + return 0; + pass: return 1; } -static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) +/* UDP encapsulation receive handler for GTPv0-U . See net/ipv4/udp.c. + * Return codes: 0: success, <0: error, >0: pass up to userspace UDP socket. + */ +static int gtp1u_udp_encap_recv(struct sock *sk, struct sk_buff *skb) { + struct gtp_dev *gtp = rcu_dereference_sk_user_data(sk); unsigned int hdrlen = sizeof(struct udphdr) + sizeof(struct gtp1_header); struct gtp1_header *gtp1; struct pdp_ctx *pctx; + if (!gtp) + goto pass; + if (!pskb_may_pull(skb, hdrlen)) goto drop; @@ -275,6 +296,8 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) if (gtp1->type != GTP_TPDU) goto pass; + netdev_dbg(gtp->dev, "received GTP1 packet\n"); + /* From 29.060: "This field shall be present if and only if any one or * more of the S, PN and E flags are set.". * @@ -296,9 +319,15 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) goto drop; } - return gtp_rx(pctx, skb, hdrlen, gtp->role); + if (!gtp_rx(pctx, skb, hdrlen, gtp->role)) { + /* Successfully received */ + return 0; + } + drop: - return -1; + kfree_skb(skb); + return 0; + pass: return 1; } @@ -329,49 +358,6 @@ static void gtp_encap_disable(struct gtp_dev *gtp) gtp_encap_disable_sock(gtp->sk1u); } -/* UDP encapsulation receive handler. See net/ipv4/udp.c. - * Return codes: 0: success, <0: error, >0: pass up to userspace UDP socket. - */ -static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb) -{ - struct gtp_dev *gtp; - int ret = 0; - - gtp = rcu_dereference_sk_user_data(sk); - if (!gtp) - return 1; - - netdev_dbg(gtp->dev, "encap_recv sk=%p\n", sk); - - switch (udp_sk(sk)->encap_type) { - case UDP_ENCAP_GTP0: - netdev_dbg(gtp->dev, "received GTP0 packet\n"); - ret = gtp0_udp_encap_recv(gtp, skb); - break; - case UDP_ENCAP_GTP1U: - netdev_dbg(gtp->dev, "received GTP1U packet\n"); - ret = gtp1u_udp_encap_recv(gtp, skb); - break; - default: - ret = -1; /* Shouldn't happen. */ - } - - switch (ret) { - case 1: - netdev_dbg(gtp->dev, "pass up to the process\n"); - break; - case 0: - break; - case -1: - netdev_dbg(gtp->dev, "GTP packet has been dropped\n"); - kfree_skb(skb); - ret = 0; - break; - } - - return ret; -} - static int gtp_dev_init(struct net_device *dev) { struct gtp_dev *gtp = netdev_priv(dev); @@ -831,9 +817,21 @@ static struct sock *gtp_encap_enable_socket(int fd, int type, sk = sock->sk; sock_hold(sk); + switch (type) { + case UDP_ENCAP_GTP0: + tuncfg.encap_rcv = gtp0_udp_encap_recv; + break; + case UDP_ENCAP_GTP1U: + tuncfg.encap_rcv = gtp1u_udp_encap_recv; + break; + default: + pr_debug("Unknown encap type %u\n", type); + sk = ERR_PTR(-EINVAL); + goto out_sock; + } + tuncfg.sk_user_data = gtp; tuncfg.encap_type = type; - tuncfg.encap_rcv = gtp_encap_recv; tuncfg.encap_destroy = gtp_encap_destroy; setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg); From patchwork Sat Oct 28 00:09:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831555 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="0Nm1mHHp"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1NM1Nfpz9t4X for ; Sat, 28 Oct 2017 11:10:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751704AbdJ1AKZ (ORCPT ); Fri, 27 Oct 2017 20:10:25 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:50209 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751673AbdJ1AKW (ORCPT ); Fri, 27 Oct 2017 20:10:22 -0400 Received: by mail-pf0-f195.google.com with SMTP id b6so6009922pfh.7 for ; Fri, 27 Oct 2017 17:10:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZmOW2Y2jK+xxsUBqAZbGHqwyqBypvBw6lWA5nDsXKrM=; b=0Nm1mHHp5BVdgJ6q4dfGWKAzXyfMVGyAn0sjK4Hsz24WNJlPC11PfJYIoqXX9B4P2p EVoSx1MWOdtgBuQ1560Ah4Uji8QiuwPzfgV8b+pvK5sP2bdr1AnNkcBZRe7LPGdbf6dx Dufy/wMYllwRSLSLq+q1LzU5XhYdcK2CaPSw19hb4GHOm/yYNzsP6P99/qAgK7OqIbPv 8Ay54H55bvjRBu/qGeC1tPIJIbwFw8jLRbnJZIw6PHnKk09NWzmPAQv0rgFRqoLtRDt5 u9WwoNElICHObkOia0gGoXqOZtbbZoruFDT2kisiuMUQ5pD93HxDdY9yQg7g6ZIPkpeV ZunA== 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:in-reply-to :references; bh=ZmOW2Y2jK+xxsUBqAZbGHqwyqBypvBw6lWA5nDsXKrM=; b=pJyTX2nVNCZBbeJk3sDfPjlqV1rzCFA+/9/cSFckt6XaTUfQSQWSl+d+H/Lxe5XZED nu/ZonDowWHAj0bhBebBzsx+MnbMT4U/AiNdkYRHitrMOp5VRGcQoT2JOGXolPfP0TbQ 0RSnPsxEkQR9NEN9UXJnJeBaerFhcMgbcGdK1p4wCCjHiKdRcuCB2XExDTjkrFPgkVMa 8tHyoc6jK2XZUVK60NnISVHOEW7n+p3k2rlOvzeYckAjTknbwUYJmrDeogFUTcECPUFq MgtCJ0Iu5L49xLltZtk6seq7YzO/u7lTQcsuyMaC0XcMcz20HpE5f0abR4zQPGT/07cy BJqQ== X-Gm-Message-State: AMCzsaVk2YBiGGqE77nf0ojHW4GkzufGHz7RFepxozV7Njy6AKnDWoK+ xqLqgs5I9s+zLLgp15H3JnRdYryc X-Google-Smtp-Source: ABhQp+QDWNg/o9Feo8Vkbmrd+sixDYD/mpq+sCe07LDHCozCoIsHWr5uEO0D8MwL377w6EJBdFABLw== X-Received: by 10.101.78.5 with SMTP id r5mr1615210pgt.94.1509149422115; Fri, 27 Oct 2017 17:10:22 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:21 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 09/13] gtp: Call function to update path mtu Date: Fri, 27 Oct 2017 17:09:33 -0700 Message-Id: <20171028000937.2631-10-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Replace mtu handling with call to __iptunnel_update_pmtu. Signed-off-by: Tom Herbert --- drivers/net/gtp.c | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 8b7014aa45c2..7b9a482b3d22 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -53,6 +53,7 @@ struct pdp_ctx { } v1; } u; u8 gtp_version; + u8 hlen; u16 af; struct in_addr ms_addr_ip4; @@ -474,8 +475,6 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, struct iphdr *iph; struct sock *sk; __be32 saddr; - __be16 df; - int mtu; /* Read the IP destination address and resolve the PDP context. * Prepend PDP header with TEI/TID from PDP ctx. @@ -521,37 +520,12 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, skb_dst_drop(skb); - /* This is similar to tnl_update_pmtu(). */ - df = iph->frag_off; - if (df) { - mtu = dst_mtu(&rt->dst) - dev->hard_header_len - - sizeof(struct iphdr) - sizeof(struct udphdr); - switch (pctx->gtp_version) { - case GTP_V0: - mtu -= sizeof(struct gtp0_header); - break; - case GTP_V1: - mtu -= sizeof(struct gtp1_header); - break; - } - } else { - mtu = dst_mtu(&rt->dst); - } - - rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu); - - if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) && - mtu < ntohs(iph->tot_len)) { - netdev_dbg(dev, "packet too big, fragmentation needed\n"); - memset(IPCB(skb), 0, sizeof(*IPCB(skb))); - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); - goto err_rt; - } - gtp_set_pktinfo_ipv4(pktinfo, sk, iph, pctx, rt, &fl4, dev); gtp_push_header(skb, pktinfo); + __iptunnel_update_pmtu(dev, skb, &rt->dst, !!iph->frag_off, iph, + pctx->hlen, pctx->peer_addr_ip4.s_addr); + return 0; err_rt: ip_rt_put(rt); @@ -922,10 +896,12 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) */ pctx->u.v0.tid = nla_get_u64(info->attrs[GTPA_TID]); pctx->u.v0.flow = nla_get_u16(info->attrs[GTPA_FLOW]); + pctx->hlen = sizeof(struct udphdr) + sizeof(struct gtp0_header); break; case GTP_V1: pctx->u.v1.i_tei = nla_get_u32(info->attrs[GTPA_I_TEI]); pctx->u.v1.o_tei = nla_get_u32(info->attrs[GTPA_O_TEI]); + pctx->hlen = sizeof(struct udphdr) + sizeof(struct gtp1_header); break; default: break; From patchwork Sat Oct 28 00:09:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831556 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="ZPZG20sc"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1NR4bw4z9t4X for ; Sat, 28 Oct 2017 11:10:31 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751802AbdJ1AK3 (ORCPT ); Fri, 27 Oct 2017 20:10:29 -0400 Received: from mail-pf0-f196.google.com ([209.85.192.196]:51665 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751686AbdJ1AKZ (ORCPT ); Fri, 27 Oct 2017 20:10:25 -0400 Received: by mail-pf0-f196.google.com with SMTP id n14so6000828pfh.8 for ; Fri, 27 Oct 2017 17:10:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wiZvZ3f7IF+dSxdPEtXQJ29TyBuKX5rBk43+3Ck/3wQ=; b=ZPZG20sc8CqTm8jWJmZCriNXEDb6/lTm51JvrDo4Yt57fGZlkvMnhq4yXNN64o7Vp2 QPwlDEixF6ZCZzTgW1D9rjjaSZbAZ9waViNMYtQOonJWONJOa/pMeBfI5fyuM4sp3PKj q1HMHVeqB9oPqk+xItE3WuNZaUHtomPCtOOelmEtixPixL/YiEUSMBtxxGYlSc/vkVvM 8IzCfbT1Pgr2S3cf7yDgytCSSZJQaTyqTfTBvdLGJNi9wmFnNCJDfwK6t4084hIac6KU edsul1pscZqg+CumL1rv15a/EvlkzJWH3ljeYW3Rw+SIsDWw3esAvwrIdUzTLcDf7lva ntsw== 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:in-reply-to :references; bh=wiZvZ3f7IF+dSxdPEtXQJ29TyBuKX5rBk43+3Ck/3wQ=; b=MN2hYMuRkiOrRAi8u/VswvsNiX8JTRZUuiOKiH6PX1+oUiMpI0hJn3NwGcn1V2qa5m tfyOJLHLcqSGr7JMkudgAKZxZ0FHZlz3SfPzmC8EWsg5Ug848lqvbWMi4mlZOk5iKM1p 8pbmdwOpP1R/fewl14F80H094AByJzJQ5FUEBx6f67m3HxQou2WvTq050gOhLDAvvz5C YM4fCYAGd3nXYPfMf1eVYFeeZjNcc0Ixnv/gJebzxNaxsa7urwqm4hDZ26v9rWim09+k fpwEpxPIURGIn0ll95tn39kRtZn77gD8PUtzoMEDwVtsaLS+7wrNPaDMeZaHo786XFLZ veXw== X-Gm-Message-State: AMCzsaXHA2Upfim/bNLogRkU8N62kxHtrWCtXVZtkeitrlk/8UXnksdH 5m4Q/8pTc0hgIHe2A1jWA3+Odg== X-Google-Smtp-Source: ABhQp+S3QkHB5j3S0az57a9cyNtXv+OqdQCoKc4332jt7WjpzOUDojdeKTc/ogAaZg8aKgITXn2PPw== X-Received: by 10.101.81.135 with SMTP id h7mr1684682pgq.320.1509149424493; Fri, 27 Oct 2017 17:10:24 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:23 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 10/13] gtp: Eliminate pktinfo and add port configuration Date: Fri, 27 Oct 2017 17:09:34 -0700 Message-Id: <20171028000937.2631-11-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The gtp pktinfo structure is unnecessary and needs a lot of code to manage it. Remove it. Also, add per pdp port configuration for transmit. Signed-off-by: Tom Herbert --- drivers/net/gtp.c | 177 +++++++++++++++++++++-------------------------- include/uapi/linux/gtp.h | 1 + 2 files changed, 80 insertions(+), 98 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 7b9a482b3d22..0b4a6e4f70a5 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -54,6 +54,7 @@ struct pdp_ctx { } u; u8 gtp_version; u8 hlen; + __be16 gtp_port; u16 af; struct in_addr ms_addr_ip4; @@ -427,73 +428,36 @@ static inline void gtp1_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) */ } -struct gtp_pktinfo { - struct sock *sk; - struct iphdr *iph; - struct flowi4 fl4; - struct rtable *rt; - struct pdp_ctx *pctx; - struct net_device *dev; - __be16 gtph_port; -}; - -static void gtp_push_header(struct sk_buff *skb, struct gtp_pktinfo *pktinfo) +static void gtp_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) { - switch (pktinfo->pctx->gtp_version) { + switch (pctx->gtp_version) { case GTP_V0: - pktinfo->gtph_port = htons(GTP0_PORT); - gtp0_push_header(skb, pktinfo->pctx); + gtp0_push_header(skb, pctx); break; case GTP_V1: - pktinfo->gtph_port = htons(GTP1U_PORT); - gtp1_push_header(skb, pktinfo->pctx); + gtp1_push_header(skb, pctx); break; } } -static inline void gtp_set_pktinfo_ipv4(struct gtp_pktinfo *pktinfo, - struct sock *sk, struct iphdr *iph, - struct pdp_ctx *pctx, struct rtable *rt, - struct flowi4 *fl4, - struct net_device *dev) -{ - pktinfo->sk = sk; - pktinfo->iph = iph; - pktinfo->pctx = pctx; - pktinfo->rt = rt; - pktinfo->fl4 = *fl4; - pktinfo->dev = dev; -} - -static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, - struct gtp_pktinfo *pktinfo) +static int gtp_xmit(struct sk_buff *skb, struct net_device *dev, + struct pdp_ctx *pctx) { - struct gtp_dev *gtp = netdev_priv(dev); - struct pdp_ctx *pctx; + struct iphdr *inner_iph = NULL; + struct sock *sk = pctx->sk; + __be32 saddr = inet_sk(sk)->inet_saddr; struct rtable *rt; - struct flowi4 fl4; - struct iphdr *iph; - struct sock *sk; - __be32 saddr; + int err = 0; - /* Read the IP destination address and resolve the PDP context. - * Prepend PDP header with TEI/TID from PDP ctx. - */ - iph = ip_hdr(skb); - if (gtp->role == GTP_ROLE_SGSN) - pctx = ipv4_pdp_find(gtp, iph->saddr); - else - pctx = ipv4_pdp_find(gtp, iph->daddr); + if (skb->protocol == ETH_P_IP) + inner_iph = ip_hdr(skb); - if (!pctx) { - netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n", - &iph->daddr); - return -ENOENT; - } - netdev_dbg(dev, "found PDP context %p\n", pctx); + /* Ensure there is sufficient headroom. */ + err = skb_cow_head(skb, dev->needed_headroom); + if (unlikely(err)) + goto out_err; - sk = pctx->sk; - saddr = inet_sk(sk)->inet_saddr; + skb_reset_inner_headers(skb); /* Source address returned by route lookup is ignored since * we get the address from a socket. @@ -501,81 +465,89 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, rt = ip_tunnel_get_route(dev, skb, sk->sk_protocol, sk->sk_bound_dev_if, RT_CONN_FLAGS(sk), pctx->peer_addr_ip4.s_addr, &saddr, - pktinfo->gtph_port, pktinfo->gtph_port, + pctx->gtp_port, pctx->gtp_port, &pctx->dst_cache, NULL); if (IS_ERR(rt)) { - if (rt == ERR_PTR(-ELOOP)) { - netdev_dbg(dev, "circular route to SSGN %pI4\n", - &pctx->peer_addr_ip4.s_addr); - dev->stats.collisions++; - goto err_rt; - } else { - netdev_dbg(dev, "no route to SSGN %pI4\n", - &pctx->peer_addr_ip4.s_addr); - dev->stats.tx_carrier_errors++; - goto err; - } + err = PTR_ERR(rt); + goto out_err; } skb_dst_drop(skb); - gtp_set_pktinfo_ipv4(pktinfo, sk, iph, pctx, rt, &fl4, dev); - gtp_push_header(skb, pktinfo); + gtp_push_header(skb, pctx); + + if (inner_iph) + __iptunnel_update_pmtu(dev, skb, &rt->dst, + !!inner_iph->frag_off, + inner_iph, pctx->hlen, + pctx->peer_addr_ip4.s_addr); - __iptunnel_update_pmtu(dev, skb, &rt->dst, !!iph->frag_off, iph, - pctx->hlen, pctx->peer_addr_ip4.s_addr); + udp_tunnel_xmit_skb(rt, sk, skb, saddr, + pctx->peer_addr_ip4.s_addr, + 0, ip4_dst_hoplimit(&rt->dst), 0, + pctx->gtp_port, pctx->gtp_port, + false, false); + + netdev_dbg(dev, "gtp -> IP src: %pI4 dst: %pI4\n", + &saddr, &pctx->peer_addr_ip4.s_addr); return 0; -err_rt: - ip_rt_put(rt); -err: - return -EBADMSG; + +out_err: + if (err == -ELOOP) + dev->stats.collisions++; + else + dev->stats.tx_carrier_errors++; + + return err; } static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned int proto = ntohs(skb->protocol); - struct gtp_pktinfo pktinfo; + struct gtp_dev *gtp = netdev_priv(dev); + struct pdp_ctx *pctx; int err; - /* Ensure there is sufficient headroom. */ - if (skb_cow_head(skb, dev->needed_headroom)) - goto tx_err; - - skb_reset_inner_headers(skb); - /* PDP context lookups in gtp_build_skb_*() need rcu read-side lock. */ rcu_read_lock(); switch (proto) { - case ETH_P_IP: - err = gtp_build_skb_ip4(skb, dev, &pktinfo); + case ETH_P_IP: { + struct iphdr *iph = ip_hdr(skb); + + if (gtp->role == GTP_ROLE_SGSN) + pctx = ipv4_pdp_find(gtp, iph->saddr); + else + pctx = ipv4_pdp_find(gtp, iph->daddr); + + if (!pctx) { + netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n", + &iph->daddr); + err = -ENOENT; + goto tx_err; + } + break; + } default: err = -EOPNOTSUPP; - break; + goto tx_err; } - rcu_read_unlock(); + + netdev_dbg(dev, "found PDP context %p\n", pctx); + + err = gtp_xmit(skb, dev, pctx); if (err < 0) goto tx_err; - switch (proto) { - case ETH_P_IP: - netdev_dbg(pktinfo.dev, "gtp -> IP src: %pI4 dst: %pI4\n", - &pktinfo.iph->saddr, &pktinfo.iph->daddr); - udp_tunnel_xmit_skb(pktinfo.rt, pktinfo.sk, skb, - pktinfo.fl4.saddr, pktinfo.fl4.daddr, - pktinfo.iph->tos, - ip4_dst_hoplimit(&pktinfo.rt->dst), - 0, - pktinfo.gtph_port, pktinfo.gtph_port, - true, false); - break; - } + rcu_read_unlock(); return NETDEV_TX_OK; + tx_err: + rcu_read_unlock(); dev->stats.tx_errors++; dev_kfree_skb(skb); return NETDEV_TX_OK; @@ -881,6 +853,8 @@ static struct gtp_dev *gtp_find_dev(struct net *src_net, struct nlattr *nla[]) static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) { + __be16 default_port = 0; + pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); pctx->af = AF_INET; pctx->peer_addr_ip4.s_addr = @@ -897,15 +871,22 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) pctx->u.v0.tid = nla_get_u64(info->attrs[GTPA_TID]); pctx->u.v0.flow = nla_get_u16(info->attrs[GTPA_FLOW]); pctx->hlen = sizeof(struct udphdr) + sizeof(struct gtp0_header); + default_port = htons(GTP0_PORT); break; case GTP_V1: pctx->u.v1.i_tei = nla_get_u32(info->attrs[GTPA_I_TEI]); pctx->u.v1.o_tei = nla_get_u32(info->attrs[GTPA_O_TEI]); pctx->hlen = sizeof(struct udphdr) + sizeof(struct gtp1_header); + default_port = htons(GTP1U_PORT); break; default: break; } + + if (info->attrs[GTPA_PORT]) + pctx->gtp_port = nla_get_u16(info->attrs[GTPA_PORT]); + else + pctx->gtp_port = default_port; } static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk, diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index 57d1edb8efd9..b2283a5c6d7f 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -27,6 +27,7 @@ enum gtp_attrs { GTPA_I_TEI, /* for GTPv1 only */ GTPA_O_TEI, /* for GTPv1 only */ GTPA_PAD, + GTPA_PORT, __GTPA_MAX, }; #define GTPA_MAX (__GTPA_MAX + 1) From patchwork Sat Oct 28 00:09:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831557 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="nu1n/zqI"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1NT6BCDz9t4X for ; Sat, 28 Oct 2017 11:10:33 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751830AbdJ1AKb (ORCPT ); Fri, 27 Oct 2017 20:10:31 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:48328 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751745AbdJ1AK1 (ORCPT ); Fri, 27 Oct 2017 20:10:27 -0400 Received: by mail-pg0-f67.google.com with SMTP id v78so6413250pgb.5 for ; Fri, 27 Oct 2017 17:10:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bZAUS8VfgqM8mtq6zdjmd6USe4KunWLghSW73cj47Ps=; b=nu1n/zqIcRPMC2AsKP+AXREAjnHJ24zprl65JyLPRBo6dBvMKJhXnkE3aBIRABOMnh Pi6wLH32gPry8sg8ELEomZ39vznJJ2F7J/oQHdQafay8SKIEIQ5q5xZliETYAPJ7joE1 q/7n5vpAX1N4+XmRDz6MqtT3YWuphSioFee4znAko4vctkoWvxSUNW4BWR9Mn4nbZnC/ pUsTmlxe+d9x24qC4JiCxUCa9PMDrhtKx1mVQDcvw/scwkXWGA5t3spVHlXFP2/AF3/Y RbRUVqRREgOLcMO7X2AILJYRqVoRSM56oX8DVIhsLqD92WG2wGLuY7ZsQIu1hNjGfM5D tlBA== 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:in-reply-to :references; bh=bZAUS8VfgqM8mtq6zdjmd6USe4KunWLghSW73cj47Ps=; b=ce7STh+1586RwCXqOToKC5LYyWni9NPBTUcP9z9iiFy42QyZBKNsZLFxQxgZ+ogl3N 6WiJKtElQtEk6kC6kjM4DHN6PfpGsCs6Rdco69Ls7dDjC/UJ6Dpoes906g6qPg4FiKlH t63ic/wxBcj2iTY+h72fODdJsYFk75IGQjauShdoXV+2AVvKJ9ygQdsjkz8/Y2P8SDzy Jj3oL7MPHDjStBUOIB80Xv3Bn7ILvOz+MeWPq/7wo/43K3q9zw77jjPuq1LjR+bwAiF8 fTYrciKXtmYe7P5qv2MkelSj1pmZjEA7K6x5XmZUBTdZfo/BjWe6OjBymWUQYQIBMfpc qlHA== X-Gm-Message-State: AMCzsaVImz3lw1yFAr3QD76wg/zKaMFyTMojh0srzJyaRimAJarv2hpG PKG+XK6Q5QgGAyZyxvACg8AFPQ== X-Google-Smtp-Source: ABhQp+S0fxEavNd8G3NqAfiKCRSWNkmyKdQHYDsVr7RgEoaIF+9A9swuPV0cRlmovjHgs5pyVrAEyA== X-Received: by 10.99.3.84 with SMTP id 81mr1557904pgd.451.1509149426734; Fri, 27 Oct 2017 17:10:26 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:25 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 11/13] gtp: Experimental encapsulation of IPv6 packets Date: Fri, 27 Oct 2017 17:09:35 -0700 Message-Id: <20171028000937.2631-12-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Allow IPv6 mobile subscriber packets. This entails adding an IPv6 mobile subscriber address to pdp context and IPv6 specific variants to find pdp contexts by address. Note that this is experimental support of IPv6, more work is necessary to make this compliant with 3GPP standard. Signed-off-by: Tom Herbert --- drivers/net/Kconfig | 12 +- drivers/net/gtp.c | 324 +++++++++++++++++++++++++++++++++++++++-------- include/uapi/linux/gtp.h | 1 + 3 files changed, 280 insertions(+), 57 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 720c2af0bb88..1af34cc4cd7e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -226,7 +226,17 @@ config GTP 3GPP TS 29.060 standards. To compile this drivers as a module, choose M here: the module - wil be called gtp. + will be called gtp. + +config GTP_IPV6_EXPERIMENTAL + bool "GTP IPv6 datapath (EXPERIMENTAL)" + default n + depends on GTP + ---help--- + This is an experimental implementation that allows encapsulating + IPv6 over GTP and using GTP over IPv6 for testing and development + purpose. This is not a standards conformant implementation for + IPv6 and GTP. More work is needed reach that level. config MACSEC tristate "IEEE 802.1AE MAC-level encryption (MACsec)" diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 0b4a6e4f70a5..6190631574dc 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -36,6 +36,8 @@ #include #include +#define GTP_IPV6 IS_ENABLED(CONFIG_GTP_IPV6_EXPERIMENTAL) + /* An active session for the subscriber. */ struct pdp_ctx { struct hlist_node hlist_tid; @@ -55,9 +57,17 @@ struct pdp_ctx { u8 gtp_version; u8 hlen; __be16 gtp_port; - u16 af; - struct in_addr ms_addr_ip4; + u16 ms_af; +#if GTP_IPV6 + union { + struct in_addr ms_addr_ip4; + struct in6_addr ms_addr_ip6; + }; +#else + struct in_addr ms_addr_ip4; +#endif + struct in_addr peer_addr_ip4; struct sock *sk; @@ -81,7 +91,11 @@ struct gtp_dev { unsigned int role; unsigned int hash_size; struct hlist_head *tid_hash; - struct hlist_head *addr_hash; + + struct hlist_head *addr4_hash; +#if GTP_IPV6 + struct hlist_head *addr6_hash; +#endif struct gro_cells gro_cells; }; @@ -99,6 +113,7 @@ static void pdp_context_delete(struct pdp_ctx *pctx); static inline u32 gtp0_hashfn(u64 tid) { u32 *tid32 = (u32 *) &tid; + return jhash_2words(tid32[0], tid32[1], gtp_h_initval); } @@ -107,11 +122,6 @@ static inline u32 gtp1u_hashfn(u32 tid) return jhash_1word(tid, gtp_h_initval); } -static inline u32 ipv4_hashfn(__be32 ip) -{ - return jhash_1word((__force u32)ip, gtp_h_initval); -} - /* Resolve a PDP context structure based on the 64bit TID. */ static struct pdp_ctx *gtp0_pdp_find(struct gtp_dev *gtp, u64 tid) { @@ -144,16 +154,21 @@ static struct pdp_ctx *gtp1_pdp_find(struct gtp_dev *gtp, u32 tid) return NULL; } +static inline u32 gtp_ipv4_hashfn(__be32 ip) +{ + return jhash_1word((__force u32)ip, gtp_h_initval); +} + /* Resolve a PDP context based on IPv4 address of MS. */ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr) { struct hlist_head *head; struct pdp_ctx *pdp; - head = >p->addr_hash[ipv4_hashfn(ms_addr) % gtp->hash_size]; + head = >p->addr4_hash[gtp_ipv4_hashfn(ms_addr) % gtp->hash_size]; hlist_for_each_entry_rcu(pdp, head, hlist_addr) { - if (pdp->af == AF_INET && + if (pdp->ms_af == AF_INET && pdp->ms_addr_ip4.s_addr == ms_addr) return pdp; } @@ -177,33 +192,109 @@ static bool gtp_check_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, return iph->saddr == pctx->ms_addr_ip4.s_addr; } +#if GTP_IPV6 + +static inline u32 gtp_ipv6_hashfn(const struct in6_addr *a) +{ + return __ipv6_addr_jhash(a, gtp_h_initval); +} + +/* Resolve a PDP context based on IPv6 address of MS. */ +static struct pdp_ctx *ipv6_pdp_find(struct gtp_dev *gtp, + const struct in6_addr *ms_addr) +{ + struct hlist_head *head; + struct pdp_ctx *pdp; + + head = >p->addr6_hash[gtp_ipv6_hashfn(ms_addr) % gtp->hash_size]; + + hlist_for_each_entry_rcu(pdp, head, hlist_addr) { + if (pdp->ms_af == AF_INET6 && + ipv6_addr_equal(&pdp->ms_addr_ip6, ms_addr)) + return pdp; + } + + return NULL; +} + +static bool gtp_check_ms_ipv6(struct sk_buff *skb, struct pdp_ctx *pctx, + unsigned int hdrlen, unsigned int role) +{ + struct ipv6hdr *ipv6h; + + if (!pskb_may_pull(skb, hdrlen + sizeof(struct ipv6hdr))) + return false; + + ipv6h = (struct ipv6hdr *)(skb->data + hdrlen); + + if (role == GTP_ROLE_SGSN) + return ipv6_addr_equal(&ipv6h->daddr, &pctx->ms_addr_ip6); + else + return ipv6_addr_equal(&ipv6h->saddr, &pctx->ms_addr_ip6); +} + +#endif + /* Check if the inner IP address in this packet is assigned to any * existing mobile subscriber. */ static bool gtp_check_ms(struct sk_buff *skb, struct pdp_ctx *pctx, unsigned int hdrlen, unsigned int role) { - switch (ntohs(skb->protocol)) { - case ETH_P_IP: + struct iphdr *iph; + + /* Minimally there needs to be an IPv4 header */ + if (!pskb_may_pull(skb, hdrlen + sizeof(struct iphdr))) + return false; + + iph = (struct iphdr *)(skb->data + hdrlen); + + switch (iph->version) { + case 4: return gtp_check_ms_ipv4(skb, pctx, hdrlen, role); +#if GTP_IPV6 + case 6: + return gtp_check_ms_ipv6(skb, pctx, hdrlen, role); +#endif } + return false; } +static u16 ipver_to_eth(struct iphdr *iph) +{ + switch (iph->version) { + case 4: + return htons(ETH_P_IP); +#if GTP_IPV6 + case 6: + return htons(ETH_P_IPV6); +#endif + default: + return 0; + } +} + static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, - unsigned int hdrlen, unsigned int role) + unsigned int hdrlen, unsigned int role) { struct gtp_dev *gtp = netdev_priv(pctx->dev); struct pcpu_sw_netstats *stats; + u16 inner_protocol; if (!gtp_check_ms(skb, pctx, hdrlen, role)) { netdev_dbg(pctx->dev, "No PDP ctx for this MS\n"); return 1; } + inner_protocol = ipver_to_eth((struct iphdr *)(skb->data + hdrlen)); + if (!inner_protocol) + return -1; + /* Get rid of the GTP + UDP headers. */ - if (iptunnel_pull_header(skb, hdrlen, skb->protocol, - !net_eq(sock_net(pctx->sk), dev_net(pctx->dev)))) + if (iptunnel_pull_header(skb, hdrlen, inner_protocol, + !net_eq(sock_net(pctx->sk), + dev_net(pctx->dev)))) return -1; netdev_dbg(pctx->dev, "forwarding packet from GGSN to uplink\n"); @@ -241,7 +332,8 @@ static int gtp0_udp_encap_recv(struct sock *sk, struct sk_buff *skb) if (!gtp) goto pass; - if (!pskb_may_pull(skb, hdrlen)) + /* Pull through IP header since gtp_rx looks at IP version */ + if (!pskb_may_pull(skb, hdrlen + sizeof(struct iphdr))) goto drop; gtp0 = (struct gtp0_header *)(skb->data + sizeof(struct udphdr)); @@ -287,7 +379,8 @@ static int gtp1u_udp_encap_recv(struct sock *sk, struct sk_buff *skb) if (!gtp) goto pass; - if (!pskb_may_pull(skb, hdrlen)) + /* Pull through IP header since gtp_rx looks at IP version */ + if (!pskb_may_pull(skb, hdrlen + sizeof(struct iphdr))) goto drop; gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); @@ -309,8 +402,10 @@ static int gtp1u_udp_encap_recv(struct sock *sk, struct sk_buff *skb) if (gtp1->flags & GTP1_F_MASK) hdrlen += 4; - /* Make sure the header is larger enough, including extensions. */ - if (!pskb_may_pull(skb, hdrlen)) + /* Make sure the header is larger enough, including extensions and + * also an IP header since gtp_rx looks at IP version + */ + if (!pskb_may_pull(skb, hdrlen + sizeof(struct iphdr))) goto drop; gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); @@ -398,7 +493,8 @@ static inline void gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) gtp0->flags = 0x1e; /* v0, GTP-non-prime. */ gtp0->type = GTP_TPDU; gtp0->length = htons(payload_len); - gtp0->seq = htons((atomic_inc_return(&pctx->tx_seq) - 1) % 0xffff); + gtp0->seq = htons((atomic_inc_return(&pctx->tx_seq) - 1) % + 0xffff); gtp0->flow = htons(pctx->u.v0.flow); gtp0->number = 0xff; gtp0->spare[0] = gtp0->spare[1] = gtp0->spare[2] = 0xff; @@ -530,6 +626,25 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) break; } +#if GTP_IPV6 + case ETH_P_IPV6: { + struct ipv6hdr *ipv6h = ipv6_hdr(skb); + + if (gtp->role == GTP_ROLE_SGSN) + pctx = ipv6_pdp_find(gtp, &ipv6h->saddr); + else + pctx = ipv6_pdp_find(gtp, &ipv6h->daddr); + + if (!pctx) { + netdev_dbg(dev, "no PDP ctx found for %pI6, skip\n", + &ipv6h->daddr); + err = -ENOENT; + goto tx_err; + } + + break; + } +#endif default: err = -EOPNOTSUPP; goto tx_err; @@ -699,23 +814,38 @@ static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize) { int i; - gtp->addr_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL); - if (gtp->addr_hash == NULL) - return -ENOMEM; + gtp->addr4_hash = kmalloc_array(hsize, sizeof(*gtp->addr4_hash), + GFP_KERNEL); + if (!gtp->addr4_hash) + goto err; + +#if GTP_IPV6 + gtp->addr6_hash = kmalloc_array(hsize, sizeof(*gtp->addr6_hash), + GFP_KERNEL); + if (!gtp->addr6_hash) + goto err; +#endif - gtp->tid_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL); - if (gtp->tid_hash == NULL) - goto err1; + gtp->tid_hash = kmalloc_array(hsize, sizeof(struct hlist_head), + GFP_KERNEL); + if (!gtp->tid_hash) + goto err; gtp->hash_size = hsize; for (i = 0; i < hsize; i++) { - INIT_HLIST_HEAD(>p->addr_hash[i]); + INIT_HLIST_HEAD(>p->addr4_hash[i]); +#if GTP_IPV6 + INIT_HLIST_HEAD(>p->addr6_hash[i]); +#endif INIT_HLIST_HEAD(>p->tid_hash[i]); } return 0; -err1: - kfree(gtp->addr_hash); +err: + kfree(gtp->addr4_hash); +#if GTP_IPV6 + kfree(gtp->addr6_hash); +#endif return -ENOMEM; } @@ -729,7 +859,10 @@ static void gtp_hashtable_free(struct gtp_dev *gtp) pdp_context_delete(pctx); synchronize_rcu(); - kfree(gtp->addr_hash); + kfree(gtp->addr4_hash); +#if GTP_IPV6 + kfree(gtp->addr6_hash); +#endif kfree(gtp->tid_hash); } @@ -851,16 +984,13 @@ static struct gtp_dev *gtp_find_dev(struct net *src_net, struct nlattr *nla[]) return gtp; } -static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) +static void pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) { __be16 default_port = 0; pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); - pctx->af = AF_INET; pctx->peer_addr_ip4.s_addr = nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); - pctx->ms_addr_ip4.s_addr = - nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); switch (pctx->gtp_version) { case GTP_V0: @@ -889,33 +1019,59 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) pctx->gtp_port = default_port; } -static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk, - struct genl_info *info) +static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, + struct genl_info *info) { struct net_device *dev = gtp->dev; + struct hlist_head *addr_list; + struct pdp_ctx *pctx = NULL; u32 hash_ms, hash_tid = 0; - struct pdp_ctx *pctx; - bool found = false; - __be32 ms_addr; +#if GTP_IPV6 + struct in6_addr ms6_addr; +#endif + __be32 ms_addr = 0; + int ms_af; int err; - ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); - hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size; +#if GTP_IPV6 + /* Caller ensures we have either v4 or v6 mobile subscriber address */ + if (info->attrs[GTPA_MS_ADDRESS]) { + /* IPv4 mobile subscriber */ - hlist_for_each_entry_rcu(pctx, >p->addr_hash[hash_ms], hlist_addr) { - if (pctx->ms_addr_ip4.s_addr == ms_addr) { - found = true; - break; - } + ms_addr = nla_get_in_addr(info->attrs[GTPA_MS_ADDRESS]); + hash_ms = gtp_ipv4_hashfn(ms_addr) % gtp->hash_size; + addr_list = >p->addr4_hash[hash_ms]; + ms_af = AF_INET; + + pctx = ipv4_pdp_find(gtp, ms_addr); + } else { + /* IPv6 mobile subscriber */ + + ms6_addr = nla_get_in6_addr(info->attrs[GTPA_MS6_ADDRESS]); + hash_ms = gtp_ipv6_hashfn(&ms6_addr) % gtp->hash_size; + addr_list = >p->addr6_hash[hash_ms]; + ms_af = AF_INET6; + + pctx = ipv6_pdp_find(gtp, &ms6_addr); } +#else + /* IPv4 mobile subscriber */ - if (found) { + ms_addr = nla_get_in_addr(info->attrs[GTPA_MS_ADDRESS]); + hash_ms = gtp_ipv4_hashfn(ms_addr) % gtp->hash_size; + addr_list = >p->addr4_hash[hash_ms]; + ms_af = AF_INET; + + pctx = ipv4_pdp_find(gtp, ms_addr); +#endif + + if (pctx) { if (info->nlhdr->nlmsg_flags & NLM_F_EXCL) return -EEXIST; if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE) return -EOPNOTSUPP; - ipv4_pdp_fill(pctx, info); + pdp_fill(pctx, info); if (pctx->gtp_version == GTP_V0) netdev_dbg(dev, "GTPv0-U: update tunnel id = %llx (pdp %p)\n", @@ -941,7 +1097,20 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk, sock_hold(sk); pctx->sk = sk; pctx->dev = gtp->dev; - ipv4_pdp_fill(pctx, info); + pctx->ms_af = ms_af; + + switch (ms_af) { + case AF_INET: + pctx->ms_addr_ip4.s_addr = ms_addr; + break; +#if GTP_IPV6 + case AF_INET6: + pctx->ms_addr_ip6 = ms6_addr; + break; +#endif + } + + pdp_fill(pctx, info); atomic_set(&pctx->tx_seq, 0); switch (pctx->gtp_version) { @@ -958,7 +1127,7 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk, break; } - hlist_add_head_rcu(&pctx->hlist_addr, >p->addr_hash[hash_ms]); + hlist_add_head_rcu(&pctx->hlist_addr, addr_list); hlist_add_head_rcu(&pctx->hlist_tid, >p->tid_hash[hash_tid]); switch (pctx->gtp_version) { @@ -1000,11 +1169,25 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) int err; if (!info->attrs[GTPA_VERSION] || - !info->attrs[GTPA_LINK] || - !info->attrs[GTPA_PEER_ADDRESS] || - !info->attrs[GTPA_MS_ADDRESS]) + !info->attrs[GTPA_LINK] || + !info->attrs[GTPA_PEER_ADDRESS]) return -EINVAL; +#if GTP_IPV6 + if (!(!!info->attrs[GTPA_MS_ADDRESS] ^ + !!info->attrs[GTPA_MS6_ADDRESS])) { + /* Either v4 or v6 mobile subscriber address must be set */ + + return -EINVAL; + } +#else + if (!info->attrs[GTPA_MS_ADDRESS]) { + /* v4 mobile subscriber address must be set */ + + return -EINVAL; + } +#endif + version = nla_get_u32(info->attrs[GTPA_VERSION]); switch (version) { @@ -1043,7 +1226,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) goto out_unlock; } - err = ipv4_pdp_add(gtp, sk, info); + err = gtp_pdp_add(gtp, sk, info); out_unlock: rcu_read_unlock(); @@ -1063,6 +1246,13 @@ static struct pdp_ctx *gtp_find_pdp_by_link(struct net *net, __be32 ip = nla_get_be32(nla[GTPA_MS_ADDRESS]); return ipv4_pdp_find(gtp, ip); +#if GTP_IPV6 + } else if (nla[GTPA_MS6_ADDRESS]) { + struct in6_addr ip6 = + nla_get_in6_addr(nla[GTPA_MS6_ADDRESS]); + + return ipv6_pdp_find(gtp, &ip6); +#endif } else if (nla[GTPA_VERSION]) { u32 gtp_version = nla_get_u32(nla[GTPA_VERSION]); @@ -1133,9 +1323,27 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, goto nlmsg_failure; if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) || - nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr) || - nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr)) + nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr)) + goto nla_put_failure; + + switch (pctx->ms_af) { + case AF_INET: + if (nla_put_be32(skb, GTPA_MS_ADDRESS, + pctx->ms_addr_ip4.s_addr)) + goto nla_put_failure; + + break; +#if GTP_IPV6 + case AF_INET6: + if (nla_put_in6_addr(skb, GTPA_MS6_ADDRESS, + &pctx->ms_addr_ip6)) + goto nla_put_failure; + + break; +#endif + default: goto nla_put_failure; + } switch (pctx->gtp_version) { case GTP_V0: @@ -1246,6 +1454,10 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { [GTPA_TID] = { .type = NLA_U64, }, [GTPA_PEER_ADDRESS] = { .type = NLA_U32, }, [GTPA_MS_ADDRESS] = { .type = NLA_U32, }, +#if GTP_IPV6 + [GTPA_MS6_ADDRESS] = { .len = FIELD_SIZEOF(struct ipv6hdr, + daddr) }, +#endif [GTPA_FLOW] = { .type = NLA_U16, }, [GTPA_NET_NS_FD] = { .type = NLA_U32, }, [GTPA_I_TEI] = { .type = NLA_U32, }, diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index b2283a5c6d7f..ae4e632c0360 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -28,6 +28,7 @@ enum gtp_attrs { GTPA_O_TEI, /* for GTPv1 only */ GTPA_PAD, GTPA_PORT, + GTPA_MS6_ADDRESS, __GTPA_MAX, }; #define GTPA_MAX (__GTPA_MAX + 1) From patchwork Sat Oct 28 00:09:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831558 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="oz5/e2DH"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1NX268Yz9t4X for ; Sat, 28 Oct 2017 11:10:36 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751854AbdJ1AKe (ORCPT ); Fri, 27 Oct 2017 20:10:34 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:46437 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751686AbdJ1AK3 (ORCPT ); Fri, 27 Oct 2017 20:10:29 -0400 Received: by mail-pg0-f65.google.com with SMTP id k7so6416983pga.3 for ; Fri, 27 Oct 2017 17:10:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=aQt4CjPVoeTVU8UiK2CbV9vkeGMOIcjM40JwLNpg7Ew=; b=oz5/e2DHvRTHOXPIuCx19ch7Qcy45vJVPRDpkSmcC/I6ojPHmVXs1s20eZd6rVid0z cn0xrKR5YoOiesBeMhaFTfOgv1RzBPoG9mTAbP2Hbt2QcX7zgl3865/eIZprJLht9mB/ Ex5Lii0H9t+CIevw4RJlDqlSO7CSswKHsTrT2IZy640mDbN9DXs0XotltRd6xulatVmx 0fB2ZpEBCue2WWDPlzbHwBwxNtz/di98XRsJO+H5+DTgxlgIKtqPb6nB76C3QpX2Gtuq IgoGU+ULlNSG0U5Vq9/tBZ+yJbIoPSR7wdvmIXSFoPNP5FypnwPsvGaX2soFyqNB68gG VsGQ== 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:in-reply-to :references; bh=aQt4CjPVoeTVU8UiK2CbV9vkeGMOIcjM40JwLNpg7Ew=; b=YXYB2OA9gbkMP6BO+lurQLIVNZ9x5bg1pmEFRTrK6pppXFIJN0OfHXyZzlnvXU+Y4T UGUbAM1oFev3t9nYnbbLfZUFyO5Q6y6eTSyfnBnwylW6psKu5sSFdR5/rqchOQFuRTKe 0bUPP7ydwSUwR2QKe3Y3uAUuyhfU8sVu67oYTOrwvPRNx3jpSm627mQ2LDE1/BZhR1yb lw+fakVzjPB41PxXIq5oKRIojy8Gq15TG74ED8n/ackcWoeBFxQc6oQphzC3IMh90/Um nNaUM6/MCFHyg/3RzSwf6OGBANhQrQFJvbNuFMiKosdBu/OLX5248gOUSrPkmdOMgKV7 5ADQ== X-Gm-Message-State: AMCzsaUJ6JqKEyJc/YqJXbsQsZxF0+RKaT9TzdBAjSk5lv9Nta7ID/C+ B7dsCRVrSyLakPDQjQYROX2HWQ== X-Google-Smtp-Source: ABhQp+S0KX699/6EvYTymwf55NuqKKx2u6yJiwHRRnKT6zK3ge2R2X21FtaM/zwMYiz+1PD+4UenHA== X-Received: by 10.99.152.17 with SMTP id q17mr1587096pgd.287.1509149429032; Fri, 27 Oct 2017 17:10:29 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:28 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 12/13] gtp: Experimental support encpasulating over IPv6 Date: Fri, 27 Oct 2017 17:09:36 -0700 Message-Id: <20171028000937.2631-13-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Allows using GTP datapath over IPv6. Remote peers are indicated by IPv6. Note this is experimental, more work is needed to make this compliant with 3GPP standard. Signed-off-by: Tom Herbert --- drivers/net/gtp.c | 248 ++++++++++++++++++++++++++++++++++--------- include/uapi/linux/gtp.h | 1 + include/uapi/linux/if_link.h | 3 + 3 files changed, 200 insertions(+), 52 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 6190631574dc..1f9c0fc4833a 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -59,16 +60,22 @@ struct pdp_ctx { __be16 gtp_port; u16 ms_af; + u16 peer_af; #if GTP_IPV6 union { struct in_addr ms_addr_ip4; struct in6_addr ms_addr_ip6; }; + + union { + struct in_addr peer_addr_ip4; + struct in6_addr peer_addr_ip6; + }; #else struct in_addr ms_addr_ip4; + struct in_addr peer_addr_ip4; #endif - struct in_addr peer_addr_ip4; struct sock *sk; struct net_device *dev; @@ -93,8 +100,11 @@ struct gtp_dev { struct hlist_head *tid_hash; struct hlist_head *addr4_hash; + #if GTP_IPV6 struct hlist_head *addr6_hash; + + unsigned int is_ipv6:1; #endif struct gro_cells gro_cells; @@ -541,8 +551,6 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev, { struct iphdr *inner_iph = NULL; struct sock *sk = pctx->sk; - __be32 saddr = inet_sk(sk)->inet_saddr; - struct rtable *rt; int err = 0; if (skb->protocol == ETH_P_IP) @@ -555,38 +563,84 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev, skb_reset_inner_headers(skb); - /* Source address returned by route lookup is ignored since - * we get the address from a socket. - */ - rt = ip_tunnel_get_route(dev, skb, sk->sk_protocol, - sk->sk_bound_dev_if, RT_CONN_FLAGS(sk), - pctx->peer_addr_ip4.s_addr, &saddr, - pctx->gtp_port, pctx->gtp_port, - &pctx->dst_cache, NULL); - - if (IS_ERR(rt)) { - err = PTR_ERR(rt); - goto out_err; - } + if (pctx->peer_af == AF_INET) { + __be32 saddr = inet_sk(sk)->inet_saddr; + struct rtable *rt; + + /* Source address returned by route lookup is ignored since + * we get the address from a socket. + */ + rt = ip_tunnel_get_route(dev, skb, sk->sk_protocol, + sk->sk_bound_dev_if, RT_CONN_FLAGS(sk), + pctx->peer_addr_ip4.s_addr, &saddr, + pctx->gtp_port, pctx->gtp_port, + &pctx->dst_cache, NULL); + + if (IS_ERR(rt)) { + err = PTR_ERR(rt); + goto out_err; + } + + skb_dst_drop(skb); - skb_dst_drop(skb); + gtp_push_header(skb, pctx); - gtp_push_header(skb, pctx); + if (inner_iph) + __iptunnel_update_pmtu(dev, skb, &rt->dst, + !!inner_iph->frag_off, + inner_iph, pctx->hlen, + pctx->peer_addr_ip4.s_addr); - if (inner_iph) - __iptunnel_update_pmtu(dev, skb, &rt->dst, - !!inner_iph->frag_off, - inner_iph, pctx->hlen, - pctx->peer_addr_ip4.s_addr); + udp_tunnel_xmit_skb(rt, sk, skb, saddr, + pctx->peer_addr_ip4.s_addr, + 0, ip4_dst_hoplimit(&rt->dst), 0, + pctx->gtp_port, pctx->gtp_port, + false, false); - udp_tunnel_xmit_skb(rt, sk, skb, saddr, - pctx->peer_addr_ip4.s_addr, - 0, ip4_dst_hoplimit(&rt->dst), 0, - pctx->gtp_port, pctx->gtp_port, - false, false); + netdev_dbg(dev, "gtp -> IP src: %pI4 dst: %pI4\n", + &saddr, &pctx->peer_addr_ip4.s_addr); - netdev_dbg(dev, "gtp -> IP src: %pI4 dst: %pI4\n", - &saddr, &pctx->peer_addr_ip4.s_addr); +#if GTP_IPV6 +#if IS_ENABLED(CONFIG_IPV6) + } else if (pctx->peer_af == AF_INET6) { + struct in6_addr saddr = inet6_sk(sk)->saddr; + struct dst_entry *dst; + + /* Source address returned by route lookup is ignored since + * we get the address from a socket. + */ + dst = ip6_tnl_get_route(dev, skb, sk, sk->sk_protocol, + sk->sk_bound_dev_if, 0, + 0, &pctx->peer_addr_ip6, &saddr, + pctx->gtp_port, pctx->gtp_port, + &pctx->dst_cache, NULL); + + if (IS_ERR(dst)) { + err = PTR_ERR(dst); + goto out_err; + } + + skb_dst_drop(skb); + + gtp_push_header(skb, pctx); + + if (inner_iph) + __iptunnel_update_pmtu(dev, skb, dst, + !!inner_iph->frag_off, + inner_iph, pctx->hlen, 0); + + udp_tunnel6_xmit_skb(dst, sk, skb, dev, + &saddr, &pctx->peer_addr_ip6, + 0, ip6_dst_hoplimit(dst), 0, + pctx->gtp_port, pctx->gtp_port, + false); + + netdev_dbg(dev, "gtp -> IP src: %pI6 dst: %pI6\n", + &saddr, &pctx->peer_addr_ip6); + +#endif +#endif + } return 0; @@ -695,7 +749,12 @@ static void gtp_link_setup(struct net_device *dev) /* Assume largest header, ie. GTPv0. */ dev->needed_headroom = LL_MAX_HEADER + +#if GTP_IPV6 + max_t(int, sizeof(struct iphdr), + sizeof(struct ipv6hdr)) + +#else sizeof(struct iphdr) + +#endif sizeof(struct udphdr) + sizeof(struct gtp0_header); @@ -704,12 +763,15 @@ static void gtp_link_setup(struct net_device *dev) static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize); static void gtp_hashtable_free(struct gtp_dev *gtp); -static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]); +static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[], + bool is_ipv6); static int gtp_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { + unsigned int role = GTP_ROLE_GGSN; + bool is_ipv6 = false; struct gtp_dev *gtp; struct gtp_net *gn; int hashsize, err; @@ -717,9 +779,32 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1]) return -EINVAL; + if (data[IFLA_GTP_ROLE]) { + role = nla_get_u32(data[IFLA_GTP_ROLE]); + if (role > GTP_ROLE_SGSN) + return -EINVAL; + } + + if (data[IFLA_GTP_AF]) { + u16 af = nla_get_u16(data[IFLA_GTP_AF]); + + switch (af) { + case AF_INET: + is_ipv6 = false; + break; +#if GTP_IPV6 + case AF_INET6: + is_ipv6 = true; + break; +#endif + default: + return -EINVAL; + } + } + gtp = netdev_priv(dev); - err = gtp_encap_enable(gtp, data); + err = gtp_encap_enable(gtp, data, is_ipv6); if (err < 0) return err; @@ -738,6 +823,11 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, goto out_hashtable; } + gtp->role = role; +#if GTP_IPV6 + gtp->is_ipv6 = is_ipv6; +#endif + gn = net_generic(dev_net(dev), gtp_net_id); list_add_rcu(>p->list, &gn->gtp_dev_list); @@ -867,7 +957,8 @@ static void gtp_hashtable_free(struct gtp_dev *gtp) } static struct sock *gtp_encap_enable_socket(int fd, int type, - struct gtp_dev *gtp) + struct gtp_dev *gtp, + bool is_ipv6) { struct udp_tunnel_sock_cfg tuncfg = {NULL}; struct socket *sock; @@ -888,6 +979,12 @@ static struct sock *gtp_encap_enable_socket(int fd, int type, goto out_sock; } + if (sock->sk->sk_family != (is_ipv6 ? AF_INET6 : AF_INET)) { + pr_debug("socket fd=%d not right family\n", fd); + sk = ERR_PTR(-EINVAL); + goto out_sock; + } + if (rcu_dereference_sk_user_data(sock->sk)) { sk = ERR_PTR(-EBUSY); goto out_sock; @@ -920,16 +1017,16 @@ static struct sock *gtp_encap_enable_socket(int fd, int type, return sk; } -static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]) +static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[], + bool is_ipv6) { - struct sock *sk1u = NULL; - struct sock *sk0 = NULL; - unsigned int role = GTP_ROLE_GGSN; + struct sock *sk0 = NULL, *sk1u = NULL; if (data[IFLA_GTP_FD0]) { u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]); - sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp); + sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp, + is_ipv6); if (IS_ERR(sk0)) return PTR_ERR(sk0); } @@ -937,7 +1034,8 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]) if (data[IFLA_GTP_FD1]) { u32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]); - sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp); + sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp, + is_ipv6); if (IS_ERR(sk1u)) { if (sk0) gtp_encap_disable_sock(sk0); @@ -945,15 +1043,8 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]) } } - if (data[IFLA_GTP_ROLE]) { - role = nla_get_u32(data[IFLA_GTP_ROLE]); - if (role > GTP_ROLE_SGSN) - return -EINVAL; - } - gtp->sk0 = sk0; gtp->sk1u = sk1u; - gtp->role = role; return 0; } @@ -989,8 +1080,18 @@ static void pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) __be16 default_port = 0; pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); - pctx->peer_addr_ip4.s_addr = - nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); + + if (info->attrs[GTPA_PEER_ADDRESS]) { + pctx->peer_af = AF_INET; + pctx->peer_addr_ip4.s_addr = + nla_get_in_addr(info->attrs[GTPA_PEER_ADDRESS]); +#if GTP_IPV6 + } else if (info->attrs[GTPA_PEER6_ADDRESS]) { + pctx->peer_af = AF_INET6; + pctx->peer_addr_ip6 = nla_get_in6_addr( + info->attrs[GTPA_PEER6_ADDRESS]); +#endif + } switch (pctx->gtp_version) { case GTP_V0: @@ -1169,11 +1270,17 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) int err; if (!info->attrs[GTPA_VERSION] || - !info->attrs[GTPA_LINK] || - !info->attrs[GTPA_PEER_ADDRESS]) + !info->attrs[GTPA_LINK]) return -EINVAL; #if GTP_IPV6 + if (!(!!info->attrs[GTPA_PEER_ADDRESS] ^ + !!info->attrs[GTPA_PEER6_ADDRESS])) { + /* Either v4 or v6 peer address must be set */ + + return -EINVAL; + } + if (!(!!info->attrs[GTPA_MS_ADDRESS] ^ !!info->attrs[GTPA_MS6_ADDRESS])) { /* Either v4 or v6 mobile subscriber address must be set */ @@ -1181,6 +1288,12 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) return -EINVAL; } #else + if (!info->attrs[GTPA_PEER_ADDRESS]) { + /* v4 peer address must be set */ + + return -EINVAL; + } + if (!info->attrs[GTPA_MS_ADDRESS]) { /* v4 mobile subscriber address must be set */ @@ -1214,6 +1327,14 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) goto out_unlock; } +#if GTP_IPV6 + if ((info->attrs[GTPA_PEER_ADDRESS] && gtp->is_ipv6) || + (info->attrs[GTPA_PEER6_ADDRESS] && !gtp->is_ipv6)) { + err = -EINVAL; + goto out_unlock; + } +#endif + if (version == GTP_V0) sk = gtp->sk0; else if (version == GTP_V1) @@ -1322,10 +1443,31 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, if (genlh == NULL) goto nlmsg_failure; - if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) || - nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr)) + if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version)) goto nla_put_failure; + if (nla_put_u32(skb, GTPA_LINK, pctx->dev->ifindex)) + goto nla_put_failure; + + switch (pctx->peer_af) { + case AF_INET: + if (nla_put_be32(skb, GTPA_PEER_ADDRESS, + pctx->peer_addr_ip4.s_addr)) + goto nla_put_failure; + + break; +#if GTP_IPV6 + case AF_INET6: + if (nla_put_in6_addr(skb, GTPA_PEER6_ADDRESS, + &pctx->peer_addr_ip6)) + goto nla_put_failure; + + break; +#endif + default: + goto nla_put_failure; + } + switch (pctx->ms_af) { case AF_INET: if (nla_put_be32(skb, GTPA_MS_ADDRESS, @@ -1455,6 +1597,8 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { [GTPA_PEER_ADDRESS] = { .type = NLA_U32, }, [GTPA_MS_ADDRESS] = { .type = NLA_U32, }, #if GTP_IPV6 + [GTPA_PEER6_ADDRESS] = { .len = FIELD_SIZEOF(struct ipv6hdr, + daddr) }, [GTPA_MS6_ADDRESS] = { .len = FIELD_SIZEOF(struct ipv6hdr, daddr) }, #endif diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index ae4e632c0360..8eec519fa754 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -29,6 +29,7 @@ enum gtp_attrs { GTPA_PAD, GTPA_PORT, GTPA_MS6_ADDRESS, + GTPA_PEER6_ADDRESS, __GTPA_MAX, }; #define GTPA_MAX (__GTPA_MAX + 1) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index b037e0ab1975..1abf0f5c01fc 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -555,6 +555,9 @@ enum { IFLA_GTP_FD1, IFLA_GTP_PDP_HASHSIZE, IFLA_GTP_ROLE, + IFLA_GTP_AF, + IFLA_GTP_PORT0, + IFLA_GTP_PORT1, __IFLA_GTP_MAX, }; #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1) From patchwork Sat Oct 28 00:09:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 831559 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="jZnTwiPb"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yP1Nc1tLzz9t4X for ; Sat, 28 Oct 2017 11:10:40 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751876AbdJ1AKj (ORCPT ); Fri, 27 Oct 2017 20:10:39 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:45548 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751839AbdJ1AKc (ORCPT ); Fri, 27 Oct 2017 20:10:32 -0400 Received: by mail-pf0-f194.google.com with SMTP id d28so6012804pfe.2 for ; Fri, 27 Oct 2017 17:10:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=sZ9rgnW1Sj/f62nE5mnfxClv3sZZdhxkJRDARkza/68=; b=jZnTwiPbNXiOG9j3OIQ136UG037kysjpBnxYFleDAYcYEX9DYExl3Qw95DynV2SmUd I7GMJMkeL+HK+XjPuJzoh/ZZtinZppijXz8Mc1H7KdbqsEDOaxZnsivfl02C51AKNEz0 A0efErPPTMTnGWr7uRvfoIauo6eUJEB95GjGzw2Nxcu7WTDlgHmoiM0goQUsnjgidowF n5tcY7ZcAU7eFBWuMvplbrknHOLtmHJ3N9bYX2RlKbrF2niVJP2DT4snENqzV3lGIsGc SLDNL4esVVHq0eRvFv9iLUzW2IRnMpNHcDn6L874dK35bus9/ZgUUL3hmdTxgrasisbY lZ0w== 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:in-reply-to :references; bh=sZ9rgnW1Sj/f62nE5mnfxClv3sZZdhxkJRDARkza/68=; b=jDDFxLiuFc13J1I5drO2mCIP0c1HXjq5rhucuL+i9h/VxcCUyAHTV3vXnw3ryqpaQm pGa2UqidJYOSdODbZgXlS7AdmsgQQYVQhNAXWsPPeVpRII0n6B0p6cpv7CR+nND9x8aC Ch9/+qpumeBQq/efBOn2FPisgY3Fk/+rtxNNYx5cvGxwmzGUL63237deT6nxL4qYpcjB zKGWtgyn0SSlb53Svv2I8tvlKk7f+M2H8u30jhxCY8cVVn/fEvZesMRUrbTXXm0btLnU MNeW3q445MoFk1FRR0ICTlsW3j1CWFSBDvUCw7khwQARFFqfdEyB2sqUqV/A5RI6DASI 5bcw== X-Gm-Message-State: AMCzsaXKMl04G6kSnYXl9VgleNfMXsL+boA34MTnTZjcpB09/Y9LYfmW LSjM7JcVCO/ejwP7xvlggbz4Hg== X-Google-Smtp-Source: ABhQp+RnxeSUiRa5hpHOIljHMqlqSnvhwsY/f1C0lvSTVnPViYuydb8oIAzsUs9uUJL8pNE7T4PxTA== X-Received: by 10.99.116.22 with SMTP id p22mr607895pgc.372.1509149431498; Fri, 27 Oct 2017 17:10:31 -0700 (PDT) Received: from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net. [73.162.13.107]) by smtp.gmail.com with ESMTPSA id 2sm9068398pgb.30.2017.10.27.17.10.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Oct 2017 17:10:30 -0700 (PDT) From: Tom Herbert To: davem@davemloft.net Cc: pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net, netdev@vger.kernel.org, rohit@quantonium.net, Tom Herbert Subject: [PATCH v7 net-next 13/13] gtp: Allow configuring GTP interface as standalone Date: Fri, 27 Oct 2017 17:09:37 -0700 Message-Id: <20171028000937.2631-14-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171028000937.2631-1-tom@quantonium.net> References: <20171028000937.2631-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add new configuration of GTP interfaces that allow specifying a port to listen on (as opposed to having to get sockets from a userspace control plane). This allows GTP interfaces to be configured and the data path tested without requiring a GTP-C daemon. Signed-off-by: Tom Herbert --- drivers/net/gtp.c | 211 ++++++++++++++++++++++++++++++++++++----------- include/uapi/linux/gtp.h | 5 ++ 2 files changed, 169 insertions(+), 47 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 1f9c0fc4833a..5f38573babd4 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -93,6 +93,9 @@ struct gtp_dev { struct sock *sk0; struct sock *sk1u; + struct socket *sock0; + struct socket *sock1u; + struct net_device *dev; unsigned int role; @@ -451,18 +454,29 @@ static void gtp_encap_destroy(struct sock *sk) } } -static void gtp_encap_disable_sock(struct sock *sk) +static void gtp_encap_release(struct gtp_dev *gtp) { - if (!sk) - return; + if (gtp->sk0) { + if (gtp->sock0) { + udp_tunnel_sock_release(gtp->sock0); + gtp->sock0 = NULL; + } else { + gtp_encap_destroy(gtp->sk0); + } - gtp_encap_destroy(sk); -} + gtp->sk0 = NULL; + } -static void gtp_encap_disable(struct gtp_dev *gtp) -{ - gtp_encap_disable_sock(gtp->sk0); - gtp_encap_disable_sock(gtp->sk1u); + if (gtp->sk1u) { + if (gtp->sock1u) { + udp_tunnel_sock_release(gtp->sock1u); + gtp->sock1u = NULL; + } else { + gtp_encap_destroy(gtp->sk1u); + } + + gtp->sk1u = NULL; + } } static int gtp_dev_init(struct net_device *dev) @@ -489,7 +503,8 @@ static void gtp_dev_uninit(struct net_device *dev) { struct gtp_dev *gtp = netdev_priv(dev); - gtp_encap_disable(gtp); + gtp_encap_release(gtp); + free_percpu(dev->tstats); } @@ -758,6 +773,8 @@ static void gtp_link_setup(struct net_device *dev) sizeof(struct udphdr) + sizeof(struct gtp0_header); + gtp->dev = dev; + gro_cells_init(>p->gro_cells, dev); } @@ -771,13 +788,19 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, struct netlink_ext_ack *extack) { unsigned int role = GTP_ROLE_GGSN; + bool have_fd, have_ports; bool is_ipv6 = false; struct gtp_dev *gtp; struct gtp_net *gn; int hashsize, err; - if (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1]) + have_fd = !!data[IFLA_GTP_FD0] || !!data[IFLA_GTP_FD1]; + have_ports = !!data[IFLA_GTP_PORT0] || !!data[IFLA_GTP_PORT1]; + + if (!(have_fd ^ have_ports)) { + /* Either got fd(s) or port(s) */ return -EINVAL; + } if (data[IFLA_GTP_ROLE]) { role = nla_get_u32(data[IFLA_GTP_ROLE]); @@ -838,7 +861,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, out_hashtable: gtp_hashtable_free(gtp); out_encap: - gtp_encap_disable(gtp); + gtp_encap_release(gtp); return err; } @@ -847,7 +870,7 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head) struct gtp_dev *gtp = netdev_priv(dev); gro_cells_destroy(>p->gro_cells); - gtp_encap_disable(gtp); + gtp_encap_release(gtp); gtp_hashtable_free(gtp); list_del_rcu(>p->list); unregister_netdevice_queue(dev, head); @@ -858,6 +881,8 @@ static const struct nla_policy gtp_policy[IFLA_GTP_MAX + 1] = { [IFLA_GTP_FD1] = { .type = NLA_U32 }, [IFLA_GTP_PDP_HASHSIZE] = { .type = NLA_U32 }, [IFLA_GTP_ROLE] = { .type = NLA_U32 }, + [IFLA_GTP_PORT0] = { .type = NLA_U16 }, + [IFLA_GTP_PORT1] = { .type = NLA_U16 }, }; static int gtp_validate(struct nlattr *tb[], struct nlattr *data[], @@ -956,11 +981,35 @@ static void gtp_hashtable_free(struct gtp_dev *gtp) kfree(gtp->tid_hash); } -static struct sock *gtp_encap_enable_socket(int fd, int type, - struct gtp_dev *gtp, - bool is_ipv6) +static int gtp_encap_enable_sock(struct socket *sock, int type, + struct gtp_dev *gtp) { struct udp_tunnel_sock_cfg tuncfg = {NULL}; + + switch (type) { + case UDP_ENCAP_GTP0: + tuncfg.encap_rcv = gtp0_udp_encap_recv; + break; + case UDP_ENCAP_GTP1U: + tuncfg.encap_rcv = gtp1u_udp_encap_recv; + break; + default: + pr_debug("Unknown encap type %u\n", type); + return -EINVAL; + } + + tuncfg.sk_user_data = gtp; + tuncfg.encap_type = type; + tuncfg.encap_destroy = gtp_encap_destroy; + + setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg); + + return 0; +} + +static struct sock *gtp_encap_enable_fd(int fd, int type, struct gtp_dev *gtp, + bool is_ipv6) +{ struct socket *sock; struct sock *sk; int err; @@ -993,60 +1042,128 @@ static struct sock *gtp_encap_enable_socket(int fd, int type, sk = sock->sk; sock_hold(sk); - switch (type) { - case UDP_ENCAP_GTP0: - tuncfg.encap_rcv = gtp0_udp_encap_recv; - break; - case UDP_ENCAP_GTP1U: - tuncfg.encap_rcv = gtp1u_udp_encap_recv; - break; - default: - pr_debug("Unknown encap type %u\n", type); - sk = ERR_PTR(-EINVAL); - goto out_sock; - } - - tuncfg.sk_user_data = gtp; - tuncfg.encap_type = type; - tuncfg.encap_destroy = gtp_encap_destroy; - - setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg); + err = gtp_encap_enable_sock(sock, type, gtp); + if (err < 0) + sk = ERR_PTR(err); out_sock: sockfd_put(sock); return sk; } +static struct socket *gtp_create_sock(struct net *net, bool ipv6, + __be16 port, u32 flags) +{ + struct socket *sock; + struct udp_port_cfg udp_conf; + int err; + + memset(&udp_conf, 0, sizeof(udp_conf)); + +#if GTP_IPV6 + if (ipv6) { + udp_conf.family = AF_INET6; + udp_conf.ipv6_v6only = 1; + } else { + udp_conf.family = AF_INET; + } +#else + udp_conf.family = AF_INET; +#endif + + udp_conf.local_udp_port = port; + + /* Open UDP socket */ + err = udp_sock_create(net, &udp_conf, &sock); + if (err) + return ERR_PTR(err); + + return sock; +} + static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[], bool is_ipv6) { + int err; + + struct socket *sock0 = NULL, *sock1u = NULL; struct sock *sk0 = NULL, *sk1u = NULL; if (data[IFLA_GTP_FD0]) { u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]); - sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp, - is_ipv6); - if (IS_ERR(sk0)) - return PTR_ERR(sk0); + sk0 = gtp_encap_enable_fd(fd0, UDP_ENCAP_GTP0, gtp, is_ipv6); + if (IS_ERR(sk0)) { + err = PTR_ERR(sk0); + sk0 = NULL; + goto out_err; + } + } else if (data[IFLA_GTP_PORT0]) { + __be16 port = nla_get_u16(data[IFLA_GTP_PORT0]); + + sock0 = gtp_create_sock(dev_net(gtp->dev), is_ipv6, port, 0); + if (IS_ERR(sock0)) { + err = PTR_ERR(sock0); + sock0 = NULL; + goto out_err; + } + + err = gtp_encap_enable_sock(sock0, UDP_ENCAP_GTP0, gtp); + if (err) + goto out_err; } if (data[IFLA_GTP_FD1]) { u32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]); - sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp, - is_ipv6); + sk1u = gtp_encap_enable_fd(fd1, UDP_ENCAP_GTP1U, gtp, is_ipv6); if (IS_ERR(sk1u)) { - if (sk0) - gtp_encap_disable_sock(sk0); - return PTR_ERR(sk1u); + err = PTR_ERR(sk1u); + sk1u = NULL; + goto out_err; + } + } else if (data[IFLA_GTP_PORT1]) { + __be16 port = nla_get_u16(data[IFLA_GTP_PORT1]); + + sock1u = gtp_create_sock(dev_net(gtp->dev), is_ipv6, port, 0); + if (IS_ERR(sock1u)) { + err = PTR_ERR(sock1u); + sock1u = NULL; + goto out_err; } + + err = gtp_encap_enable_sock(sock1u, UDP_ENCAP_GTP1U, gtp); + if (err) + goto out_err; } - gtp->sk0 = sk0; - gtp->sk1u = sk1u; + if (sock0) { + gtp->sock0 = sock0; + gtp->sk0 = sock0->sk; + } else { + gtp->sk0 = sk0; + } + + if (sock1u) { + gtp->sock1u = sock1u; + gtp->sk1u = sock1u->sk; + } else { + gtp->sk1u = sk1u; + } return 0; + +out_err: + if (sk0) + gtp_encap_destroy(sk0); + if (sk1u) + gtp_encap_destroy(sk1u); + if (sock0) + udp_tunnel_sock_release(sock0); + if (sock1u) + udp_tunnel_sock_release(sock1u); + + return err; } static struct gtp_dev *gtp_find_dev(struct net *src_net, struct nlattr *nla[]) @@ -1631,8 +1748,8 @@ static const struct genl_ops gtp_genl_ops[] = { }; static struct genl_family gtp_genl_family __ro_after_init = { - .name = "gtp", - .version = 0, + .name = GTP_GENL_NAME, + .version = GTP_GENL_VERSION, .hdrsize = 0, .maxattr = GTPA_MAX, .netnsok = true, diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index 8eec519fa754..0da18aa88be8 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -9,6 +9,11 @@ enum gtp_genl_cmds { GTP_CMD_MAX, }; +/* NETLINK_GENERIC related info + */ +#define GTP_GENL_NAME "gtp" +#define GTP_GENL_VERSION 0 + enum gtp_version { GTP_V0 = 0, GTP_V1,