Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/818039/?format=api
{ "id": 818039, "url": "http://patchwork.ozlabs.org/api/patches/818039/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20170925032941.14586-12-tom@quantonium.net/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170925032941.14586-12-tom@quantonium.net>", "list_archive_url": null, "date": "2017-09-25T03:29:40", "name": "[v3,net-next,11/12] gtp: Experimental support encpasulating over IPv6", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": true, "hash": "ee565866c839823c847f88d2d2a3a1009bcff2bf", "submitter": { "id": 72064, "url": "http://patchwork.ozlabs.org/api/people/72064/?format=api", "name": "Tom Herbert", "email": "tom@quantonium.net" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/20170925032941.14586-12-tom@quantonium.net/mbox/", "series": [ { "id": 4865, "url": "http://patchwork.ozlabs.org/api/series/4865/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=4865", "date": "2017-09-25T03:29:29", "name": "gtp: Additional feature support - Part I", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/4865/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/818039/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/818039/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=quantonium-net.20150623.gappssmtp.com\n\theader.i=@quantonium-net.20150623.gappssmtp.com\n\theader.b=\"Hc5tBNij\"; dkim-atps=neutral" ], "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3y0qNQ6ZNmz9t3t\n\tfor <patchwork-incoming@ozlabs.org>;\n\tMon, 25 Sep 2017 13:30:30 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S933102AbdIYDa3 (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tSun, 24 Sep 2017 23:30:29 -0400", "from mail-pg0-f43.google.com ([74.125.83.43]:51236 \"EHLO\n\tmail-pg0-f43.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S933072AbdIYDaY (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Sun, 24 Sep 2017 23:30:24 -0400", "by mail-pg0-f43.google.com with SMTP id k193so3271719pgc.8\n\tfor <netdev@vger.kernel.org>; Sun, 24 Sep 2017 20:30:24 -0700 (PDT)", "from localhost.localdomain (c-73-162-13-107.hsd1.ca.comcast.net.\n\t[73.162.13.107]) by smtp.gmail.com with ESMTPSA id\n\tj2sm9112907pgn.26.2017.09.24.20.30.22\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tSun, 24 Sep 2017 20:30:23 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=quantonium-net.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=OXUGchucXcUf7bydYwkcOwhbIkeA/9SejDVsVZQgpBw=;\n\tb=Hc5tBNijo6T6048gEyxCKktqTzyc2O7gE5DF2wpoiGs9yWMMHuwemiQRvS7v1kYBLP\n\trUFlVaZ0Ao2hIkMwafG6lbXxbRrNZnIc+5AnCWPqUU0PGSt3GZU3iw749dYH4zHLSQG2\n\tbZsxjFFKocQlMJM918JXo1FYdOya5U17VmXJvW4cT8IGB1OuSjHqFF8mGvYlmWA8cS7s\n\tj6HVLOwi42Y7HjtC4+x3nH2rPhFWOjGJY7m5824yQpX53UsTN/UKKX1vLHhScdJWHAN8\n\tMhSxZjbNLffhov357rstxRT0REm+ZMhDNA1d+XY6VkBCaUQt4MP1cPYtNIXy2OUk1WgB\n\tvTxg==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=OXUGchucXcUf7bydYwkcOwhbIkeA/9SejDVsVZQgpBw=;\n\tb=cFBxpyJULObDeN1T6/XqFxVyK1OimUivpGNOGYALA/V/+SiS4WgylJSj200sqbUB+2\n\tJ/d0zaeWQMy5zgZJLj0gjtv6rFTGgEToUyuLHTZU8wWODk/7GzJXTixIVYIUa9ZxcnG0\n\tuMiITi4O5YEPJCi2VRq/5abT8l/kS2OQkrE4C0qn09LP7m/cl1oGaGVG8WmDxqF3/Tnl\n\t2/NS2jR35G20QPs+zlRxk5T24VnPT6YBzLCKOZZJvSkflNUOpvbJA0leT1xhUNZBzkTd\n\tzLWAHK1fzMpIUlYsBoX63fLDcjTN0S47dYf7BocJqqXLfaZgdkAUi3KC12y9v2b3VQeh\n\tGxKA==", "X-Gm-Message-State": "AHPjjUg6FNLM4YTqXDu1N055HYpDgSoXcJaWJwI0rzfGxjnblq0U38Zv\n\tmCMXWJeEV6NYDdKFMeW5/OnIBg==", "X-Google-Smtp-Source": "AOwi7QDQSRWuzcP3QBktPjKNdaIgHqKTPcCIvGyWwa8JCYItPQ0ycBA1iz6NP434C2WsO1mY6mWZjA==", "X-Received": "by 10.159.194.10 with SMTP id x10mr6442144pln.47.1506310224388; \n\tSun, 24 Sep 2017 20:30:24 -0700 (PDT)", "From": "Tom Herbert <tom@quantonium.net>", "To": "davem@davemloft.net", "Cc": "pablo@netfilter.org, laforge@gnumonks.org, aschultz@tpip.net,\n\tnetdev@vger.kernel.org, rohit@quantonium.net,\n\tTom Herbert <tom@quantonium.net>", "Subject": "[PATCH v3 net-next 11/12] gtp: Experimental support encpasulating\n\tover 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": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "Allows using GTP datapath over IPv6. Remote peers are indicated by IPv6.\n\nNote this is experimental, more work is needed to make this\ncompliant with 3GPP standard.\n\nSigned-off-by: Tom Herbert <tom@quantonium.net>\n---\n drivers/net/gtp.c | 248 ++++++++++++++++++++++++++++++++++---------\n include/uapi/linux/gtp.h | 1 +\n include/uapi/linux/if_link.h | 3 +\n 3 files changed, 200 insertions(+), 52 deletions(-)", "diff": "diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c\nindex 919ec6e14973..1c580df4cfc5 100644\n--- a/drivers/net/gtp.c\n+++ b/drivers/net/gtp.c\n@@ -28,6 +28,7 @@\n #include <net/net_namespace.h>\n #include <net/protocol.h>\n #include <net/ip.h>\n+#include <net/ip6_tunnel.h>\n #include <net/udp.h>\n #include <net/udp_tunnel.h>\n #include <net/icmp.h>\n@@ -59,16 +60,22 @@ struct pdp_ctx {\n \t__be16\t\t\tgtp_port;\n \n \tu16\t\t\tms_af;\n+\tu16\t\t\tpeer_af;\n #if GTP_IPV6\n \tunion {\n \t\tstruct in_addr\tms_addr_ip4;\n \t\tstruct in6_addr\tms_addr_ip6;\n \t};\n+\n+\tunion {\n+\t\tstruct in_addr\tpeer_addr_ip4;\n+\t\tstruct in6_addr\tpeer_addr_ip6;\n+\t};\n #else\n \tstruct in_addr\tms_addr_ip4;\n+\tstruct in_addr\tpeer_addr_ip4;\n #endif\n \n-\tstruct in_addr\t\tpeer_addr_ip4;\n \n \tstruct sock\t\t*sk;\n \tstruct net_device *dev;\n@@ -93,8 +100,11 @@ struct gtp_dev {\n \tstruct hlist_head\t*tid_hash;\n \n \tstruct hlist_head\t*addr4_hash;\n+\n #if GTP_IPV6\n \tstruct hlist_head\t*addr6_hash;\n+\n+\tunsigned int\t\tis_ipv6:1;\n #endif\n \n \tstruct gro_cells\tgro_cells;\n@@ -534,8 +544,6 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev,\n {\n \tstruct iphdr *inner_iph = NULL;\n \tstruct sock *sk = pctx->sk;\n-\t__be32 saddr = inet_sk(sk)->inet_saddr;\n-\tstruct rtable *rt;\n \tint err = 0;\n \n \tif (skb->protocol == ETH_P_IP)\n@@ -548,38 +556,84 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev,\n \n \tskb_reset_inner_headers(skb);\n \n-\t/* Source address returned by route lookup is ignored since\n-\t * we get the address from a socket.\n-\t */\n-\trt = ip_tunnel_get_route(dev, skb, sk->sk_protocol,\n-\t\t\t\t sk->sk_bound_dev_if, RT_CONN_FLAGS(sk),\n-\t\t\t\t pctx->peer_addr_ip4.s_addr, &saddr,\n-\t\t\t\t pctx->gtp_port, pctx->gtp_port,\n-\t\t\t\t &pctx->dst_cache, NULL);\n-\n-\tif (IS_ERR(rt)) {\n-\t\terr = PTR_ERR(rt);\n-\t\tgoto out_err;\n-\t}\n+\tif (pctx->peer_af == AF_INET) {\n+\t\t__be32 saddr = inet_sk(sk)->inet_saddr;\n+\t\tstruct rtable *rt;\n+\n+\t\t/* Source address returned by route lookup is ignored since\n+\t\t * we get the address from a socket.\n+\t\t */\n+\t\trt = ip_tunnel_get_route(dev, skb, sk->sk_protocol,\n+\t\t\t\t\t sk->sk_bound_dev_if, RT_CONN_FLAGS(sk),\n+\t\t\t\t\t pctx->peer_addr_ip4.s_addr, &saddr,\n+\t\t\t\t\t pctx->gtp_port, pctx->gtp_port,\n+\t\t\t\t\t &pctx->dst_cache, NULL);\n+\n+\t\tif (IS_ERR(rt)) {\n+\t\t\terr = PTR_ERR(rt);\n+\t\t\tgoto out_err;\n+\t\t}\n+\n+\t\tskb_dst_drop(skb);\n \n-\tskb_dst_drop(skb);\n+\t\tgtp_push_header(skb, pctx);\n \n-\tgtp_push_header(skb, pctx);\n+\t\tif (inner_iph)\n+\t\t\t__iptunnel_update_pmtu(dev, skb, &rt->dst,\n+\t\t\t\t\t !!inner_iph->frag_off,\n+\t\t\t\t\t inner_iph, pctx->hlen,\n+\t\t\t\t\t pctx->peer_addr_ip4.s_addr);\n \n-\tif (inner_iph)\n-\t\t__iptunnel_update_pmtu(dev, skb, &rt->dst,\n-\t\t\t\t !!inner_iph->frag_off,\n-\t\t\t\t inner_iph, pctx->hlen,\n-\t\t\t\t pctx->peer_addr_ip4.s_addr);\n+\t\tudp_tunnel_xmit_skb(rt, sk, skb, saddr,\n+\t\t\t\t pctx->peer_addr_ip4.s_addr,\n+\t\t\t\t 0, ip4_dst_hoplimit(&rt->dst), 0,\n+\t\t\t\t pctx->gtp_port, pctx->gtp_port,\n+\t\t\t\t false, false);\n \n-\tudp_tunnel_xmit_skb(rt, sk, skb, saddr,\n-\t\t\t pctx->peer_addr_ip4.s_addr,\n-\t\t\t 0, ip4_dst_hoplimit(&rt->dst), 0,\n-\t\t\t pctx->gtp_port, pctx->gtp_port,\n-\t\t\t false, false);\n+\t\tnetdev_dbg(dev, \"gtp -> IP src: %pI4 dst: %pI4\\n\",\n+\t\t\t &saddr, &pctx->peer_addr_ip4.s_addr);\n \n-\tnetdev_dbg(dev, \"gtp -> IP src: %pI4 dst: %pI4\\n\",\n-\t\t &saddr, &pctx->peer_addr_ip4.s_addr);\n+#if GTP_IPV6\n+#if IS_ENABLED(CONFIG_IPV6)\n+\t} else if (pctx->peer_af == AF_INET6) {\n+\t\tstruct in6_addr saddr = inet6_sk(sk)->saddr;\n+\t\tstruct dst_entry *dst;\n+\n+\t\t/* Source address returned by route lookup is ignored since\n+\t\t * we get the address from a socket.\n+\t\t */\n+\t\tdst = ip6_tnl_get_route(dev, skb, sk, sk->sk_protocol,\n+\t\t\t\t\tsk->sk_bound_dev_if, 0,\n+\t\t\t\t\t0, &pctx->peer_addr_ip6, &saddr,\n+\t\t\t\t\tpctx->gtp_port, pctx->gtp_port,\n+\t\t\t\t\t&pctx->dst_cache, NULL);\n+\n+\t\tif (IS_ERR(dst)) {\n+\t\t\terr = PTR_ERR(dst);\n+\t\t\tgoto out_err;\n+\t\t}\n+\n+\t\tskb_dst_drop(skb);\n+\n+\t\tgtp_push_header(skb, pctx);\n+\n+\t\tif (inner_iph)\n+\t\t\t__iptunnel_update_pmtu(dev, skb, dst,\n+\t\t\t\t\t !!inner_iph->frag_off,\n+\t\t\t\t\t inner_iph, pctx->hlen, 0);\n+\n+\t\tudp_tunnel6_xmit_skb(dst, sk, skb, dev,\n+\t\t\t\t &saddr, &pctx->peer_addr_ip6,\n+\t\t\t\t 0, ip6_dst_hoplimit(dst), 0,\n+\t\t\t\t pctx->gtp_port, pctx->gtp_port,\n+\t\t\t\t false);\n+\n+\t\tnetdev_dbg(dev, \"gtp -> IP src: %pI6 dst: %pI6\\n\",\n+\t\t\t &saddr, &pctx->peer_addr_ip6);\n+\n+#endif\n+#endif\n+\t}\n \n \treturn 0;\n \n@@ -688,7 +742,12 @@ static void gtp_link_setup(struct net_device *dev)\n \n \t/* Assume largest header, ie. GTPv0. */\n \tdev->needed_headroom\t= LL_MAX_HEADER +\n+#if GTP_IPV6\n+\t\t\t\t max_t(int, sizeof(struct iphdr),\n+\t\t\t\t\tsizeof(struct ipv6hdr)) +\n+#else\n \t\t\t\t sizeof(struct iphdr) +\n+#endif\n \t\t\t\t sizeof(struct udphdr) +\n \t\t\t\t sizeof(struct gtp0_header);\n \n@@ -697,12 +756,15 @@ static void gtp_link_setup(struct net_device *dev)\n \n static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize);\n static void gtp_hashtable_free(struct gtp_dev *gtp);\n-static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]);\n+static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[],\n+\t\t\t bool is_ipv6);\n \n static int gtp_newlink(struct net *src_net, struct net_device *dev,\n \t\t struct nlattr *tb[], struct nlattr *data[],\n \t\t struct netlink_ext_ack *extack)\n {\n+\tunsigned int role = GTP_ROLE_GGSN;\n+\tbool is_ipv6 = false;\n \tstruct gtp_dev *gtp;\n \tstruct gtp_net *gn;\n \tint hashsize, err;\n@@ -710,9 +772,32 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,\n \tif (!data[IFLA_GTP_FD0] && !data[IFLA_GTP_FD1])\n \t\treturn -EINVAL;\n \n+\tif (data[IFLA_GTP_ROLE]) {\n+\t\trole = nla_get_u32(data[IFLA_GTP_ROLE]);\n+\t\tif (role > GTP_ROLE_SGSN)\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\tif (data[IFLA_GTP_AF]) {\n+\t\tu16 af = nla_get_u16(data[IFLA_GTP_AF]);\n+\n+\t\tswitch (af) {\n+\t\tcase AF_INET:\n+\t\t\tis_ipv6 = false;\n+\t\t\tbreak;\n+#if GTP_IPV6\n+\t\tcase AF_INET6:\n+\t\t\tis_ipv6 = true;\n+\t\t\tbreak;\n+#endif\n+\t\tdefault:\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n \tgtp = netdev_priv(dev);\n \n-\terr = gtp_encap_enable(gtp, data);\n+\terr = gtp_encap_enable(gtp, data, is_ipv6);\n \tif (err < 0)\n \t\treturn err;\n \n@@ -731,6 +816,11 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,\n \t\tgoto out_hashtable;\n \t}\n \n+\tgtp->role = role;\n+#if GTP_IPV6\n+\tgtp->is_ipv6 = is_ipv6;\n+#endif\n+\n \tgn = net_generic(dev_net(dev), gtp_net_id);\n \tlist_add_rcu(>p->list, &gn->gtp_dev_list);\n \n@@ -860,7 +950,8 @@ static void gtp_hashtable_free(struct gtp_dev *gtp)\n }\n \n static struct sock *gtp_encap_enable_socket(int fd, int type,\n-\t\t\t\t\t struct gtp_dev *gtp)\n+\t\t\t\t\t struct gtp_dev *gtp,\n+\t\t\t\t\t bool is_ipv6)\n {\n \tstruct udp_tunnel_sock_cfg tuncfg = {NULL};\n \tstruct socket *sock;\n@@ -881,6 +972,12 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,\n \t\tgoto out_sock;\n \t}\n \n+\tif (sock->sk->sk_family != (is_ipv6 ? AF_INET6 : AF_INET)) {\n+\t\tpr_debug(\"socket fd=%d not right family\\n\", fd);\n+\t\tsk = ERR_PTR(-EINVAL);\n+\t\tgoto out_sock;\n+\t}\n+\n \tif (rcu_dereference_sk_user_data(sock->sk)) {\n \t\tsk = ERR_PTR(-EBUSY);\n \t\tgoto out_sock;\n@@ -913,16 +1010,16 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,\n \treturn sk;\n }\n \n-static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])\n+static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[],\n+\t\t\t bool is_ipv6)\n {\n-\tstruct sock *sk1u = NULL;\n-\tstruct sock *sk0 = NULL;\n-\tunsigned int role = GTP_ROLE_GGSN;\n+\tstruct sock *sk0 = NULL, *sk1u = NULL;\n \n \tif (data[IFLA_GTP_FD0]) {\n \t\tu32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);\n \n-\t\tsk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp);\n+\t\tsk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp,\n+\t\t\t\t\t is_ipv6);\n \t\tif (IS_ERR(sk0))\n \t\t\treturn PTR_ERR(sk0);\n \t}\n@@ -930,7 +1027,8 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])\n \tif (data[IFLA_GTP_FD1]) {\n \t\tu32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]);\n \n-\t\tsk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp);\n+\t\tsk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp,\n+\t\t\t\t\t is_ipv6);\n \t\tif (IS_ERR(sk1u)) {\n \t\t\tif (sk0)\n \t\t\t\tgtp_encap_disable_sock(sk0);\n@@ -938,15 +1036,8 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])\n \t\t}\n \t}\n \n-\tif (data[IFLA_GTP_ROLE]) {\n-\t\trole = nla_get_u32(data[IFLA_GTP_ROLE]);\n-\t\tif (role > GTP_ROLE_SGSN)\n-\t\t\treturn -EINVAL;\n-\t}\n-\n \tgtp->sk0 = sk0;\n \tgtp->sk1u = sk1u;\n-\tgtp->role = role;\n \n \treturn 0;\n }\n@@ -982,8 +1073,18 @@ static void pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)\n \t__be16 default_port = 0;\n \n \tpctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]);\n-\tpctx->peer_addr_ip4.s_addr =\n-\t\tnla_get_be32(info->attrs[GTPA_PEER_ADDRESS]);\n+\n+\tif (info->attrs[GTPA_PEER_ADDRESS]) {\n+\t\tpctx->peer_af = AF_INET;\n+\t\tpctx->peer_addr_ip4.s_addr =\n+\t\t\tnla_get_in_addr(info->attrs[GTPA_PEER_ADDRESS]);\n+#if GTP_IPV6\n+\t} else if (info->attrs[GTPA_PEER6_ADDRESS]) {\n+\t\tpctx->peer_af = AF_INET6;\n+\t\tpctx->peer_addr_ip6 = nla_get_in6_addr(\n+\t\t\t\t\tinfo->attrs[GTPA_PEER6_ADDRESS]);\n+#endif\n+\t}\n \n \tswitch (pctx->gtp_version) {\n \tcase GTP_V0:\n@@ -1162,11 +1263,17 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)\n \tint err;\n \n \tif (!info->attrs[GTPA_VERSION] ||\n-\t !info->attrs[GTPA_LINK] ||\n-\t !info->attrs[GTPA_PEER_ADDRESS])\n+\t !info->attrs[GTPA_LINK])\n \t\treturn -EINVAL;\n \n #if GTP_IPV6\n+\tif (!(!!info->attrs[GTPA_PEER_ADDRESS] ^\n+\t !!info->attrs[GTPA_PEER6_ADDRESS])) {\n+\t\t/* Either v4 or v6 peer address must be set */\n+\n+\t\treturn -EINVAL;\n+\t}\n+\n \tif (!(!!info->attrs[GTPA_MS_ADDRESS] ^\n \t !!info->attrs[GTPA_MS6_ADDRESS])) {\n \t\t/* Either v4 or v6 mobile subscriber address must be set */\n@@ -1174,6 +1281,12 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)\n \t\treturn -EINVAL;\n \t}\n #else\n+\tif (!info->attrs[GTPA_PEER_ADDRESS]) {\n+\t\t/* v4 peer address must be set */\n+\n+\t\treturn -EINVAL;\n+\t}\n+\n \tif (!info->attrs[GTPA_MS_ADDRESS]) {\n \t\t/* v4 mobile subscriber address must be set */\n \n@@ -1207,6 +1320,14 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)\n \t\tgoto out_unlock;\n \t}\n \n+#if GTP_IPV6\n+\tif ((info->attrs[GTPA_PEER_ADDRESS] && gtp->is_ipv6) ||\n+\t (info->attrs[GTPA_PEER6_ADDRESS] && !gtp->is_ipv6)) {\n+\t\terr = -EINVAL;\n+\t\tgoto out_unlock;\n+\t}\n+#endif\n+\n \tif (version == GTP_V0)\n \t\tsk = gtp->sk0;\n \telse if (version == GTP_V1)\n@@ -1315,10 +1436,31 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,\n \tif (genlh == NULL)\n \t\tgoto nlmsg_failure;\n \n-\tif (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) ||\n-\t nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr))\n+\tif (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version))\n \t\tgoto nla_put_failure;\n \n+\tif (nla_put_u32(skb, GTPA_LINK, pctx->dev->ifindex))\n+\t\tgoto nla_put_failure;\n+\n+\tswitch (pctx->peer_af) {\n+\tcase AF_INET:\n+\t\tif (nla_put_be32(skb, GTPA_PEER_ADDRESS,\n+\t\t\t\t pctx->peer_addr_ip4.s_addr))\n+\t\t\tgoto nla_put_failure;\n+\n+\t\tbreak;\n+#if GTP_IPV6\n+\tcase AF_INET6:\n+\t\tif (nla_put_in6_addr(skb, GTPA_PEER6_ADDRESS,\n+\t\t\t\t &pctx->peer_addr_ip6))\n+\t\t\tgoto nla_put_failure;\n+\n+\t\tbreak;\n+#endif\n+\tdefault:\n+\t\tgoto nla_put_failure;\n+\t}\n+\n \tswitch (pctx->ms_af) {\n \tcase AF_INET:\n \t\tif (nla_put_be32(skb, GTPA_MS_ADDRESS,\n@@ -1448,6 +1590,8 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = {\n \t[GTPA_PEER_ADDRESS]\t= { .type = NLA_U32, },\n \t[GTPA_MS_ADDRESS]\t= { .type = NLA_U32, },\n #if GTP_IPV6\n+\t[GTPA_PEER6_ADDRESS]\t= { .len = FIELD_SIZEOF(struct ipv6hdr,\n+\t\t\t\t\t\t\tdaddr) },\n \t[GTPA_MS6_ADDRESS]\t= { .len = FIELD_SIZEOF(struct ipv6hdr,\n \t\t\t\t\t\t\tdaddr) },\n #endif\ndiff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h\nindex ae4e632c0360..8eec519fa754 100644\n--- a/include/uapi/linux/gtp.h\n+++ b/include/uapi/linux/gtp.h\n@@ -29,6 +29,7 @@ enum gtp_attrs {\n \tGTPA_PAD,\n \tGTPA_PORT,\n \tGTPA_MS6_ADDRESS,\n+\tGTPA_PEER6_ADDRESS,\n \t__GTPA_MAX,\n };\n #define GTPA_MAX (__GTPA_MAX + 1)\ndiff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h\nindex 8d062c58d5cb..81c26864abeb 100644\n--- a/include/uapi/linux/if_link.h\n+++ b/include/uapi/linux/if_link.h\n@@ -552,6 +552,9 @@ enum {\n \tIFLA_GTP_FD1,\n \tIFLA_GTP_PDP_HASHSIZE,\n \tIFLA_GTP_ROLE,\n+\tIFLA_GTP_AF,\n+\tIFLA_GTP_PORT0,\n+\tIFLA_GTP_PORT1,\n \t__IFLA_GTP_MAX,\n };\n #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)\n", "prefixes": [ "v3", "net-next", "11/12" ] }