From patchwork Mon Sep 25 03:29: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: 818029 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="kJbg5X93"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qN16K28z9t4B for ; Mon, 25 Sep 2017 13:30:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932835AbdIYDaE (ORCPT ); Sun, 24 Sep 2017 23:30:04 -0400 Received: from mail-pg0-f41.google.com ([74.125.83.41]:53823 "EHLO mail-pg0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932698AbdIYDaC (ORCPT ); Sun, 24 Sep 2017 23:30:02 -0400 Received: by mail-pg0-f41.google.com with SMTP id j70so3268638pgc.10 for ; Sun, 24 Sep 2017 20:30:02 -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=H7R4a1v989F/1hXp0bbod6Na0WTSG5WBok1oEpXD/0s=; b=kJbg5X93JPpmEXFe0AaMs+EYzMuNus5Z16BjjnSkSN1F688FUlHSUpCx6o3MbQuJQk N7bdvaCNoEsVdhGIgwgSwuvim0rmiaO1ieN1n5MZFqB22ZY/L2sMGMacO4/L8RvVKAf4 IV5gcMmf7kzrDA3mqLm20SreZi/BiznZv+aomBhM1BrHxw3ZerCnJGDhDHnbydHVHbIh ffEuCqWM5d/dXI2d/x/lr12T+UquuSkweRKTmgoZcC16khNN5bftBZCcXJj+54AhjBmM xQyKzBw+m1h6f8KW+DsPDEwCIvAzQLos2ynb+pG62XeRCI+udtDZ2YTadfFLjHO/QLoT gDYQ== 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=H7R4a1v989F/1hXp0bbod6Na0WTSG5WBok1oEpXD/0s=; b=jay4B234ycsSRu86n+Ln2O1cx2jaDW8cyNb+w+TKrtkBdSGcA00C5bV6VuIdpcNGme 28dPNPcVp+Kgk46XV+bRcXlQZHZZ8+rhG+AaR0wCoafprQayhqWX+cdyujbJSTGs0ETI PmEPsgiO6ydOVub4BKALinvAn+VgCkuDtt1Gd7f76CVecKap0YsCyaYPjl0d8cpH/Zb0 IBBBfGgpaXhmVerKQmvtjRY042k0f6aLapYMgEtRReQlw2NF9jZG4BJCf4WftphJGsGD ahYfJw4CfngKFBVfhgbSwtq4V2JEfT1ddiztoe4N8vf65O/tAah0oqmqesEVBV9q6OOf ewag== X-Gm-Message-State: AHPjjUgsGdv1JEUSFPF21c707Jzt/aOTH1fj84zlm5dXr7BkXgOt/UdC UH7sZFLgAjB2HqNEl5MUjyDYBg== X-Google-Smtp-Source: AOwi7QB9ltpRTG/kA341p3zpQzckOBjpM02FOvcfAYGzXgzOXhn1g4jpKYMKIkVwrUKV7BoHU3il9A== X-Received: by 10.84.177.131 with SMTP id x3mr6350177plb.123.1506310201697; Sun, 24 Sep 2017 20:30: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 j2sm9112907pgn.26.2017.09.24.20.29.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30: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 v3 net-next 01/12] iptunnel: Add common functions to get a tunnel route Date: Sun, 24 Sep 2017 20:29:30 -0700 Message-Id: <20170925032941.14586-2-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 | 35 +++++++++++++++++++++++++++++++++++ include/net/ip_tunnels.h | 33 +++++++++++++++++++++++++++++++++ net/ipv4/ip_tunnel.c | 41 +++++++++++++++++++++++++++++++++++++++++ net/ipv6/ip6_tunnel.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h index 08fbc7f7d8d7..5a67301b0416 100644 --- a/include/net/ip6_tunnel.h +++ b/include/net/ip6_tunnel.h @@ -142,6 +142,41 @@ __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, + const struct ip_tunnel_info *info, + 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 IS_ENABLED(CONFIG_IPV6) + if (use_cache) { + struct dst_entry *ndst = dst_cache_get_ip6(dst_cache, saddr); + + if (ndst) + return ndst; + } +#endif + + return __ip6_tnl_get_route(dev, skb, sk, proto, oif, tos, label, + daddr, saddr, dport, sport, dst_cache, + info, 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..9650efff33d7 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -285,6 +285,39 @@ 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, + const struct ip_tunnel_info *info, + 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, info, 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..ea8f8bc0aaf9 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -935,6 +935,47 @@ 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, + const struct ip_tunnel_info *info, + 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 3d6df489b39f..a541daea1379 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1663,6 +1663,49 @@ 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, + const struct ip_tunnel_info *info, + 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 Mon Sep 25 03:29: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: 818031 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="du7suHjl"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qN26Vzbz9t4Z for ; Mon, 25 Sep 2017 13:30:10 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932888AbdIYDaG (ORCPT ); Sun, 24 Sep 2017 23:30:06 -0400 Received: from mail-pg0-f41.google.com ([74.125.83.41]:54616 "EHLO mail-pg0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932698AbdIYDaE (ORCPT ); Sun, 24 Sep 2017 23:30:04 -0400 Received: by mail-pg0-f41.google.com with SMTP id c137so3272129pga.11 for ; Sun, 24 Sep 2017 20:30: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=atgSc7cSWpfP0yeG8RydMP5L2g1hZzx81Z5EoLNlTI8=; b=du7suHjlPK2GHQ45itWrZcR8IqVxBt3Cda0BwHk28ynckxkoUsQkh4RcpSXfhs6DdM jPXk6roJWg7Msg56gR321kgHJLxUmvoARL8Tcv39q5Q77ZFcdZ7lBI8CrOhDTLYZ5Pr4 99QFAEZ4QL1eSV4aDXMsvjVudEwixDko5P5H46JIk3T2dvILEEPMEEY3EGRJcFygsfEK 4gi0PO82Qz6vXYD4L0cR97hRhTC0/Zeq9GRJNuiv3Z0EP+SXEsimG12Ll4x6P5YVTike pWRCs8K7d9x4otA1gcycH/8hBSKNoqdhjk3uM4bN7MshafYH4E+PjS7ec3ho+6HqFku4 sCdQ== 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=atgSc7cSWpfP0yeG8RydMP5L2g1hZzx81Z5EoLNlTI8=; b=qGsAO+6GIepssR6P+tnbRzECWyp9/Gr7A1xV4QS19nwOCJgeIhjRuF7J6cPZVqSWis lGPnb0LKrP7u3Ej7ClNfkfijfCPIXNP91DHuT2hHIErEGxdhaVqjfaGqmJSL6ruTokbe 73bRJCm7bZlB0uhXv/9PJ5KvkhZen5ZGeMebIuu6iVcS/SBFge3A8qwNRXWab+3MBC0S SDvazLFtjhD/Br57vaDzlYg0YhsvzwN60Us9qzz0/e6b3Kl5EOmhJHD5Ms93AwzK9lZD 50be0YUlGr+LmY0XiKRsKlP/utDUTLbjxhAnxB+Dpcep/hMFWcxui14dtEtimRiqyhG5 maVg== X-Gm-Message-State: AHPjjUhffeCVDSYSogZCtCGpItsu0ISNh04waWSnIvaoWGCsc8gJNvZH +VpFhDWqJ74QhHSxw3pIkPrVOw== X-Google-Smtp-Source: AOwi7QCHE3Jt6o06PlIyVCOLBTEbp1GZRLK8H5JfBU8jDL2t6tCH8NYHzJq3dJZWUugZ1xenNd1DxQ== X-Received: by 10.99.56.29 with SMTP id f29mr6343330pga.328.1506310204058; Sun, 24 Sep 2017 20:30:04 -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 j2sm9112907pgn.26.2017.09.24.20.30.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30:03 -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 v3 net-next 02/12] vxlan: Call common functions to get tunnel routes Date: Sun, 24 Sep 2017 20:29:31 -0700 Message-Id: <20170925032941.14586-3-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 d7c49cf1d5e9..810caa9adf37 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 Mon Sep 25 03:29: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: 818032 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="cijeXWcl"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qN34Bjbz9t5b for ; Mon, 25 Sep 2017 13:30:11 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932937AbdIYDaJ (ORCPT ); Sun, 24 Sep 2017 23:30:09 -0400 Received: from mail-pg0-f44.google.com ([74.125.83.44]:44472 "EHLO mail-pg0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932893AbdIYDaH (ORCPT ); Sun, 24 Sep 2017 23:30:07 -0400 Received: by mail-pg0-f44.google.com with SMTP id j16so3280452pga.1 for ; Sun, 24 Sep 2017 20:30:06 -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=cijeXWclirYlY+4ZxAabQosjlqFuwoj2ecA0LPFMZgNM6cfLVBrPfSXllabqxJRZ+R Micg7i2LKEx94KRqcNNH1LH/rK2ANdTWIeOlDGu3HR5mB5lOvnMZ/wPH5MBqzDv7tUmS KEnZOMXPMNn62OeHvztolHVNOITa8lHslFPEL4ygjOTA2iBm1rhX28SgAeP87rDogTZH 23j+rJQzEpGfKVEwXXJQbOdVrTl1Rr7bb5BhzPUcZD6e/2gkGpYDMYriMHrrbw1uRes9 3MuDtdz0f6P9McfOlPZ8eN7i8HPjvFThfG6fVcQa9IcNh++wJloBJrGnAQXjoetkX1yp FU2g== 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=ueD9ZZeaLbsPiSj6wxfpBqRv86wdBJMXGsUG5ArU9okjzweniopr2MD02K8BoEtUg8 wpxucFLOhNNTRRCZvQMORT7ndoSVI8iZJA7/XKUpircSKSiHhl2tMPXz1Z1/5Zxh4d5L rSh5amHF8JzLvU6jp1iKcU+lNNPGA2omHLL03DtAYxT3aHUSfkNTLGB7KT0ZUbeEanSQ 7qMjie5ofUfCdnOYMraLCBO7fCw3FeZyUCHHIWijCfF5DwQURtcGw7lp4FaLAqWeXg7F z6qxI5Qb44p11zVrXugqus08klBSUmJ7uzYOgBTxBH8qJqlPc1C6QO3aVgaONAvaCF3P z9+w== X-Gm-Message-State: AHPjjUgjXLb+HZ83OzBfdAW6HrQov0Q2kIlDy0IWgIqKyl9oLkWX8znK 1RnrU/6FZUwQsb6tgremRip59A== X-Google-Smtp-Source: AOwi7QCH87bhSMAoXULZgJr5xAXmcZMZc6qyLjhg5x0L/7sY8b4FwY3y4cyJHxZEGYA5ky3XzUTTmA== X-Received: by 10.99.103.2 with SMTP id b2mr6182704pgc.177.1506310206442; Sun, 24 Sep 2017 20:30: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 j2sm9112907pgn.26.2017.09.24.20.30.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30: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 v3 net-next 03/12] gtp: Call common functions to get tunnel routes and add dst_cache Date: Sun, 24 Sep 2017 20:29:32 -0700 Message-Id: <20170925032941.14586-4-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 Mon Sep 25 03:29: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: 818033 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="u4NC64+N"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qN56fFvz9t4B for ; Mon, 25 Sep 2017 13:30:13 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932967AbdIYDaM (ORCPT ); Sun, 24 Sep 2017 23:30:12 -0400 Received: from mail-pf0-f180.google.com ([209.85.192.180]:53657 "EHLO mail-pf0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932893AbdIYDaK (ORCPT ); Sun, 24 Sep 2017 23:30:10 -0400 Received: by mail-pf0-f180.google.com with SMTP id x78so3134972pff.10 for ; Sun, 24 Sep 2017 20:30:10 -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=oZKveqoes9D18SVp3KtzsiipJgaPIVkzyRcXKyWNBJ0=; b=u4NC64+NXVmy6qVxb9X5DCcWZ2ZLiWBQf02WSQu8TZBjKOV0D0liWK1QRlVp6GfsLZ B3xCUhnfPsxV7IQ+cRgf5rD9KzF7mPbGI20m2k0KTSkyXsFqOvQvavLCxPB6meW+Egwk 4cV4kMXehL2Pqbu0azkMmIYm4F/NzL+ZFjvcxlY+9V/Ul0jBFP9pLAclEXPzI3gylHJk tamp25MloUaU9s3ntgwXVtGGbweqwdp/meWSURdSvxFmOZiPhQWc/l3PtoeEpH3/+4I1 qEWZIlUDNQ7Zf8upU4kOza9cWB0M/105koBPSk9xDMPZkirEe1T3ylGE2nWkfkCxCvnI XGUw== 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=oZKveqoes9D18SVp3KtzsiipJgaPIVkzyRcXKyWNBJ0=; b=T2Rn1XAiHZ5L+C5SxKvwEaQFrz3ugXJ3NPUd0WeJQ1xG2ykwrYe3JarE3eDvk+LQ6v fyAZ6oaRePagVg1xAOG52ElhDrYi2P0LGBsJxwezrg4FUTNve18OvQ9opypMGe+mErYi 6cUm/rzZOGmrlbC2veZAZFR99vs0Vb6Ua+QPTqhTiGBYdO1zkYwlt65q5cpXeWAfr8e6 fsKl9t5o4aKn8TerVqoW9dQkbd5OL4YTppPCBHfImvcjiRmq9qqmVhPKBEcmdVJ9COVe xOQgnP6rzKibKdRzP8S+gH/g+qPYsIN31DVQmCHb6qQX0s4K35Pgg3G71w1st3zANcGZ 3Pcw== X-Gm-Message-State: AHPjjUjvpW70MRsnihuxMUd57nXgH67TNTHwY/Nx+mdrrfMkLUcu17x4 g/FbmmzcLTujouVvms+SQw5yNZO5 X-Google-Smtp-Source: AOwi7QCnWKs/ObOBjmZ4+aPbqLQ8o1C6OtqMmENh/tLM/TSfsMOREYCH/SOIKIsvWZ7UlrwPXvOKtQ== X-Received: by 10.99.126.87 with SMTP id o23mr6180129pgn.277.1506310209589; Sun, 24 Sep 2017 20:30: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 j2sm9112907pgn.26.2017.09.24.20.30.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30:07 -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 v3 net-next 04/12] iptunnel: Generalize tunnel update pmtu Date: Sun, 24 Sep 2017 20:29:33 -0700 Message-Id: <20170925032941.14586-5-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 9650efff33d7..880c9ea5b08c 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -318,6 +318,10 @@ static inline struct rtable *ip_tunnel_get_route(struct net_device *dev, dst_cache, info, 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 ea8f8bc0aaf9..31d6dc9f6859 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 Mon Sep 25 03:29: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: 818034 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="ylVwd0sq"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qN82r3Vz9t3t for ; Mon, 25 Sep 2017 13:30:16 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932992AbdIYDaO (ORCPT ); Sun, 24 Sep 2017 23:30:14 -0400 Received: from mail-pf0-f180.google.com ([209.85.192.180]:52098 "EHLO mail-pf0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932947AbdIYDaM (ORCPT ); Sun, 24 Sep 2017 23:30:12 -0400 Received: by mail-pf0-f180.google.com with SMTP id b70so3138692pfl.8 for ; Sun, 24 Sep 2017 20:30: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=ptyq9wQpaDalqO+2nGacNTdjmcEZaMvikI4fAhqHJTQ=; b=ylVwd0sqJj+RGKAvY4BYSIWhMWJzW0qsEGc4Q/OrQlMnQ7xuvLFipyNE4FAyTwfLsr /sn7XSuhsllVZutMmBHlZlxcOWOY/ADQwxilmsw/zyTOte6KuD8gCPRW4ppyZq9v8pnI wGkSOEv732rqkuVjrMI3oF+kGrsyOh1/th1i63s3zPawUtlj4naeIAgaW5qxJ4u1Mmiv Z1nJtQIFB8xNovvnnNKqRZgsauN5sN9XswvxQQsPof0M3PCYhYQcVV/2AQo7e98ji4Fk fpCIY/JRQmi7ucPQqfxsgoK+SrNDyyAKXNkxm3FztRUOpLAPSf7O3yp90ImKO4c6nY5G GTvw== 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=ptyq9wQpaDalqO+2nGacNTdjmcEZaMvikI4fAhqHJTQ=; b=Xtla5KB9JVCrj8RRvEBiyUZetMFyEFkmbdAxHifJI9oVKMKga5AQK+Cg2CmiEZNM01 itIFuLE2HLtFkeU7Put8lZrPpqZoCrPkp8OPOsWX7XhqyPlHOtMoDkTjNrCXCB/p0p/2 lsVBAQMBj7X5gHqiKmuZYIRl/ZRt6k4eFvjNOhlSSAI9mxyd7PJ3BEcYQ4Tlx5ePdumQ fZvvNd5P8+RORYmSpEmyEJY4xIjEW+piFiZLtSvMAJv9R/WO8H0iaXrDxzhQKhXDlKCh x7mDRJkizZ+e8mOXc1zrvAj2sBvyUI2jHYn0LEFTrHeP+YGV6X9g2wS5vX0ZeMOzLrnv 0eVA== X-Gm-Message-State: AHPjjUg+gIjiR6tTOoJShTOsBkCR4c1LmIdB+WQH97yc0X5xHH8lk4KU RIxU26RWwOLS3I1DnImv8K0wAg== X-Google-Smtp-Source: AOwi7QCrzyp/tFNY8bhepq1Es9TX3HMYd2iDfeeDrGi5L788zczkmfQ0HJseJ2q5pZvQsVzaj4UGpQ== X-Received: by 10.84.224.75 with SMTP id a11mr6322814plt.106.1506310211862; Sun, 24 Sep 2017 20:30:11 -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 j2sm9112907pgn.26.2017.09.24.20.30.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30:10 -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 v3 net-next 05/12] gtp: Change to use gro_cells Date: Sun, 24 Sep 2017 20:29:34 -0700 Message-Id: <20170925032941.14586-6-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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/gtp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 6dabd605607c..f2aac5d01143 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; } @@ -611,6 +615,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 +636,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 +694,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 Mon Sep 25 03:29: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: 818035 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="Lh/CRKEw"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qNC0czJz9t3t for ; Mon, 25 Sep 2017 13:30:19 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933009AbdIYDaQ (ORCPT ); Sun, 24 Sep 2017 23:30:16 -0400 Received: from mail-pf0-f182.google.com ([209.85.192.182]:52100 "EHLO mail-pf0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932986AbdIYDaO (ORCPT ); Sun, 24 Sep 2017 23:30:14 -0400 Received: by mail-pf0-f182.google.com with SMTP id b70so3138736pfl.8 for ; Sun, 24 Sep 2017 20:30:14 -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=M3FXeq2nLYeSn0fU0Ho7wThC1D83EIjbYlgwheu0zTM=; b=Lh/CRKEwzK/9ZUpWndBR+fm8bGlpdO1nK5d5ZzFzu5f+w+R3V7TWGawVO36X7nfHiD RKraRjRQzgHXZlJmLvvit2v1lIpYIJ1L0ipCZLmzjoMp1Q8fF9Xm0OTsrwrb/1aHqOTB Ut6RhAQ1j0aV/U31hOv7juTn+8K3DLJwR/8Y2GHbI4BojR0DCw+hiLzcWlwocjUT/0YA NewIkAFfSDo4WdGAPKKMLiX7Phu/hD2u4O/znc7B7vgOiiAh4oVstJeVba673YcOtlat ZkQBfwR6EU8ebblZmX5L1R7wVl25qviHjPNaNevfh0+X3PUftOd8ozGeUdwYOMvae4lG IsmQ== 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=M3FXeq2nLYeSn0fU0Ho7wThC1D83EIjbYlgwheu0zTM=; b=pE4Gz7NPZL+g+FYi/LvwvDRgj7V2RZ43Ofs4tDfDyfpP7/JLdPJraJ/ATJ/UOAEBps SZdaQDZ+l2s4SFN5a8s3UkS8kD+KsnsOyyKE27gDMmtXiduz2vcseoh8lc1ss0DFTyw8 VsiJMYtv7ZYalUyLqIQIWyOlsw6xCvUHLhSqhfcuBpJ8g3tPt8Yt0DnEuGmjIsx4QQxH NeM3vBpk3lkUmGO8LgwFpS5P/ovuBQlmkty7fY8nIwTYCW45cG03BBlfeG6WPi6tLxZ/ JeV7Ee7r4KroSbfLsxX0jQa4T578c3J9Njt7o2ia9+vLXzE0VdSEXVTY0Qci17X0RtPb baGQ== X-Gm-Message-State: AHPjjUhjhgJIRbbIChNXEi61GD5MPvKn1wKf7QJOgYp+nE/+JZa3/zyQ yeMlOhf4uQgQRvJksaEsPA5PzXRF X-Google-Smtp-Source: AOwi7QDwWGA0EN3feX9iVKt/b8iGgcN9HNz2GGIbSRZL/fKE8OzoSXs6j3DDb5cXtd5mwyXpR8b19w== X-Received: by 10.84.252.144 with SMTP id y16mr6418958pll.113.1506310213937; Sun, 24 Sep 2017 20:30:13 -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 j2sm9112907pgn.26.2017.09.24.20.30.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30:13 -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 v3 net-next 06/12] gtp: Use goto for exceptions in gtp_udp_encap_recv funcs Date: Sun, 24 Sep 2017 20:29:35 -0700 Message-Id: <20170925032941.14586-7-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 f2aac5d01143..00e5ea5cb935 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 Mon Sep 25 03:29: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: 818036 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="xtg3Ru7L"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qND4NB3z9t3t for ; Mon, 25 Sep 2017 13:30:20 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933037AbdIYDaS (ORCPT ); Sun, 24 Sep 2017 23:30:18 -0400 Received: from mail-pf0-f173.google.com ([209.85.192.173]:48801 "EHLO mail-pf0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932999AbdIYDaQ (ORCPT ); Sun, 24 Sep 2017 23:30:16 -0400 Received: by mail-pf0-f173.google.com with SMTP id n24so3141451pfk.5 for ; Sun, 24 Sep 2017 20:30:16 -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=G5gS2YcdNOL7PfeoOGrAzI2uDXz5s6P1cpqdBXFzg9c=; b=xtg3Ru7LVhAZAUixYRshyYTezmSvuOoM+zEzV1h518NLRwx5b0lqcd3jKIpwEjgXzf 8XnGrmd2mAeCT6LU17iK8ulu8J4BpgmmrufP38UzfcEjq7tSgev+h/sGcqa1vdwdIUvB DKpLoj4RXeuFtYHaIL+qSMWi5X2c/bS847lIBtyf4Uypxv+rdvooWv8XyIbPmHwAR51B rTKBCyRnWvHBGthzcn/fBFWrs/l5EVCQyL/Zd+NfUkZznAlcXfuzaM3cFGgavk1Eq0xV nDdpOv9hL+P990aHVir/naWXZP7WI4jesRbwL52I86Xlo8Fu2I/bJkegFreZzOpF0Vcf Ir/w== 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=G5gS2YcdNOL7PfeoOGrAzI2uDXz5s6P1cpqdBXFzg9c=; b=OvYG2UwtC6ohc3qgUWMwuk+t5V8EIvMvglOtWKeFKv/e3jrRHG3M1E2HNHV0jq4Q6O bfUMyyAgmWvcZafY5dgdOUZWfLEcKsF0DN74FR5SfMbWfeSZ1keyzXIfRB41/utTxTwD lyw6J84yzcuMO9DDnHWsn7oMpoBByemYgYkpXU6ugIBMwJ9K2S+nJKFsaYmT8tv6Aabb taKGh5w6zFScu3HikSJA7WDfDoLoQOtTMSJCJ9RohgfSbg9fhfb0S0JsfrytqVliMjRo lVXRwJaUM5S1HpurAMfcp9oXgtngO3K/1jCcLxahyuYTjMY0yEdVtE+RROgbcHqn4xnx H9Kw== X-Gm-Message-State: AHPjjUjXDUGo7WfckRspyfLEC5sngLn9yoK5edo98blmttZCxRVqrQjr 3nT9SqLIp9CioC37bLTvgXUhHw== X-Google-Smtp-Source: AOwi7QAsCUZQLlaIfAtVWEIy0wxMZwxXvmvWgYYzLwmQx1rym9YYHZzghuajpIWvMMMNWJC5u4JhLg== X-Received: by 10.99.168.72 with SMTP id i8mr6369839pgp.427.1506310215978; Sun, 24 Sep 2017 20:30: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 j2sm9112907pgn.26.2017.09.24.20.30.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30:15 -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 v3 net-next 07/12] gtp: udp recv clean up Date: Sun, 24 Sep 2017 20:29:36 -0700 Message-Id: <20170925032941.14586-8-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 00e5ea5cb935..a6e2e0a1f424 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); @@ -824,9 +810,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 Mon Sep 25 03:29: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: 818037 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="faC8A0GM"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qNJ1T2mz9t3t for ; Mon, 25 Sep 2017 13:30:24 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933054AbdIYDaU (ORCPT ); Sun, 24 Sep 2017 23:30:20 -0400 Received: from mail-pf0-f173.google.com ([209.85.192.173]:56614 "EHLO mail-pf0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933022AbdIYDaS (ORCPT ); Sun, 24 Sep 2017 23:30:18 -0400 Received: by mail-pf0-f173.google.com with SMTP id g65so3132230pfe.13 for ; Sun, 24 Sep 2017 20:30:18 -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=c9b+Zk1pz2iqm+GXKGvvZ1oRizQA5GgRF8hIJCjrWB0=; b=faC8A0GMWkzvCkA7THHt6Y5Pe827okR/RNoZsjn8RxGXltKZb+bmd2kiUtpVRsRBWh 7Ra3KlloB46ZOOWsXvuHSKb6cXwEKVN0ykl4hOYm4j+1DOOVCIWJbW4yXiywMc2ldz57 KKAlh+GQx5ztFp2EgIId/2NsUSdgaygwr8eqWmK6O0fOs6P6/ThjjxU6uKWfjZ1RGlMg 3ZeVi4FAXgf7MEOsk+PoodPNz8Z6KJThU3GmFBdi1XPnSHILsxTNXNfnyL+xAyd/K7sZ awA9E5Qv1nIp3xDuo6mQXM+Qt8h0QG1mJLmE9kdxwQpG7qlMFc4QkcLtZgIk2jEVK5A/ d/Mw== 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=c9b+Zk1pz2iqm+GXKGvvZ1oRizQA5GgRF8hIJCjrWB0=; b=O1nkosoqLy79c+QLmZ4TFOtpPQAadTbRZbkMmTncRTvwZ+V1ZSJ1VFhfd6/L+tQaAR ZyQp3A7Xxu7jpUeybMy/Qukp9QCNiYM/f9PRlxT7dwcvrlevI3ZelZ17YVumHBNAuM2G vEA67NNEDuLKhcE2R/REBCjOJMcIs5ssCTPXimdDPYOFV4CPXbZsLP5673z/csP+iSyM k3tiAUYhZoa7VwjIr39Fgavgk7hXzabo1RbXDLykK2b+UWIRVu0yfYxZq7wovyxoBr8B 2J1s8R5O9zw3TbdM3AWUzJ25/tU6heXYYI/h6WYlJDsW+T2nErAOH3pv+DhhqT3nBuoS vNaA== X-Gm-Message-State: AHPjjUg589ihn7j9T+vHKmGd3B4w1T4ALleAjlK7QtH1ecs1qFNBMyub 9UOS0T78ID6BHj9QkCagsQ3Kwg== X-Google-Smtp-Source: AOwi7QBanKcRNHlp7hZ7lFNERc5foVVlhHHfPDaoCnVAhwSkMavQkoLGI4brmEqAOxv4XRBVKgdkYg== X-Received: by 10.84.132.34 with SMTP id 31mr6193721ple.225.1506310217998; Sun, 24 Sep 2017 20:30: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 j2sm9112907pgn.26.2017.09.24.20.30.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30:17 -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 v3 net-next 08/12] gtp: Call function to update path mtu Date: Sun, 24 Sep 2017 20:29:37 -0700 Message-Id: <20170925032941.14586-9-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 a6e2e0a1f424..bbb08f8849d3 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; @@ -467,8 +468,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. @@ -514,37 +513,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); @@ -915,10 +889,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 Mon Sep 25 03:29:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 818038 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="wekvWgSC"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qNL3Gnxz9t3t for ; Mon, 25 Sep 2017 13:30:26 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933068AbdIYDaY (ORCPT ); Sun, 24 Sep 2017 23:30:24 -0400 Received: from mail-pf0-f177.google.com ([209.85.192.177]:54487 "EHLO mail-pf0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933044AbdIYDaU (ORCPT ); Sun, 24 Sep 2017 23:30:20 -0400 Received: by mail-pf0-f177.google.com with SMTP id d187so3136914pfg.11 for ; Sun, 24 Sep 2017 20:30: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=1jPs//2PQQ6nFjehrosWRdlrzA317lfzDVLuu7P/x9Q=; b=wekvWgSCQM3g9tOnMsDItoe5Q9sJGDJ9hgFQZkvWmndL7LDAOJswCjPkBdhjzGGBAk MY1Kx2IqFz/jpgfHM/xguBfgRjEjUeBfMH6PlnCCRFAMcWAW/+AgdIeOtBAVafd9ihsX DVWpms4xcUxJik+glraIELsUtQG5Taw+JJBTSoxLFVZGZyMCmAzMUAhpHKrk27qKRZqM Lw3PPh35AO4Wpp0lcrr9fa771SAh4Lbx++kyKLvzjq2Pq+nykwWTolcvZwX6unX51rIt ktKYZHe79RURCxLOuWInNdbwU2UhX505zhbpOZ4jMENnHa/WuVDDaTWQGpHraEaKlUcB IdAw== 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=1jPs//2PQQ6nFjehrosWRdlrzA317lfzDVLuu7P/x9Q=; b=qFh9/GmqpQyiKPlNuoL/vDp+zgE8l9R2WUh3KFss9+MakNF5kmyMfeA4jyBnaSGQ/p Tk8MlCpKKURTVwlOZ2qb/JuYkpLDGygS5OdqRG+2Eqve7Uh6Uce8NqRBi25oIV3hz1oP yfRW98G1rZ2X/zWdIxyqe3qsuxDT2lR/TS7UOIqfJaaj4q2Ld5d+LhVnj5kdUAYqV5rn 3WTB2PRS2wsZymazX1YLxCH1Dmtf6Q8PznQ5rOkSNfP83JBmEqpSJc7cAQp7FUV197tQ DiSAQAJvYq8NhCvC+mroa43+Hn8U9ryzh/WSYdUkaw1A0XoBTI58tST4blpmMI8mmMcU fHJQ== X-Gm-Message-State: AHPjjUgYG0YwZFBmmtGinhyVzIVWwpU30xvmHaGnN+BcKRnpiC+InT1k 4kz3g32gIMFNJm39J/NK8e6s2HEB X-Google-Smtp-Source: AOwi7QDrq3n6iQllG/6dqSE+2O1k64wUdD15+sctNNgi9e4/jsv9w+GcPvqvy1iNaF0NWq/uirBhmw== X-Received: by 10.84.134.35 with SMTP id 32mr6375508plg.20.1506310220181; Sun, 24 Sep 2017 20:30: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 j2sm9112907pgn.26.2017.09.24.20.30.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30: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 v3 net-next 09/12] gtp: Eliminate pktinfo and add port configuration Date: Sun, 24 Sep 2017 20:29:38 -0700 Message-Id: <20170925032941.14586-10-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 bbb08f8849d3..44844eba8df2 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; @@ -420,73 +421,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. @@ -494,81 +458,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; @@ -874,6 +846,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 = @@ -890,15 +864,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 Mon Sep 25 03:29:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 818041 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="fuTVGWlo"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qNY218xz9t4Z for ; Mon, 25 Sep 2017 13:30:37 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933128AbdIYDag (ORCPT ); Sun, 24 Sep 2017 23:30:36 -0400 Received: from mail-pf0-f180.google.com ([209.85.192.180]:47507 "EHLO mail-pf0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933022AbdIYDaW (ORCPT ); Sun, 24 Sep 2017 23:30:22 -0400 Received: by mail-pf0-f180.google.com with SMTP id u12so3144432pfl.4 for ; Sun, 24 Sep 2017 20:30: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=6pKmF1ebjceotI+8CDC/igN0VTICOLDDuxXuQvdd7Xc=; b=fuTVGWlo7nGkxWX7ix/eU76RVxXoMg4sngOYIzdVhd9cp5tukDWAh3MKskwDW93aH4 28PBbct8GAzyoowqCBT/3TG/9noIqNVxYIfeGetJ1MExNwb4w68VLHaybD/yV3THbT54 uiH3O1prNtwVGg1xIbuBiXYJLO5XeL4dahlG7iU8J/o4JXEMTO7rjfLtqHpFAXc8UMqC nE5ymhyX+5d0SKVSHCbfvXWeUrjf2ure7T17Ktjz9f6Rg56qdFPgUGZ0oiSt5BPsBBLG +AAT1hrgjFC7LWtMmIoQw3T4Cy8cFyfpyLLx9CYCNuWaEP7XTuAElffnrOsfzfYIs8C1 reFA== 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=6pKmF1ebjceotI+8CDC/igN0VTICOLDDuxXuQvdd7Xc=; b=bzbsyqN6ip7OIUoHZk4AZPQx/5Z86tQG/zSgVduGrTP0w8JB3DLdI9DnBCAfXOgiCQ 8FMqfBjAZjyg/hkjFNshIGX672iK76TW4DpVaggp5FON/f+yu0INO5UrnseKRaMYvwHo JNW3Uymkkcvr05rVZqhaAGLsEqQtK66vginc5777ZUEsdyKD48tS0uZ7TB25LJOMnhNB bEVYE9usB56uKf0Sr+IyiRSr3ButAcDk+XGvHs7p3euIsIgtXQoT8ia+8d3iKHvyul1Z +MYt54agMs30cJbwRlIGs3h+/9fRo/x+FO/Si0DFA/SJTwL2dDqU1MXW0USCtjIbAGJk HQcw== X-Gm-Message-State: AHPjjUj/46DwSKG5jr4IOxL550qX6WFxQi6QCdp8ZDRdBMPeSYN3hQFB CmPPhF91CL5K/2BPsBbRF+je6lbj X-Google-Smtp-Source: AOwi7QBIF3znow7xM3VlWHZ6b1LBcCKKk3yZhaPqS0XNWvDemh8+LOhtFt19vUkgp3YBLxgKxe41/w== X-Received: by 10.84.165.171 with SMTP id y40mr6307060pla.373.1506310222220; Sun, 24 Sep 2017 20:30: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 j2sm9112907pgn.26.2017.09.24.20.30.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30: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 v3 net-next 10/12] gtp: Experimental encapsulation of IPv6 packets Date: Sun, 24 Sep 2017 20:29:39 -0700 Message-Id: <20170925032941.14586-11-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 aba0d652095b..8e55367ab6d4 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -225,7 +225,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 44844eba8df2..919ec6e14973 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)); @@ -391,7 +486,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; @@ -523,6 +619,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; @@ -692,23 +807,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; } @@ -722,7 +852,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); } @@ -844,16 +977,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: @@ -882,33 +1012,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", @@ -934,7 +1090,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) { @@ -951,7 +1120,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) { @@ -993,11 +1162,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) { @@ -1036,7 +1219,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(); @@ -1056,6 +1239,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]); @@ -1126,9 +1316,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: @@ -1239,6 +1447,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 Mon Sep 25 03:29:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 818039 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="Hc5tBNij"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qNQ6ZNmz9t3t for ; Mon, 25 Sep 2017 13:30:30 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933102AbdIYDa3 (ORCPT ); Sun, 24 Sep 2017 23:30:29 -0400 Received: from mail-pg0-f43.google.com ([74.125.83.43]:51236 "EHLO mail-pg0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933072AbdIYDaY (ORCPT ); Sun, 24 Sep 2017 23:30:24 -0400 Received: by mail-pg0-f43.google.com with SMTP id k193so3271719pgc.8 for ; Sun, 24 Sep 2017 20:30:24 -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=OXUGchucXcUf7bydYwkcOwhbIkeA/9SejDVsVZQgpBw=; b=Hc5tBNijo6T6048gEyxCKktqTzyc2O7gE5DF2wpoiGs9yWMMHuwemiQRvS7v1kYBLP rUFlVaZ0Ao2hIkMwafG6lbXxbRrNZnIc+5AnCWPqUU0PGSt3GZU3iw749dYH4zHLSQG2 bZsxjFFKocQlMJM918JXo1FYdOya5U17VmXJvW4cT8IGB1OuSjHqFF8mGvYlmWA8cS7s j6HVLOwi42Y7HjtC4+x3nH2rPhFWOjGJY7m5824yQpX53UsTN/UKKX1vLHhScdJWHAN8 MhSxZjbNLffhov357rstxRT0REm+ZMhDNA1d+XY6VkBCaUQt4MP1cPYtNIXy2OUk1WgB vTxg== 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=OXUGchucXcUf7bydYwkcOwhbIkeA/9SejDVsVZQgpBw=; b=cFBxpyJULObDeN1T6/XqFxVyK1OimUivpGNOGYALA/V/+SiS4WgylJSj200sqbUB+2 J/d0zaeWQMy5zgZJLj0gjtv6rFTGgEToUyuLHTZU8wWODk/7GzJXTixIVYIUa9ZxcnG0 uMiITi4O5YEPJCi2VRq/5abT8l/kS2OQkrE4C0qn09LP7m/cl1oGaGVG8WmDxqF3/Tnl 2/NS2jR35G20QPs+zlRxk5T24VnPT6YBzLCKOZZJvSkflNUOpvbJA0leT1xhUNZBzkTd zLWAHK1fzMpIUlYsBoX63fLDcjTN0S47dYf7BocJqqXLfaZgdkAUi3KC12y9v2b3VQeh GxKA== X-Gm-Message-State: AHPjjUg6FNLM4YTqXDu1N055HYpDgSoXcJaWJwI0rzfGxjnblq0U38Zv mCMXWJeEV6NYDdKFMeW5/OnIBg== X-Google-Smtp-Source: AOwi7QDQSRWuzcP3QBktPjKNdaIgHqKTPcCIvGyWwa8JCYItPQ0ycBA1iz6NP434C2WsO1mY6mWZjA== X-Received: by 10.159.194.10 with SMTP id x10mr6442144pln.47.1506310224388; Sun, 24 Sep 2017 20:30: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 j2sm9112907pgn.26.2017.09.24.20.30.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30: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 v3 net-next 11/12] gtp: Experimental support encpasulating over IPv6 Date: Sun, 24 Sep 2017 20:29:40 -0700 Message-Id: <20170925032941.14586-12-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 919ec6e14973..1c580df4cfc5 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; @@ -534,8 +544,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) @@ -548,38 +556,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; @@ -688,7 +742,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); @@ -697,12 +756,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; @@ -710,9 +772,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; @@ -731,6 +816,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); @@ -860,7 +950,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; @@ -881,6 +972,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; @@ -913,16 +1010,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); } @@ -930,7 +1027,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); @@ -938,15 +1036,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; } @@ -982,8 +1073,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: @@ -1162,11 +1263,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 */ @@ -1174,6 +1281,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 */ @@ -1207,6 +1320,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) @@ -1315,10 +1436,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, @@ -1448,6 +1590,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 8d062c58d5cb..81c26864abeb 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -552,6 +552,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 Mon Sep 25 03:29:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 818040 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="0S6MdoT3"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y0qNX2gDfz9t4B for ; Mon, 25 Sep 2017 13:30:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933120AbdIYDae (ORCPT ); Sun, 24 Sep 2017 23:30:34 -0400 Received: from mail-pf0-f176.google.com ([209.85.192.176]:47512 "EHLO mail-pf0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933044AbdIYDa1 (ORCPT ); Sun, 24 Sep 2017 23:30:27 -0400 Received: by mail-pf0-f176.google.com with SMTP id u12so3144514pfl.4 for ; Sun, 24 Sep 2017 20:30: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=SIIbcZrGbo9vQ9tcpBRscAQ3X42DLFB/thBEL5E/EhY=; b=0S6MdoT39pRfoRgR1uO9yEd9eN2iX8jny9UsFx90Cjxy156NpHwXf5mwVa342tVG5M pJ2ls55DNjjHnbL95PILoEe8y4TXvLgsT83cwwRU4tDvhofPGlZsnZOUeI/5d4OY0hIA Jye36m5RBUBYizXbTvKr/SXXVunoXWU6GfXlIO3E1rGVCW5Q57fmw61pJKkLifg8Vvpl gDcdGrM6X//KsaT+UnzvULKj9tQQqK/h0rhs5apPgCllEeEGLpMsv1l9bIaLwA9aBe2Z QjnLG5XO6atINkkCJxhNeCJyPD+URN0w9F9Xca0a+xbq0o3eboLxW3EPARty4nQ1orGB bfxw== 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=SIIbcZrGbo9vQ9tcpBRscAQ3X42DLFB/thBEL5E/EhY=; b=maWgktbZSSqJiZ1eaOsh2Rgrh5MFzAozUZoTFt5Yefz1+4dfIoOyWHwbH5H4FOxx7R gdROEl+r3V46Ku+O9ClKEDzhxih7eePBjv+eUCZWpy1QkkeH+rR/3XeZ5l8GTDDg72hu h5zN7kGBVJEuxjVYSmViifAvuieSLzTH1vk1ut4km+3LxfqZ58UEl3xXMLKKsGOwiIvU P/DbOjKEy3964cryf1ly8BC1TI4VyhoIejzsnkBULWwTDB7J9lnYtQisdCJWT15xIQVa x4oo3ehRHgO9NNL4Ti/er9hUEMfFztZQjgRde2nBpihf8ij8zSrs/cQIRFm5ZMBhLoh/ +0Yg== X-Gm-Message-State: AHPjjUi6015QVVTnP0bdRhGZ2DiPHb1h2GeR/jURDlLsi89SHwZC6VIW hpQcFfovXFIjUL2A9mxoR04OWg== X-Google-Smtp-Source: AOwi7QB1Wi9d78DmUIY+rLhLDFmAqAzIQeyI3xxpPUTJtWrRHAj3hvpbLLVu1Y73z10W8FwVP+LKJg== X-Received: by 10.101.66.70 with SMTP id d6mr6219152pgq.169.1506310226816; Sun, 24 Sep 2017 20:30: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 j2sm9112907pgn.26.2017.09.24.20.30.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Sep 2017 20:30: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 v3 net-next 12/12] gtp: Allow configuring GTP interface as standalone Date: Sun, 24 Sep 2017 20:29:41 -0700 Message-Id: <20170925032941.14586-13-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170925032941.14586-1-tom@quantonium.net> References: <20170925032941.14586-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 | 215 ++++++++++++++++++++++++++++++++++++----------- include/uapi/linux/gtp.h | 5 ++ 2 files changed, 169 insertions(+), 51 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 1c580df4cfc5..dc1fcd3034af 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,26 +454,33 @@ 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) { - struct gtp_dev *gtp = netdev_priv(dev); - - gtp->dev = dev; - dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) return -ENOMEM; @@ -482,7 +492,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); } @@ -751,6 +762,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); } @@ -764,13 +777,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]); @@ -831,7 +850,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; } @@ -840,7 +859,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); @@ -851,6 +870,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[], @@ -949,11 +970,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; @@ -986,60 +1031,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; + } + + if (sock0) { + gtp->sock0 = sock0; + gtp->sk0 = sock0->sk; + } else { + gtp->sk0 = sk0; } - gtp->sk0 = sk0; - gtp->sk1u = sk1u; + 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[]) @@ -1624,8 +1737,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,