From patchwork Fri Dec 11 12:26:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonas Bonn X-Patchwork-Id: 342607 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D9BD7C2BB40 for ; Fri, 11 Dec 2020 12:28:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BD9A223EB3 for ; Fri, 11 Dec 2020 12:28:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405925AbgLKM1w (ORCPT ); Fri, 11 Dec 2020 07:27:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54020 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2405452AbgLKM1i (ORCPT ); Fri, 11 Dec 2020 07:27:38 -0500 Received: from mail-lf1-x142.google.com (mail-lf1-x142.google.com [IPv6:2a00:1450:4864:20::142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 870DFC06179C for ; Fri, 11 Dec 2020 04:26:20 -0800 (PST) Received: by mail-lf1-x142.google.com with SMTP id h19so13024831lfc.12 for ; Fri, 11 Dec 2020 04:26:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=norrbonn-se.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=u+zB4aisBlYMRxDkDUv0BdgHZ/QQl8spoPtF5xMzNTQ=; b=s74/kpkqpRYIOuTw1+yWS+F3OaDRn/04LLTjGHo/46LVCKqL0ek5NET9q96m6gLDM2 6AQqdnjCZETRhtPl+LmQzSvVHqrduERFZoqnznoR8NAafZBq/BurgfWuPMCRV8+9odjO m7QWbVg+2mTTOgTI2uXzSSfztbHQHmZn6TLTfZPOEvXtdBCdCkGvlD6glqKiCb27Qvb9 MzVcdvRfYvjk/JXA2LeU0lCNK47VKmrRg0dY+kEegGMAG/xk5H3HtM1E0uWg4t7OPnMQ bK/rb8H/+wU+fuTANx5bBXzdy3RJfy68oDe+TM1vtHMxKmE9kj0Z19P9yjB4zmUJliFY 9jbg== 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:mime-version:content-transfer-encoding; bh=u+zB4aisBlYMRxDkDUv0BdgHZ/QQl8spoPtF5xMzNTQ=; b=oypdX0YZIxoXv9y28pArEz0kg+t7ljYPzhJ4uQde3bNKY/Ufj15U0Gokn1a5eqlD9r lVRRCs/3uGbj3qdsCOxiO7lW0F6+NQWuefylGdFUgavWlNXh4rvDVYZffeLJLabFMBoZ 8ZFuWuPh6eLXYERdt5SuFD1GTJZDA/ngt0RIJmrqtUglKg959EQuOyWsb1wtTMpQLdsS MwrFzHv5DP/1BWUVmwTbs4/Cq7RhHzypNyNACJ5FUkhafQfuhtLf+cyu/N7DDUAvV2sh N+csLYnmIhSGYNu9gKtRvDL71NKEmZbmY2MgrAaZvEZ4KRdnorqiRfvMHg1aGsXTpjhm OvSg== X-Gm-Message-State: AOAM531yGRmbygq3X8yKNl0OMhqAfTrkprS86tSt9MOQWAFkkjsE3Ylm cJ9gYaB1VI1Wt1IC5MhN4ADbx0XSLSITtg== X-Google-Smtp-Source: ABdhPJwQtpBtzvnpFjXft3O19GhThHsmHVHfbl7zvGmuPSdTWvQtPn6nBOOwY/BqsVuJDl7PN63Hdw== X-Received: by 2002:a19:f101:: with SMTP id p1mr2365670lfh.54.1607689578967; Fri, 11 Dec 2020 04:26:18 -0800 (PST) Received: from mimer.emblasoft.lan (h-137-65.A159.priv.bahnhof.se. [81.170.137.65]) by smtp.gmail.com with ESMTPSA id s8sm335818lfi.21.2020.12.11.04.26.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Dec 2020 04:26:18 -0800 (PST) From: Jonas Bonn To: netdev@vger.kernel.org Cc: pablo@netfilter.org, laforge@gnumonks.org, Jonas Bonn Subject: [PATCH net-next v2 05/12] gtp: set device type Date: Fri, 11 Dec 2020 13:26:05 +0100 Message-Id: <20201211122612.869225-6-jonas@norrbonn.se> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201211122612.869225-1-jonas@norrbonn.se> References: <20201211122612.869225-1-jonas@norrbonn.se> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Set the devtype to 'gtp' when setting up the link. Signed-off-by: Jonas Bonn Acked-by: Harald Welte --- drivers/net/gtp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 04d9de385549..a1bb02818977 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -610,6 +610,10 @@ static const struct net_device_ops gtp_netdev_ops = { .ndo_get_stats64 = dev_get_tstats64, }; +static const struct device_type gtp_type = { + .name = "gtp", +}; + static void gtp_link_setup(struct net_device *dev) { unsigned int max_gtp_header_len = sizeof(struct iphdr) + @@ -618,6 +622,7 @@ static void gtp_link_setup(struct net_device *dev) dev->netdev_ops = >p_netdev_ops; dev->needs_free_netdev = true; + SET_NETDEV_DEVTYPE(dev, >p_type); dev->hard_header_len = 0; dev->addr_len = 0; From patchwork Fri Dec 11 12:26:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonas Bonn X-Patchwork-Id: 342609 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CAC7DC1B0D8 for ; Fri, 11 Dec 2020 12:28:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9FA9623F28 for ; Fri, 11 Dec 2020 12:28:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405929AbgLKM1x (ORCPT ); Fri, 11 Dec 2020 07:27:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54022 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2405451AbgLKM1i (ORCPT ); Fri, 11 Dec 2020 07:27:38 -0500 Received: from mail-lf1-x143.google.com (mail-lf1-x143.google.com [IPv6:2a00:1450:4864:20::143]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7A109C0617A6 for ; Fri, 11 Dec 2020 04:26:21 -0800 (PST) Received: by mail-lf1-x143.google.com with SMTP id a12so13065701lfl.6 for ; Fri, 11 Dec 2020 04:26:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=norrbonn-se.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=J2qbl8+PQmeLyZfcgsn0UGIJs64aBXhfNs1G+gzOFeE=; b=GT30ZDQUXTm6AgOvtLafVa+12Pm0Mk5ihvh++zIqDa+1qort8nK8G0jJjda5uq2wq1 j7NTSZQ+Echrv6LNGiB8GuX3zw9V+BLFH9UFNCxGxQPW3vV2srz8AS5M+88tInuAUEqy Bzv0GI2p57WDP52HQkQTkq+9wtJ87Dwc7Nz1J3TP8pK+qAUApJ6RiGIiD5ByLX0Anfrs h8jqhaTNwaTHLLasAMnIXAa0ozhMRDTq1hOwXBZW/P7OuzbxqGty7n5P67hXxbD7F6gt seiyniJd2RJ8OBmv9nep2kKIdFnw6+S5nu2d2OQnXAQ17r6gidMI5QLeHwcriWNvWBmJ 4Gug== 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:mime-version:content-transfer-encoding; bh=J2qbl8+PQmeLyZfcgsn0UGIJs64aBXhfNs1G+gzOFeE=; b=uWv8gtCcl433ZeqPm4XuxwZb02jdFgvZY/LNM6KfAQxENHNKc0o7rcwz+ESg1kWERV gz1Ln3iyCmTW5IxnHFFCEhYQw14I198ZpZOi6Y8r8dq7P9cPmndKF0WgQVXl5nJljstT LQkAFWSBAyoLYWzpdfYmTjwhyAv4LlOXYhddHy3V2PJl8LBj67VOcK6Rhv/CDqI7dvnM Pnfyzrw7vyIvtSt1R8KnhfpDyuGyFD2PjMAof/6KyAomHmT94qX8lsZ967gDcV8JrCuH YUOgRs2jHc7PszNO1ZInP0i46xo6e3BWqmT+sayl/vu2k4V4d1O/NFyAO45Sn4XO+LuJ ROsg== X-Gm-Message-State: AOAM533SngTfVzD7xTgZLwL76F6uJ+cEcDuZKvPzLeyvGbN3EF5i1yrI KRvE2phXEoPN8jdnpzTKu+gCI+VPrHR5IA== X-Google-Smtp-Source: ABdhPJztF0eHgvjzMT/9s3bmTnfbsUOQG9mTd32xeu2BL9RpQSiMqhX7Ds0wlkMh8tAoDPpP3gvvUA== X-Received: by 2002:a19:418d:: with SMTP id o135mr4299776lfa.329.1607689579748; Fri, 11 Dec 2020 04:26:19 -0800 (PST) Received: from mimer.emblasoft.lan (h-137-65.A159.priv.bahnhof.se. [81.170.137.65]) by smtp.gmail.com with ESMTPSA id s8sm335818lfi.21.2020.12.11.04.26.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Dec 2020 04:26:19 -0800 (PST) From: Jonas Bonn To: netdev@vger.kernel.org Cc: pablo@netfilter.org, laforge@gnumonks.org, Jonas Bonn Subject: [PATCH net-next v2 06/12] gtp: rework IPv4 functionality Date: Fri, 11 Dec 2020 13:26:06 +0100 Message-Id: <20201211122612.869225-7-jonas@norrbonn.se> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201211122612.869225-1-jonas@norrbonn.se> References: <20201211122612.869225-1-jonas@norrbonn.se> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch does some cleanup work in the IPv4 functionality to lay the groundwork for adding support for IPv6. The form of these changes is largely borrowed from the bareudp and geneve drivers, so there shouldn't be anything here that looks unnecessarily unfamiliar. Signed-off-by: Jonas Bonn --- drivers/net/gtp.c | 204 +++++++++++++++++++++------------------------- 1 file changed, 92 insertions(+), 112 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index a1bb02818977..4a3a52970856 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -381,18 +382,36 @@ 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) +static struct rtable *gtp_get_v4_rt(struct sk_buff *skb, + struct net_device *dev, + struct pdp_ctx *pctx, + __be32 *saddr) { - 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); + const struct sock *sk = pctx->sk; + struct rtable *rt = NULL; + struct flowi4 fl4; + + memset(&fl4, 0, sizeof(fl4)); + fl4.flowi4_oif = sk->sk_bound_dev_if; + fl4.daddr = pctx->peer_addr_ip4.s_addr; + fl4.saddr = inet_sk(sk)->inet_saddr; + fl4.flowi4_tos = RT_CONN_FLAGS(sk); + fl4.flowi4_proto = sk->sk_protocol; + + rt = ip_route_output_key(sock_net(sk), &fl4); + if (IS_ERR(rt)) { + netdev_dbg(pctx->dev, "no route to %pI4\n", &fl4.daddr); + return ERR_PTR(-ENETUNREACH); + } + if (rt->dst.dev == dev) { + netdev_dbg(pctx->dev, "circular route to %pI4\n", &fl4.daddr); + ip_rt_put(rt); + return ERR_PTR(-ELOOP); + } + + *saddr = fl4.saddr; + + return rt; } static inline void gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) @@ -435,54 +454,31 @@ 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, + __be16 *port) { - switch (pktinfo->pctx->gtp_version) { + switch (pctx->gtp_version) { case GTP_V0: - pktinfo->gtph_port = htons(GTP0_PORT); - gtp0_push_header(skb, pktinfo->pctx); + *port = htons(GTP0_PORT); + gtp0_push_header(skb, pctx); break; case GTP_V1: - pktinfo->gtph_port = htons(GTP1U_PORT); - gtp1_push_header(skb, pktinfo->pctx); + *port = htons(GTP1U_PORT); + 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_ip4(struct sk_buff *skb, struct net_device *dev) { struct gtp_dev *gtp = netdev_priv(dev); struct pdp_ctx *pctx; struct rtable *rt; - struct flowi4 fl4; + __be32 saddr; struct iphdr *iph; - __be16 df; - int mtu; + int headroom; + __be16 port; + int r; /* Read the IP destination address and resolve the PDP context. * Prepend PDP header with TEI/TID from PDP ctx. @@ -500,102 +496,86 @@ 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); + rt = gtp_get_v4_rt(skb, dev, pctx, &saddr); 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; + if (PTR_ERR(rt) == -ENETUNREACH) + dev->stats.tx_carrier_errors++; + else if (PTR_ERR(rt) == -ELOOP) + dev->stats.collisions++; + return PTR_ERR(rt); } - 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; - } + headroom = sizeof(struct iphdr) + sizeof(struct udphdr); - /* 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); + switch (pctx->gtp_version) { + case GTP_V0: + headroom += sizeof(struct gtp0_header); + break; + case GTP_V1: + headroom += sizeof(struct gtp1_header); + break; } - rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu, false); + r = skb_tunnel_check_pmtu(skb, &rt->dst, headroom, + netif_is_any_bridge_port(dev)); + if (r < 0) { + ip_rt_put(rt); + return r; + } else if (r) { + netif_rx(skb); + ip_rt_put(rt); + return -EMSGSIZE; + } - 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_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); + /* Ensure there is sufficient headroom. */ + r = skb_cow_head(skb, headroom); + if (unlikely(r)) goto err_rt; - } - gtp_set_pktinfo_ipv4(pktinfo, pctx->sk, iph, pctx, rt, &fl4, dev); - gtp_push_header(skb, pktinfo); + skb_reset_inner_headers(skb); + + gtp_push_header(skb, pctx, &port); + + iph = ip_hdr(skb); + netdev_dbg(dev, "gtp -> IP src: %pI4 dst: %pI4\n", + &iph->saddr, &iph->daddr); + + udp_tunnel_xmit_skb(rt, pctx->sk, skb, + saddr, pctx->peer_addr_ip4.s_addr, + iph->tos, + ip4_dst_hoplimit(&rt->dst), + 0, + port, port, + !net_eq(sock_net(pctx->sk), + dev_net(pctx->dev)), + false); return 0; err_rt: ip_rt_put(rt); -err: return -EBADMSG; } 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; int err; - /* Ensure there is sufficient headroom. */ - if (skb_cow_head(skb, dev->needed_headroom)) + if (proto != ETH_P_IP && proto != ETH_P_IPV6) { + err = -ENOTSUPP; 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); - break; - default: - err = -EOPNOTSUPP; - break; - } + + err = gtp_xmit_ip4(skb, dev); + rcu_read_unlock(); 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, - !net_eq(sock_net(pktinfo.pctx->sk), - dev_net(dev)), - false); - break; - } - return NETDEV_TX_OK; tx_err: dev->stats.tx_errors++; From patchwork Fri Dec 11 12:26:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonas Bonn X-Patchwork-Id: 342606 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7155DC433FE for ; Fri, 11 Dec 2020 12:28:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 36B9123E26 for ; Fri, 11 Dec 2020 12:28:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405902AbgLKM2h (ORCPT ); Fri, 11 Dec 2020 07:28:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54032 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2405460AbgLKM1k (ORCPT ); Fri, 11 Dec 2020 07:27:40 -0500 Received: from mail-lf1-x142.google.com (mail-lf1-x142.google.com [IPv6:2a00:1450:4864:20::142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 013DAC06138C for ; Fri, 11 Dec 2020 04:26:24 -0800 (PST) Received: by mail-lf1-x142.google.com with SMTP id 23so13059249lfg.10 for ; Fri, 11 Dec 2020 04:26:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=norrbonn-se.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pjyu2kzXzjFlV5SiNsnxkSgTKn4vgsNhKYRUSqrh5SM=; b=OSXgQ+OWQ22nsiZMDN4YIhCkRPR9Wjvxa2WaNhET5d7SBGq5dXkX6wLeyGmnvStUjE ycjaXbEmSP+8FndrvHQJpSLmo1ztwG2gaYH0QSvHf9GqUoqlGsO8UZepeMoPvTfb5f/8 SEybQpTVylVm0rfDSJz7mQH6PHOMGbGoeZfYRsshDMZlcFQ3yCUWv34cvheAGpbYCPz4 lWkLqtop8zYZVUXAPb0UqfSPV1rTDA2q6Jjv6og1+A+QeNhjgrz7ZyCpJi7xFBy+g7hx hkVvPSNgl/nQgdlGA2hs0ftuISFldVaVQXHTWqCCR9TjpU0GDR2Ma/IFo7CQfxKSc79O PHnQ== 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:mime-version:content-transfer-encoding; bh=pjyu2kzXzjFlV5SiNsnxkSgTKn4vgsNhKYRUSqrh5SM=; b=N9vD2JZMVd7Fdo9YMbJ6Wpr3U/CPfaps5i/wJxYwypFzIL5bd3BLTdwd+eZB3je0H1 L4nbrzowIeeDYShJQwx5cp3oXpjwUwmxvtESE0VEaSNj1FkF2rOifVTglmBdVGn2SM6X k++rni1O4UUh3yVAU7m/Gpb6+RLMVotvToTV6ovmXWB2t4OWt+s+QSQo2Q7cBUzQNAE2 z+LmS7r1Xeh0YYf373xTte8dB7mQBCre5FQij7IRWfikMDJWsXNJh75RzlvoalnoTvXV 1jFNTbEXMMARfVWe6tXrSBtNESvf3ZbF6wsow3VfPO7IQGh3ZV7fghAogT7a39GSUbBR LrMQ== X-Gm-Message-State: AOAM5339+TS+ngd0EgaupoD+cghriFEdIVyJvQaUYsYYRnaxIoADjyhM YS/rS64FiAISVdI29PRg0Qdteh0rmAhLZQ== X-Google-Smtp-Source: ABdhPJwMWWIyCltmSRx4cnTVud54k+XgIh3lVIFG9kMPTw8WxVTc2jvV/RRFDXalBU6YARfcxJi/UQ== X-Received: by 2002:ac2:48ad:: with SMTP id u13mr4333194lfg.416.1607689582295; Fri, 11 Dec 2020 04:26:22 -0800 (PST) Received: from mimer.emblasoft.lan (h-137-65.A159.priv.bahnhof.se. [81.170.137.65]) by smtp.gmail.com with ESMTPSA id s8sm335818lfi.21.2020.12.11.04.26.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Dec 2020 04:26:21 -0800 (PST) From: Jonas Bonn To: netdev@vger.kernel.org Cc: pablo@netfilter.org, laforge@gnumonks.org, Jonas Bonn Subject: [PATCH net-next v2 09/12] gtp: support GRO Date: Fri, 11 Dec 2020 13:26:09 +0100 Message-Id: <20201211122612.869225-10-jonas@norrbonn.se> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201211122612.869225-1-jonas@norrbonn.se> References: <20201211122612.869225-1-jonas@norrbonn.se> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch implements GRO callbacks for UDP-tunneled GTP traffic. iperf3 numbers Without GRO for GTP tunnels: Accepted connection from 172.99.2.1, port 48783 [ 5] local 172.99.0.1 port 5201 connected to 172.99.2.1 port 46095 [ ID] Interval Transfer Bitrate [ 5] 0.00-1.00 sec 563 MBytes 576306 KBytes/sec [ 5] 1.00-2.00 sec 681 MBytes 697814 KBytes/sec [ 5] 2.00-3.00 sec 677 MBytes 693612 KBytes/sec [ 5] 3.00-4.00 sec 679 MBytes 695690 KBytes/sec [ 5] 4.00-5.00 sec 683 MBytes 699521 KBytes/sec [ 5] 5.00-6.00 sec 682 MBytes 698922 KBytes/sec [ 5] 6.00-7.00 sec 683 MBytes 699820 KBytes/sec [ 5] 7.00-8.00 sec 682 MBytes 698052 KBytes/sec [ 5] 8.00-9.00 sec 683 MBytes 699245 KBytes/sec [ 5] 9.00-10.00 sec 683 MBytes 699554 KBytes/sec [ 5] 10.00-10.00 sec 616 KBytes 687914 KBytes/sec - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bitrate [ 5] 0.00-10.00 sec 6.54 GBytes 685853 KBytes/sec receiver With GRO for GTP tunnels: Accepted connection from 172.99.2.1, port 40847 [ 5] local 172.99.0.1 port 5201 connected to 172.99.2.1 port 55053 [ ID] Interval Transfer Bitrate [ 5] 0.00-1.00 sec 989 MBytes 1012640 KBytes/sec [ 5] 1.00-2.00 sec 1.23 GBytes 1291408 KBytes/sec [ 5] 2.00-3.00 sec 1.26 GBytes 1320197 KBytes/sec [ 5] 3.00-4.00 sec 1.29 GBytes 1350097 KBytes/sec [ 5] 4.00-5.00 sec 1.23 GBytes 1284512 KBytes/sec [ 5] 5.00-6.00 sec 1.26 GBytes 1326329 KBytes/sec [ 5] 6.00-7.00 sec 1.28 GBytes 1338620 KBytes/sec [ 5] 7.00-8.00 sec 1.28 GBytes 1346391 KBytes/sec [ 5] 8.00-9.00 sec 1.30 GBytes 1366394 KBytes/sec [ 5] 9.00-10.00 sec 1.26 GBytes 1323848 KBytes/sec [ 5] 10.00-10.00 sec 384 KBytes 1113043 KBytes/sec - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bitrate [ 5] 0.00-10.00 sec 12.4 GBytes 1296036 KBytes/sec receiver Signed-off-by: Jonas Bonn Reported-by: kernel test robot --- drivers/net/gtp.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 7bbeec173113..86639fae8d45 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -361,6 +361,128 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb) return ret; } +static int gtp_gro_complete(struct sock *sk, struct sk_buff * skb, int nhoff) +{ + size_t hdrlen; + char* gtphdr = skb->data + nhoff; + u8 version; + __be16 type; + struct packet_offload *ptype; + uint8_t ipver; + int err; + + version = *gtphdr >> 5; + switch (version) { + case GTP_V0: + hdrlen = sizeof(struct gtp0_header); + break; + case GTP_V1: + hdrlen = sizeof(struct gtp1_header); + if (*gtphdr & GTP1_F_MASK) + hdrlen += 4; + break; + } + + skb_set_inner_network_header(skb, nhoff + hdrlen); + + ipver = inner_ip_hdr(skb)->version; + switch (ipver) { + case 4: + type = cpu_to_be16(ETH_P_IP); + break; + case 6: + type = cpu_to_be16(ETH_P_IPV6); + break; + default: + goto out; + } + + rcu_read_lock(); + ptype = gro_find_complete_by_type(type); + if (!ptype) + goto out_unlock; + + err = ptype->callbacks.gro_complete(skb, nhoff + hdrlen); + + skb_set_inner_mac_header(skb, nhoff + hdrlen); + +out_unlock: + rcu_read_unlock(); +out: + + return err; + +} + +static struct sk_buff *gtp_gro_receive(struct sock *sk, + struct list_head *head, + struct sk_buff *skb) +{ + size_t off, hdrlen; + char* gtphdr; + u8 version; + struct sk_buff *pp = NULL; + __be16 type; + struct packet_offload *ptype; + + off = skb_gro_offset(skb); + + gtphdr = skb_gro_header_fast(skb, off); + if (skb_gro_header_hard(skb, off+1)) { + gtphdr = skb_gro_header_slow(skb, off+1, off); + if (unlikely(!gtphdr)) + goto out; + } + + version = *gtphdr >> 5; + switch (version) { + case GTP_V0: + hdrlen = sizeof(struct gtp0_header); + break; + case GTP_V1: + hdrlen = sizeof(struct gtp1_header); + if (*gtphdr & GTP1_F_MASK) + hdrlen += 4; + break; + } + + gtphdr = skb_gro_header_fast(skb, off); + if (skb_gro_header_hard(skb, off+hdrlen)) { + gtphdr = skb_gro_header_slow(skb, off+hdrlen, off); + if (unlikely(!gtphdr)) + goto out; + } + + skb_set_inner_network_header(skb, off + hdrlen); + + switch(inner_ip_hdr(skb)->version) { + case 4: + type = cpu_to_be16(ETH_P_IP); + break; + case 6: + type = cpu_to_be16(ETH_P_IPV6); + break; + default: + goto out; + } + + rcu_read_lock(); + ptype = gro_find_receive_by_type(type); + if (!ptype) + goto out_unlock; + + skb_gro_pull(skb, hdrlen); + skb_gro_postpull_rcsum(skb, gtphdr, hdrlen); + + pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + +out_unlock: + rcu_read_unlock(); +out: + + return pp; +} + static int gtp_dev_init(struct net_device *dev) { struct gtp_dev *gtp = netdev_priv(dev); @@ -622,7 +744,9 @@ static void gtp_link_setup(struct net_device *dev) dev->priv_flags |= IFF_NO_QUEUE; dev->features |= NETIF_F_LLTX; + dev->hw_features |= NETIF_F_RXCSUM; dev->hw_features |= NETIF_F_SG | NETIF_F_GSO_SOFTWARE | NETIF_F_HW_CSUM; + dev->features |= NETIF_F_RXCSUM; dev->features |= NETIF_F_SG | NETIF_F_GSO_SOFTWARE | NETIF_F_HW_CSUM; netif_keep_dst(dev); @@ -818,6 +942,8 @@ static struct sock *gtp_encap_enable_socket(int fd, int type, tuncfg.encap_type = type; tuncfg.encap_rcv = gtp_encap_recv; tuncfg.encap_destroy = gtp_encap_destroy; + tuncfg.gro_receive = gtp_gro_receive; + tuncfg.gro_complete = gtp_gro_complete; setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg); From patchwork Fri Dec 11 12:26:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonas Bonn X-Patchwork-Id: 342605 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D8453C4167B for ; Fri, 11 Dec 2020 12:29:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9F31E23EF2 for ; Fri, 11 Dec 2020 12:29:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405953AbgLKM3C (ORCPT ); Fri, 11 Dec 2020 07:29:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54034 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2405464AbgLKM1k (ORCPT ); Fri, 11 Dec 2020 07:27:40 -0500 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0CE7DC061282 for ; Fri, 11 Dec 2020 04:26:25 -0800 (PST) Received: by mail-lf1-x136.google.com with SMTP id a8so13082624lfb.3 for ; Fri, 11 Dec 2020 04:26:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=norrbonn-se.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=dM12+Q/bakrS1tkrkdKbft7ySXKZKzkcL4AuLlZcx7o=; b=svHECUKDhhbfHcRJ5ys5kJ8uINtvptz1g7jOX3D9gxJisvLRcUUwc14TgpTYTthorX dp4vz0EEFDfvp9xyOWupe4rWrwA4eQ2WVduNc3a8QFrVNtX1CQFuiq/4QRgOHVPzD1Jb D33P7HSz5n2IZdSfxVLXzJ6RUILvlss5p7qMgLVbYZ1G0Zj/RDfOFLW1uYRlKSgUvnLf n/9ljyuEixF8CPIgYEUU4DLEwUQug7A3uPY3ofccKG5qO4qmOnMlPXYZz0m8CqOh/vpO We5Q8IZO942B2LpN3wHPFVjVeuVaEX8o25Pc3+DkvnVjzWAatNEPeduBsi/nTgH8NTHI s6VA== 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:mime-version:content-transfer-encoding; bh=dM12+Q/bakrS1tkrkdKbft7ySXKZKzkcL4AuLlZcx7o=; b=ro1CmK/1iPNQwik4K5rPK2fdAzi38HVzoVVOX21iF8duV+6yffO8cTz6IA+w0MC+C1 eudKtMNZiuFOgb9kXOfeq2WY9e/832Up3zJXRAMXqSWXsvwSSPp/wV9+mxf8ptZJNaFe HQQxKZ1nmDjzSuGvTvkJyuvMcL5WelfCyBhyHGdflv4USgJFOn+LfS03aLEgZEyYbVXe MSFW6oy+nzQI6X+hEQDmSYhhZfxt60fm73q3GAzYO5ccbrs/Qt8pW2b/z5HUA2cSrjC6 RhI7jpady0QEz7PTSjWkTPAjTwf1weJTo3XFqsx8fUZug06A88WaxfePz+YKSnOSvzMU ZeNw== X-Gm-Message-State: AOAM530Vhsf6zgqSgVf6WVAPt85UBmEyT1kOiivKb7rb7l4OXqrtDKyP oHBd85qpbX3dzJHVhKdVSWTM5cGlQdJ1mw== X-Google-Smtp-Source: ABdhPJwXotUp6myNv1HC8YIfXNQp+h/St7VzGop3mK6xpyrpcswqT6m8EQyVKISrEpgfJ1opfyyD5A== X-Received: by 2002:ac2:48a5:: with SMTP id u5mr2319522lfg.97.1607689583051; Fri, 11 Dec 2020 04:26:23 -0800 (PST) Received: from mimer.emblasoft.lan (h-137-65.A159.priv.bahnhof.se. [81.170.137.65]) by smtp.gmail.com with ESMTPSA id s8sm335818lfi.21.2020.12.11.04.26.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Dec 2020 04:26:22 -0800 (PST) From: Jonas Bonn To: netdev@vger.kernel.org Cc: pablo@netfilter.org, laforge@gnumonks.org, Jonas Bonn Subject: [PATCH net-next v2 10/12] gtp: add IPv6 support Date: Fri, 11 Dec 2020 13:26:10 +0100 Message-Id: <20201211122612.869225-11-jonas@norrbonn.se> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201211122612.869225-1-jonas@norrbonn.se> References: <20201211122612.869225-1-jonas@norrbonn.se> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds support for handling IPv6. Both the GTP tunnel and the tunneled packets may be IPv6; as they constitute independent streams, both v4-over-v6 and v6-over-v4 are supported, as well. This patch includes only the driver functionality for IPv6 support. A follow-on patch will add support for configuring the tunnels with IPv6 addresses. Signed-off-by: Jonas Bonn --- drivers/net/gtp.c | 330 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 269 insertions(+), 61 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 86639fae8d45..4c902bffefa3 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -3,6 +3,7 @@ * * (C) 2012-2014 by sysmocom - s.f.m.c. GmbH * (C) 2016 by Pablo Neira Ayuso + * (C) 2020 by Jonas Bonn * * Author: Harald Welte * Pablo Neira Ayuso @@ -20,6 +21,7 @@ #include #include #include +#include #include #include @@ -33,6 +35,11 @@ #include #include +#define PDP_F_PEER_V6 (1 << 0) +#define PDP_F_MS_V6 (1 << 1) + +#define ipv4(in6addr) ((in6addr)->s6_addr32[3]) + /* An active session for the subscriber. */ struct pdp_ctx { struct hlist_node hlist_tid; @@ -49,10 +56,10 @@ struct pdp_ctx { } v1; } u; u8 gtp_version; - u16 af; + u16 flags; - struct in_addr ms_addr_ip4; - struct in_addr peer_addr_ip4; + struct in6_addr ms_addr; + struct in6_addr peer_addr; struct sock *sk; struct net_device *dev; @@ -97,9 +104,23 @@ static inline u32 gtp1u_hashfn(u32 tid) return jhash_1word(tid, gtp_h_initval); } +static inline u32 ip_hashfn(struct in6_addr *ip) +{ + return __ipv6_addr_jhash(ip, gtp_h_initval); +} + +static inline u32 ipv6_hashfn(struct in6_addr *ip) +{ + return ip_hashfn(ip); +} + static inline u32 ipv4_hashfn(__be32 ip) { - return jhash_1word((__force u32)ip, gtp_h_initval); + struct in6_addr addr; + + ipv6_addr_set_v4mapped(ip, &addr); + + return ipv6_hashfn(&addr); } /* Resolve a PDP context structure based on the 64bit TID. */ @@ -134,23 +155,42 @@ static struct pdp_ctx *gtp1_pdp_find(struct gtp_dev *gtp, u32 tid) return NULL; } -/* Resolve a PDP context based on IPv4 address of MS. */ -static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr) +static struct pdp_ctx *ip_pdp_find(struct gtp_dev *gtp, + struct in6_addr *ms_addr) { struct hlist_head *head; struct pdp_ctx *pdp; - head = >p->addr_hash[ipv4_hashfn(ms_addr) % gtp->hash_size]; + head = >p->addr_hash[ipv6_hashfn(ms_addr) % gtp->hash_size]; hlist_for_each_entry_rcu(pdp, head, hlist_addr) { - if (pdp->af == AF_INET && - pdp->ms_addr_ip4.s_addr == ms_addr) + if (ipv6_addr_equal(&pdp->ms_addr, ms_addr)) return pdp; } return NULL; } +/* Resolve a PDP context based on IPv6 address of MS. */ +static struct pdp_ctx *ipv6_pdp_find(struct gtp_dev *gtp, + struct in6_addr *ms_addr) +{ + return ip_pdp_find(gtp, ms_addr); +} + +/* 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 in6_addr addr; + + ipv6_addr_set_v4mapped(ms_addr, &addr); + + return ip_pdp_find(gtp, &addr); +} + +/* Check if the inner IP address in this packet is assigned to any + * existing mobile subscriber. + */ static bool gtp_check_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, unsigned int hdrlen, unsigned int role) { @@ -162,28 +202,51 @@ static bool gtp_check_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx, iph = (struct iphdr *)(skb->data + hdrlen); if (role == GTP_ROLE_SGSN) - return iph->daddr == pctx->ms_addr_ip4.s_addr; + return iph->daddr == ipv4(&pctx->ms_addr); else - return iph->saddr == pctx->ms_addr_ip4.s_addr; + return iph->saddr == ipv4(&pctx->ms_addr); } -/* 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) +static bool gtp_check_ms_ipv6(struct sk_buff *skb, struct pdp_ctx *pctx, + unsigned int hdrlen, unsigned int role) { - switch (ntohs(skb->protocol)) { - case ETH_P_IP: - return gtp_check_ms_ipv4(skb, pctx, hdrlen, role); - } - return false; + struct ipv6hdr *iph; + + if (!pskb_may_pull(skb, hdrlen + sizeof(struct ipv6hdr))) + return false; + + iph = (struct ipv6hdr *)(skb->data + hdrlen); + + if (role == GTP_ROLE_SGSN) + return ipv6_addr_equal(&iph->daddr, &pctx->ms_addr); + else + return ipv6_addr_equal(&iph->saddr, &pctx->ms_addr); } static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen, unsigned int role) { - if (!gtp_check_ms(skb, pctx, hdrlen, role)) { + uint8_t ipver; + int r; + + if (!pskb_may_pull(skb, hdrlen + 1)) + return false; + + /* Get IP version of _inner_ packet */ + ipver = inner_ip_hdr(skb)->version; + + switch (ipver) { + case 4: + skb_set_inner_protocol(skb, cpu_to_be16(ETH_P_IP)); + r = gtp_check_ms_ipv4(skb, pctx, hdrlen, role); + break; + case 6: + skb_set_inner_protocol(skb, cpu_to_be16(ETH_P_IPV6)); + r = gtp_check_ms_ipv6(skb, pctx, hdrlen, role); + break; + } + + if (!r) { netdev_dbg(pctx->dev, "No PDP ctx for this MS\n"); return 1; } @@ -193,6 +256,8 @@ static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, !net_eq(sock_net(pctx->sk), dev_net(pctx->dev)))) return -1; + skb->protocol = skb->inner_protocol; + netdev_dbg(pctx->dev, "forwarding packet from GGSN to uplink\n"); /* Now that the UDP and the GTP header have been removed, set up the @@ -201,7 +266,7 @@ static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, */ skb_reset_network_header(skb); - skb->dev = pctx->dev; + __skb_tunnel_rx(skb, pctx->dev, sock_net(pctx->sk)); dev_sw_netstats_rx_add(pctx->dev, skb->len); @@ -220,7 +285,9 @@ static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) if (!pskb_may_pull(skb, hdrlen)) return -1; - gtp0 = (struct gtp0_header *)(skb->data + sizeof(struct udphdr)); + skb_set_inner_network_header(skb, skb_transport_offset(skb) + hdrlen); + + gtp0 = (struct gtp0_header *)&udp_hdr(skb)[1]; if ((gtp0->flags >> 5) != GTP_V0) return 1; @@ -247,7 +314,9 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) if (!pskb_may_pull(skb, hdrlen)) return -1; - gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); + skb_set_inner_network_header(skb, skb_transport_offset(skb) + hdrlen); + + gtp1 = (struct gtp1_header *)&udp_hdr(skb)[1]; if ((gtp1->flags >> 5) != GTP_V1) return 1; @@ -264,12 +333,10 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) if (gtp1->flags & GTP1_F_MASK) hdrlen += 4; - /* Make sure the header is larger enough, including extensions. */ + /* Make sure the header is large enough, including extensions. */ if (!pskb_may_pull(skb, hdrlen)) return -1; - 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); @@ -515,7 +582,7 @@ static struct rtable *gtp_get_v4_rt(struct sk_buff *skb, memset(&fl4, 0, sizeof(fl4)); fl4.flowi4_oif = sk->sk_bound_dev_if; - fl4.daddr = pctx->peer_addr_ip4.s_addr; + fl4.daddr = ipv4(&pctx->peer_addr); fl4.saddr = inet_sk(sk)->inet_saddr; fl4.flowi4_tos = RT_CONN_FLAGS(sk); fl4.flowi4_proto = sk->sk_protocol; @@ -536,6 +603,36 @@ static struct rtable *gtp_get_v4_rt(struct sk_buff *skb, return rt; } +static struct dst_entry *gtp_get_v6_dst(struct sk_buff *skb, + struct net_device *dev, + struct pdp_ctx *pctx, + struct in6_addr *saddr) +{ + const struct sock *sk = pctx->sk; + struct dst_entry *dst = NULL; + struct flowi6 fl6; + + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_mark = skb->mark; + fl6.flowi6_proto = IPPROTO_UDP; + fl6.daddr = pctx->peer_addr; + + dst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(sk), sk, &fl6, NULL); + if (IS_ERR(dst)) { + netdev_dbg(pctx->dev, "no route to %pI6\n", &fl6.daddr); + return ERR_PTR(-ENETUNREACH); + } + if (dst->dev == pctx->dev) { + netdev_dbg(pctx->dev, "circular route to %pI6\n", &fl6.daddr); + dst_release(dst); + return ERR_PTR(-ELOOP); + } + + *saddr = fl6.saddr; + + return dst; +} + static inline void gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) { int payload_len = skb->len; @@ -591,10 +688,9 @@ static void gtp_push_header(struct sk_buff *skb, struct pdp_ctx *pctx, } } -static int gtp_xmit_ip4(struct sk_buff *skb, struct net_device *dev) +static int gtp_xmit_ip4(struct sk_buff *skb, struct net_device *dev, + struct pdp_ctx* pctx) { - struct gtp_dev *gtp = netdev_priv(dev); - struct pdp_ctx *pctx; struct rtable *rt; __be32 saddr; struct iphdr *iph; @@ -602,22 +698,6 @@ static int gtp_xmit_ip4(struct sk_buff *skb, struct net_device *dev) __be16 sport, port; int r; - /* 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 (!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); - rt = gtp_get_v4_rt(skb, dev, pctx, &saddr); if (IS_ERR(rt)) { if (PTR_ERR(rt) == -ENETUNREACH) @@ -671,7 +751,7 @@ static int gtp_xmit_ip4(struct sk_buff *skb, struct net_device *dev) &iph->saddr, &iph->daddr); udp_tunnel_xmit_skb(rt, pctx->sk, skb, - saddr, pctx->peer_addr_ip4.s_addr, + saddr, ipv4(&pctx->peer_addr), iph->tos, ip4_dst_hoplimit(&rt->dst), 0, @@ -686,9 +766,130 @@ static int gtp_xmit_ip4(struct sk_buff *skb, struct net_device *dev) return -EBADMSG; } +static int gtp_xmit_ip6(struct sk_buff *skb, struct net_device *dev, + struct pdp_ctx* pctx) +{ + struct dst_entry *dst; + struct in6_addr saddr; + struct ipv6hdr *iph; + int headroom; + __be16 sport, port; + int r; + + dst = gtp_get_v6_dst(skb, dev, pctx, &saddr); + if (IS_ERR(dst)) { + if (PTR_ERR(dst) == -ENETUNREACH) + dev->stats.tx_carrier_errors++; + else if (PTR_ERR(dst) == -ELOOP) + dev->stats.collisions++; + return PTR_ERR(dst); + } + + headroom = sizeof(struct ipv6hdr) + sizeof(struct udphdr); + + switch (pctx->gtp_version) { + case GTP_V0: + headroom += sizeof(struct gtp0_header); + break; + case GTP_V1: + headroom += sizeof(struct gtp1_header); + break; + } + + sport = udp_flow_src_port(sock_net(pctx->sk), skb, + 0, USHRT_MAX, + true); + + r = skb_tunnel_check_pmtu(skb, dst, headroom, + netif_is_any_bridge_port(dev)); + if (r < 0) { + dst_release(dst); + return r; + } else if (r) { + netif_rx(skb); + dst_release(dst); + return -EMSGSIZE; + } + + skb_scrub_packet(skb, !net_eq(sock_net(pctx->sk), dev_net(pctx->dev))); + + /* Ensure there is sufficient headroom. */ + r = skb_cow_head(skb, dev->needed_headroom); + if (unlikely(r)) + goto free_dst; + + r = udp_tunnel_handle_offloads(skb, true); + if (unlikely(r)) + goto free_dst; + + skb_set_inner_protocol(skb, skb->protocol); + + gtp_push_header(skb, pctx, &port); + + iph = ipv6_hdr(skb); + netdev_dbg(dev, "gtp -> IP src: %pI6 dst: %pI6\n", + &iph->saddr, &iph->daddr); + + udp_tunnel6_xmit_skb(dst, pctx->sk, skb, + skb->dev, + &saddr, &pctx->peer_addr, + 0, + ip6_dst_hoplimit(dst), + 0, + sport, port, + false); + + return 0; + +free_dst: + dst_release(dst); + return -EBADMSG; +} + +static struct pdp_ctx *pdp_find(struct sk_buff *skb, struct net_device *dev) +{ + struct gtp_dev *gtp = netdev_priv(dev); + unsigned int proto = ntohs(skb->protocol); + struct pdp_ctx* pctx = NULL; + + switch (proto) { + case ETH_P_IP: { + __be32 addr; + struct iphdr *iph = ip_hdr(skb); + addr = (gtp->role == GTP_ROLE_SGSN) ? iph->saddr : iph->daddr; + pctx = ipv4_pdp_find(gtp, addr); + + if (!pctx) { + netdev_dbg(dev, "no PDP ctx found for %pI4, skip\n", + &addr); + } + + break; + } + case ETH_P_IPV6: { + struct in6_addr* addr; + struct ipv6hdr *iph = ipv6_hdr(skb); + addr = (gtp->role == GTP_ROLE_SGSN) ? &iph->saddr : &iph->daddr; + pctx = ipv6_pdp_find(gtp, addr); + + if (!pctx) { + netdev_dbg(dev, "no PDP ctx found for %pI6, skip\n", + addr); + } + + break; + } + default: + break; + } + + return pctx; +} + static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned int proto = ntohs(skb->protocol); + struct pdp_ctx *pctx; int err; if (proto != ETH_P_IP && proto != ETH_P_IPV6) { @@ -699,7 +900,17 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) /* PDP context lookups in gtp_build_skb_*() need rcu read-side lock. */ rcu_read_lock(); - err = gtp_xmit_ip4(skb, dev); + pctx = pdp_find(skb, dev); + if (!pctx) { + err = -ENOENT; + rcu_read_unlock(); + goto tx_err; + } + + if (pctx->flags & PDP_F_PEER_V6) + err = gtp_xmit_ip6(skb, dev, pctx); + else + err = gtp_xmit_ip4(skb, dev, pctx); rcu_read_unlock(); @@ -726,7 +937,7 @@ static const struct device_type gtp_type = { static void gtp_link_setup(struct net_device *dev) { - unsigned int max_gtp_header_len = sizeof(struct iphdr) + + unsigned int max_gtp_header_len = sizeof(struct ipv6hdr) + sizeof(struct udphdr) + sizeof(struct gtp0_header); @@ -1023,11 +1234,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) { 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]); + ipv4(&pctx->peer_addr) = nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); + ipv4(&pctx->ms_addr) = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); switch (pctx->gtp_version) { case GTP_V0: @@ -1127,13 +1335,13 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, switch (pctx->gtp_version) { case GTP_V0: netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI4 ms=%pI4 (pdp=%p)\n", - pctx->u.v0.tid, &pctx->peer_addr_ip4, - &pctx->ms_addr_ip4, pctx); + pctx->u.v0.tid, &ipv4(&pctx->peer_addr), + &ipv4(&pctx->ms_addr), pctx); break; case GTP_V1: netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI4 ms=%pI4 (pdp=%p)\n", pctx->u.v1.i_tei, pctx->u.v1.o_tei, - &pctx->peer_addr_ip4, &pctx->ms_addr_ip4, pctx); + &ipv4(&pctx->peer_addr), &ipv4(&pctx->ms_addr), pctx); break; } @@ -1315,8 +1523,8 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) || nla_put_u32(skb, GTPA_LINK, pctx->dev->ifindex) || - 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, ipv4(&pctx->peer_addr)) || + nla_put_be32(skb, GTPA_MS_ADDRESS, ipv4(&pctx->ms_addr))) goto nla_put_failure; switch (pctx->gtp_version) { From patchwork Fri Dec 11 12:26:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonas Bonn X-Patchwork-Id: 342604 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 822C3C433FE for ; Fri, 11 Dec 2020 12:29:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4D52923EB3 for ; Fri, 11 Dec 2020 12:29:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405960AbgLKM3U (ORCPT ); Fri, 11 Dec 2020 07:29:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54040 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2405476AbgLKM1k (ORCPT ); Fri, 11 Dec 2020 07:27:40 -0500 Received: from mail-lf1-x144.google.com (mail-lf1-x144.google.com [IPv6:2a00:1450:4864:20::144]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85D55C061285 for ; Fri, 11 Dec 2020 04:26:25 -0800 (PST) Received: by mail-lf1-x144.google.com with SMTP id 23so13059354lfg.10 for ; Fri, 11 Dec 2020 04:26:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=norrbonn-se.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jVfvXqT12TyMn/Pwpg5bdVK94JN1/wHnqx5/oPgUWmg=; b=L2YBod+kUjkJENr40XjzVBovwZfjlgXd5oq+DLNldj2Tkjb/mN/76cep9sa+XjIYEm TIY72mE9NMzQxI66XL0nVyfG8bKBx0IqVhgOqB1EnOYWgDlDzyoTI5uZD/3FqNxuCciU Vt7LXuH7ddop7475GnVzJ0i3Qgh7E77h5JmghAFIcr6Hl+vb3ilMS//Pa8eqda2+lfxi IUEETl+JVtdGBXzeU/E72wmeRqmrIacPMwTuMDRNLWthcxk40bfL769AgN2Fc6WmvXql pIdm1L4RrGqdSaXI5+fPQb0HltHCX7CdORMqYPpmCttnGKsBoXRLgtsr/BZa/3KePBpm Oobw== 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:mime-version:content-transfer-encoding; bh=jVfvXqT12TyMn/Pwpg5bdVK94JN1/wHnqx5/oPgUWmg=; b=Lq5Bq461Mrht3Don8AvduAAKeP7EuheAFDBTWLsk5WyQ7GAb8mS5CqZqb7FbiniFYD +RwLPxYEJ4y5bHM+LFqGPanwkjE0ooBia6hNAdAI0ilcIpcRMfBU1Raq5zW3t1I3IBFP cJReSIXYl4pSHaRGwEL3Z9fv/OMmoR3dC60c8dqteT5j3Sp0Ki+me/f8dlel9fB638JO sjAAoMW18twPoOlYa9ARlpSKkeJpOfZ41yBynTM7jQd7zW5hSLav+dEpat/JxHFfvu6p 2EyGENNRq4qG+0sRpG5zdfLdv3KFkh3ovCBN+rEXLu++ad5Lqk0z9r5Gp1jiR7O4dQ/b Xbzw== X-Gm-Message-State: AOAM530ktadDGwkjHYNhuHNWKarARCkoKX5Ro+GCjDWWZcy80N+HlXhN eLHcB0IAq6LFW03I1uKEvoYA3oKlqpjgZw== X-Google-Smtp-Source: ABdhPJwJLE2eNZlah/1nlYfg9uHjBCC4O5rde+NYVmwXvaj603Co81vljXvZTyDs1YPTIt0dZXxPbw== X-Received: by 2002:ac2:41da:: with SMTP id d26mr4632916lfi.15.1607689583818; Fri, 11 Dec 2020 04:26:23 -0800 (PST) Received: from mimer.emblasoft.lan (h-137-65.A159.priv.bahnhof.se. [81.170.137.65]) by smtp.gmail.com with ESMTPSA id s8sm335818lfi.21.2020.12.11.04.26.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Dec 2020 04:26:23 -0800 (PST) From: Jonas Bonn To: netdev@vger.kernel.org Cc: pablo@netfilter.org, laforge@gnumonks.org, Jonas Bonn Subject: [PATCH net-next v2 11/12] gtp: netlink update for ipv6 Date: Fri, 11 Dec 2020 13:26:11 +0100 Message-Id: <20201211122612.869225-12-jonas@norrbonn.se> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201211122612.869225-1-jonas@norrbonn.se> References: <20201211122612.869225-1-jonas@norrbonn.se> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds the netlink changes required to support IPv6. Signed-off-by: Jonas Bonn --- drivers/net/gtp.c | 84 ++++++++++++++++++++++++++++++---------- include/uapi/linux/gtp.h | 2 + 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 4c902bffefa3..40bbbe8cfad6 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1231,11 +1231,26 @@ 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) { pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); - ipv4(&pctx->peer_addr) = nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); - ipv4(&pctx->ms_addr) = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); + pctx->flags = 0; + + if (info->attrs[GTPA_PEER_IPV6]) { + pctx->flags |= PDP_F_PEER_V6; + pctx->peer_addr = nla_get_in6_addr(info->attrs[GTPA_PEER_IPV6]); + } else + ipv6_addr_set_v4mapped( + nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]), + &pctx->peer_addr); + + if (info->attrs[GTPA_MS_IPV6]) { + pctx->flags |= PDP_F_MS_V6; + pctx->ms_addr = nla_get_in6_addr(info->attrs[GTPA_MS_IPV6]); + } else + ipv6_addr_set_v4mapped( + nla_get_be32(info->attrs[GTPA_MS_ADDRESS]), + &pctx->ms_addr); switch (pctx->gtp_version) { case GTP_V0: @@ -1263,13 +1278,20 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, u32 hash_ms, hash_tid = 0; unsigned int version; bool found = false; - __be32 ms_addr; - ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); - hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size; + if (info->attrs[GTPA_MS_IPV6]) { + struct in6_addr ms_addr_v6; + ms_addr_v6 = nla_get_in6_addr(info->attrs[GTPA_MS_IPV6]); + hash_ms = ipv6_hashfn(&ms_addr_v6) % gtp->hash_size; + pctx = ipv6_pdp_find(gtp, &ms_addr_v6); + } else { + __be32 ms_addr; + ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); + hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size; + pctx = ipv4_pdp_find(gtp, ms_addr); + } version = nla_get_u32(info->attrs[GTPA_VERSION]); - pctx = ipv4_pdp_find(gtp, ms_addr); if (pctx) found = true; if (version == GTP_V0) @@ -1292,7 +1314,7 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, if (!pctx) pctx = pctx_tid; - 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", @@ -1312,7 +1334,7 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, sock_hold(sk); pctx->sk = sk; pctx->dev = gtp->dev; - ipv4_pdp_fill(pctx, info); + pdp_fill(pctx, info); atomic_set(&pctx->tx_seq, 0); switch (pctx->gtp_version) { @@ -1334,14 +1356,14 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, switch (pctx->gtp_version) { case GTP_V0: - netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI4 ms=%pI4 (pdp=%p)\n", - pctx->u.v0.tid, &ipv4(&pctx->peer_addr), - &ipv4(&pctx->ms_addr), pctx); + netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI6 ms=%pI6 (pdp=%p)\n", + pctx->u.v0.tid, &pctx->peer_addr, + &pctx->ms_addr, pctx); break; case GTP_V1: - netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI4 ms=%pI4 (pdp=%p)\n", + netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI6 ms=%pI6 (pdp=%p)\n", pctx->u.v1.i_tei, pctx->u.v1.o_tei, - &ipv4(&pctx->peer_addr), &ipv4(&pctx->ms_addr), pctx); + &pctx->peer_addr, &pctx->ms_addr, pctx); break; } @@ -1374,9 +1396,13 @@ 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]) + return -EINVAL; + + if (!info->attrs[GTPA_PEER_ADDRESS] == !info->attrs[GTPA_PEER_IPV6]) + return -EINVAL; + + if (!info->attrs[GTPA_MS_ADDRESS] == !info->attrs[GTPA_MS_IPV6]) return -EINVAL; version = nla_get_u32(info->attrs[GTPA_VERSION]); @@ -1439,7 +1465,11 @@ static struct pdp_ctx *gtp_find_pdp_by_link(struct net *net, if (!gtp) return ERR_PTR(-ENODEV); - if (nla[GTPA_MS_ADDRESS]) { + if (nla[GTPA_MS_IPV6]) { + struct in6_addr ip = nla_get_in6_addr(nla[GTPA_MS_IPV6]); + + return ipv6_pdp_find(gtp, &ip); + } else if (nla[GTPA_MS_ADDRESS]) { __be32 ip = nla_get_be32(nla[GTPA_MS_ADDRESS]); return ipv4_pdp_find(gtp, ip); @@ -1522,9 +1552,19 @@ 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_u32(skb, GTPA_LINK, pctx->dev->ifindex) || - nla_put_be32(skb, GTPA_PEER_ADDRESS, ipv4(&pctx->peer_addr)) || - nla_put_be32(skb, GTPA_MS_ADDRESS, ipv4(&pctx->ms_addr))) + nla_put_u32(skb, GTPA_LINK, pctx->dev->ifindex)) + goto nla_put_failure; + + if ((pctx->flags & PDP_F_PEER_V6) && + nla_put_in6_addr(skb, GTPA_PEER_IPV6, &pctx->peer_addr)) + goto nla_put_failure; + else if (nla_put_be32(skb, GTPA_PEER_ADDRESS, ipv4(&pctx->peer_addr))) + goto nla_put_failure; + + if ((pctx->flags & PDP_F_MS_V6) && + nla_put_in6_addr(skb, GTPA_MS_IPV6, &pctx->ms_addr)) + goto nla_put_failure; + else if (nla_put_be32(skb, GTPA_MS_ADDRESS, ipv4(&pctx->ms_addr))) goto nla_put_failure; switch (pctx->gtp_version) { @@ -1660,6 +1700,8 @@ static const 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, }, + [GTPA_PEER_IPV6] = { .len = sizeof(struct in6_addr), }, + [GTPA_MS_IPV6] = { .len = sizeof(struct in6_addr), }, [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 79f9191bbb24..5fe0ca6a917e 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -30,6 +30,8 @@ enum gtp_attrs { GTPA_I_TEI, /* for GTPv1 only */ GTPA_O_TEI, /* for GTPv1 only */ GTPA_PAD, + GTPA_PEER_IPV6, + GTPA_MS_IPV6, __GTPA_MAX, }; #define GTPA_MAX (__GTPA_MAX + 1) From patchwork Fri Dec 11 12:26:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonas Bonn X-Patchwork-Id: 342608 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3BCBC4167B for ; Fri, 11 Dec 2020 12:28:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8548323EB3 for ; Fri, 11 Dec 2020 12:28:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405933AbgLKM1x (ORCPT ); Fri, 11 Dec 2020 07:27:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54042 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2405899AbgLKM1k (ORCPT ); Fri, 11 Dec 2020 07:27:40 -0500 Received: from mail-lf1-x144.google.com (mail-lf1-x144.google.com [IPv6:2a00:1450:4864:20::144]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3EAE6C061248 for ; Fri, 11 Dec 2020 04:26:26 -0800 (PST) Received: by mail-lf1-x144.google.com with SMTP id a12so13065993lfl.6 for ; Fri, 11 Dec 2020 04:26:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=norrbonn-se.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=P3S4hFr4sUY3q9oJIspkv2JQh9Jprg+/KchwSNWk44w=; b=MBQgcXdxOWCH2B4vDU0nx25MIWrkYAOLyVL8t1eC1cRxA14QK0jHUT1wh/YTVz9Q1M 3o15MNEFKlOQlfc1gJ/B6Q7GMyJccGxW6Ci2Z83Yk/iiyTYDW6lNrT5F9YIJEJTZfWrF T4KL22Sc29xqdnm5RGJcT8Lkhylxhoaf14V1yJ+9fjZttvFBFbAmaTpoIQpEwyl5r2Pw A/7k44mouXEaA3IVxxeVZJP5uFJbjxgIx8VfgrzaYANjqb9N7z1dbLt/Y/rYDsRAEnJ5 YBAZnJ6sy6yoCy2yHES1O7uAEIZa1je8e/qdJDnJPhGVJfp8/yrunxw2Iew9sXflpFCx hvyw== 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:mime-version:content-transfer-encoding; bh=P3S4hFr4sUY3q9oJIspkv2JQh9Jprg+/KchwSNWk44w=; b=n5iW+TGaJxd+XthA5STuLzdmrIEmjzCfaODK8Cvc3vjsLm4eB4bha0RMK57z0Ac6vN 3KcY01lRD+wkKptjoUmXWixAvkQsMu1dFMC1iEqyWJoxP6v4PQHxuMPONfAb4eXczPpC mzXY8+fJQGrwtcwQlO3RK0EUfPG7nZOMu5aLHgl9nnqdwMoUoRtj+Gc+dXuSeHnScqHJ kNkrpy7vpndssrxvXGeAQRXLGuwxbCzOl1gj5j65t6FASAJnqAZgO+BvkZ91fbBhvtGK cVP4V3TAfDW8SBmQj29N9FX2JGydrmbEyBQ5tALIMtDti7epvK/V3we3TmeF3QLQLP+G W1PA== X-Gm-Message-State: AOAM531M8/n6118WkXUvow+HL05/kv/TX6Ma7MMUM8sQCvvSP/j7HLpr zig3pXnbKMW6lJR4a2BGrUAASnTHWl5pmQ== X-Google-Smtp-Source: ABdhPJzPohI11G+HnJ/Twoe+TNrvdYtl8yb/GvwW/m3uRetacM+LsWbH8Ph11AByhqPvjLNrDski7A== X-Received: by 2002:ac2:59c6:: with SMTP id x6mr4749108lfn.82.1607689584591; Fri, 11 Dec 2020 04:26:24 -0800 (PST) Received: from mimer.emblasoft.lan (h-137-65.A159.priv.bahnhof.se. [81.170.137.65]) by smtp.gmail.com with ESMTPSA id s8sm335818lfi.21.2020.12.11.04.26.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Dec 2020 04:26:24 -0800 (PST) From: Jonas Bonn To: netdev@vger.kernel.org Cc: pablo@netfilter.org, laforge@gnumonks.org, Jonas Bonn Subject: [PATCH net-next v2 12/12] gtp: add dst_cache to tunnels Date: Fri, 11 Dec 2020 13:26:12 +0100 Message-Id: <20201211122612.869225-13-jonas@norrbonn.se> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201211122612.869225-1-jonas@norrbonn.se> References: <20201211122612.869225-1-jonas@norrbonn.se> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Destination caching on a per-tunnel basis is a performance win, so we enable this unconditionally for the module. Signed-off-by: Jonas Bonn Reported-by: kernel test robot --- drivers/net/Kconfig | 1 + drivers/net/gtp.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 260f9f46668b..f79277222125 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -276,6 +276,7 @@ config GTP tristate "GPRS Tunneling Protocol datapath (GTP-U)" depends on INET select NET_UDP_TUNNEL + select DST_CACHE help This allows one to create gtp virtual interfaces that provide the GPRS Tunneling Protocol datapath (GTP-U). This tunneling protocol diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 40bbbe8cfad6..6708738681d2 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -64,6 +64,8 @@ struct pdp_ctx { struct sock *sk; struct net_device *dev; + struct dst_cache dst_cache; + atomic_t tx_seq; struct rcu_head rcu_head; }; @@ -577,9 +579,15 @@ static struct rtable *gtp_get_v4_rt(struct sk_buff *skb, __be32 *saddr) { const struct sock *sk = pctx->sk; + struct dst_cache *dst_cache; struct rtable *rt = NULL; struct flowi4 fl4; + dst_cache = (struct dst_cache *)&pctx->dst_cache; + rt = dst_cache_get_ip4(dst_cache, saddr); + if (rt) + return rt; + memset(&fl4, 0, sizeof(fl4)); fl4.flowi4_oif = sk->sk_bound_dev_if; fl4.daddr = ipv4(&pctx->peer_addr); @@ -600,6 +608,8 @@ static struct rtable *gtp_get_v4_rt(struct sk_buff *skb, *saddr = fl4.saddr; + dst_cache_set_ip4(dst_cache, &rt->dst, *saddr); + return rt; } @@ -610,8 +620,14 @@ static struct dst_entry *gtp_get_v6_dst(struct sk_buff *skb, { const struct sock *sk = pctx->sk; struct dst_entry *dst = NULL; + struct dst_cache *dst_cache; struct flowi6 fl6; + dst_cache = (struct dst_cache *)&pctx->dst_cache; + dst = dst_cache_get_ip6(dst_cache, saddr); + if (dst) + return dst; + memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_mark = skb->mark; fl6.flowi6_proto = IPPROTO_UDP; @@ -630,6 +646,8 @@ static struct dst_entry *gtp_get_v6_dst(struct sk_buff *skb, *saddr = fl6.saddr; + dst_cache_set_ip6(dst_cache, dst, saddr); + return dst; } @@ -1236,6 +1254,8 @@ static void pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); pctx->flags = 0; + dst_cache_reset(&pctx->dst_cache); + if (info->attrs[GTPA_PEER_IPV6]) { pctx->flags |= PDP_F_PEER_V6; pctx->peer_addr = nla_get_in6_addr(info->attrs[GTPA_PEER_IPV6]); @@ -1331,6 +1351,11 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, if (pctx == NULL) return ERR_PTR(-ENOMEM); + if (dst_cache_init(&pctx->dst_cache, GFP_ATOMIC)) { + kfree(pctx); + return ERR_PTR(-ENOBUFS); + } + sock_hold(sk); pctx->sk = sk; pctx->dev = gtp->dev; @@ -1374,6 +1399,8 @@ static void pdp_context_free(struct rcu_head *head) { struct pdp_ctx *pctx = container_of(head, struct pdp_ctx, rcu_head); + dst_cache_destroy(&pctx->dst_cache); + sock_put(pctx->sk); kfree(pctx); }