netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ipv6: Fix the pmtu path for connected UDP socket
@ 2016-03-14 20:59 Wei Wang
  2016-03-16 23:53 ` David Miller
  2016-03-18  7:17 ` Martin KaFai Lau
  0 siblings, 2 replies; 32+ messages in thread
From: Wei Wang @ 2016-03-14 20:59 UTC (permalink / raw)
  To: David S . Miller; +Cc: Eric Dumazet, netdev, Wei Wang

From: Wei Wang <weiwan@google.com>

When ICMPV6_PKT_TOOBIG message is received by a connected UDP socket,
the new mtu value is not properly updated in the dst_entry associated
with the socket.
This leads to the issue that the mtu value returned by getsockopt(sockfd,
IPPROTO_IPV6, IPV6_MTU, ...) is wrong.
The fix is to update sk->sk_dst_cache and other corresponding fields
when a new routing cache is allocated for the new pmtu in UDP connected
socket case.

Signed-off-by: Wei Wang <weiwan@google.com>
---
 include/net/ip6_route.h |  4 ++--
 net/ipv6/ah6.c          |  2 +-
 net/ipv6/esp6.c         |  2 +-
 net/ipv6/icmp.c         |  2 +-
 net/ipv6/ip6_vti.c      |  2 +-
 net/ipv6/ipcomp6.c      |  2 +-
 net/ipv6/route.c        | 21 +++++++++------------
 7 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 295d291..2b147a8 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -115,8 +115,8 @@ void rt6_purge_dflt_routers(struct net *net);
 int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
 		  const struct in6_addr *gwaddr);
 
-void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif,
-		     u32 mark);
+void ip6_update_pmtu(struct net *net, struct sock *sk, struct sk_buff *skb,
+		     __be32 mtu, int oif, u32 mark);
 void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu);
 void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
 void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 0630a4d5..2c926ec 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -664,7 +664,7 @@ static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	if (type == NDISC_REDIRECT)
 		ip6_redirect(skb, net, skb->dev->ifindex, 0);
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0);
+		ip6_update_pmtu(net, NULL, skb, info, 0, 0);
 	xfrm_state_put(x);
 
 	return 0;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 060a60b..b74847a 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -476,7 +476,7 @@ static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	if (type == NDISC_REDIRECT)
 		ip6_redirect(skb, net, skb->dev->ifindex, 0);
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0);
+		ip6_update_pmtu(net, NULL, skb, info, 0, 0);
 	xfrm_state_put(x);
 
 	return 0;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 0a37ddc..03816f5 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -92,7 +92,7 @@ static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	struct net *net = dev_net(skb->dev);
 
 	if (type == ICMPV6_PKT_TOOBIG)
-		ip6_update_pmtu(skb, net, info, 0, 0);
+		ip6_update_pmtu(net, NULL, skb, info, 0, 0);
 	else if (type == NDISC_REDIRECT)
 		ip6_redirect(skb, net, skb->dev->ifindex, 0);
 
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index d90a11f..fa873ca 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -599,7 +599,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	if (type == NDISC_REDIRECT)
 		ip6_redirect(skb, net, skb->dev->ifindex, 0);
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0);
+		ip6_update_pmtu(net, NULL, skb, info, 0, 0);
 	xfrm_state_put(x);
 
 	return 0;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 1b9316e..c07a5ac 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -76,7 +76,7 @@ static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	if (type == NDISC_REDIRECT)
 		ip6_redirect(skb, net, skb->dev->ifindex, 0);
 	else
-		ip6_update_pmtu(skb, net, info, 0, 0);
+		ip6_update_pmtu(net, NULL, skb, info, 0, 0);
 	xfrm_state_put(x);
 
 	return 0;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index ed44663..8f6a5f1 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1346,7 +1346,7 @@ static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt)
 		(rt->rt6i_flags & RTF_PCPU || rt->rt6i_node);
 }
 
-static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
+static void __ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
 				 const struct ipv6hdr *iph, u32 mtu)
 {
 	struct rt6_info *rt6 = (struct rt6_info *)dst;
@@ -1377,12 +1377,8 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
 		nrt6 = ip6_rt_cache_alloc(rt6, daddr, saddr);
 		if (nrt6) {
 			rt6_do_update_pmtu(nrt6, mtu);
-
-			/* ip6_ins_rt(nrt6) will bump the
-			 * rt6->rt6i_node->fn_sernum
-			 * which will fail the next rt6_check() and
-			 * invalidate the sk->sk_dst_cache.
-			 */
+			if (sk)
+				ip6_dst_store(sk, &nrt6->dst, daddr, saddr);
 			ip6_ins_rt(nrt6);
 		}
 	}
@@ -1394,8 +1390,8 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
 	__ip6_rt_update_pmtu(dst, sk, skb ? ipv6_hdr(skb) : NULL, mtu);
 }
 
-void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
-		     int oif, u32 mark)
+void ip6_update_pmtu(struct net *net, struct sock *sk,
+		     struct sk_buff *skb, __be32 mtu, int oif, u32 mark)
 {
 	const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
 	struct dst_entry *dst;
@@ -1410,15 +1406,16 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
 
 	dst = ip6_route_output(net, NULL, &fl6);
 	if (!dst->error)
-		__ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu));
+		__ip6_rt_update_pmtu(dst, sk, iph, ntohl(mtu));
 	dst_release(dst);
 }
 EXPORT_SYMBOL_GPL(ip6_update_pmtu);
 
 void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
 {
-	ip6_update_pmtu(skb, sock_net(sk), mtu,
-			sk->sk_bound_dev_if, sk->sk_mark);
+	ip6_update_pmtu(sock_net(sk),
+			(sk->sk_state != TCP_ESTABLISHED) ? NULL : sk,
+			skb, mtu, sk->sk_bound_dev_if, sk->sk_mark);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);
 
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related	[flat|nested] 32+ messages in thread
* [PATCH] ipv6: Fix the pmtu path for connected UDP socket
@ 2016-03-02 19:19 Wei Wang
  2016-03-06  5:55 ` David Miller
  2016-03-07 21:28 ` Martin KaFai Lau
  0 siblings, 2 replies; 32+ messages in thread
From: Wei Wang @ 2016-03-02 19:19 UTC (permalink / raw)
  To: David S . Miller; +Cc: netdev, Eric Dumazet, Wei Wang

From: Wei Wang <weiwan@google.com>

When ICMPV6_PKT_TOOBIG message is received by a connected UDP socket,
the new mtu value is not properly updated in the dst_entry associated
with the socket.
This leads to the issue that the mtu value returned by getsockopt(sockfd,
IPPROTO_IPV6, IPV6_MTU, ...) is wrong.
The fix is to call the corresponding pmtu related function for connected
socket so that the dst_entry associated with the socket will get updated
with the new mtu value.
And before we call the above function to update mtu, we check to make
sure the source IP address, destination IP address, source port and
destination port are matching between the incoming flow and the socket.

Signed-off-by: Wei Wang <weiwan@google.com>
---
 net/ipv6/udp.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 0711f8f..5e6ba54 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -49,6 +49,7 @@
 #include <net/inet6_hashtables.h>
 #include <net/busy_poll.h>
 #include <net/sock_reuseport.h>
+#include <net/inet6_connection_sock.h>
 
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -566,7 +567,16 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	if (type == ICMPV6_PKT_TOOBIG) {
 		if (!ip6_sk_accept_pmtu(sk))
 			goto out;
-		ip6_sk_update_pmtu(skb, sk, info);
+		bh_lock_sock(sk);
+		if (sk->sk_state == TCP_ESTABLISHED &&
+		    !sock_owned_by_user(sk) &&
+		    ipv6_addr_equal(saddr, &sk->sk_v6_rcv_saddr) &&
+		    ipv6_addr_equal(daddr, &sk->sk_v6_daddr) &&
+		    uh->dest == sk->sk_dport)
+			inet6_csk_update_pmtu(sk, ntohl(info));
+		else
+			ip6_sk_update_pmtu(skb, sk, info);
+		bh_unlock_sock(sk);
 		if (np->pmtudisc != IPV6_PMTUDISC_DONT)
 			harderr = 1;
 	}
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2016-03-28 23:44 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-14 20:59 [PATCH] ipv6: Fix the pmtu path for connected UDP socket Wei Wang
2016-03-16 23:53 ` David Miller
2016-03-17  0:22   ` Eric Dumazet
2016-03-17  2:38     ` David Miller
2016-03-17  3:34       ` Eric Dumazet
2016-03-18 17:19         ` Cong Wang
     [not found]           ` <CAEA6p_CfDYYLf-s0pUy7VNFH+46PDZSXNzUExXRAM_xv2w8tcw@mail.gmail.com>
2016-03-18 18:10             ` Cong Wang
2016-03-18 21:26               ` Wei Wang
2016-03-18 22:09                 ` Cong Wang
2016-03-21 17:13                   ` Wei Wang
2016-03-22  6:02                     ` Martin KaFai Lau
2016-03-22 16:53                       ` Cong Wang
2016-03-22 17:39                         ` Martin KaFai Lau
2016-03-22 18:03                           ` Wei Wang
2016-03-22 18:16                             ` Martin KaFai Lau
2016-03-22 20:13                             ` Cong Wang
2016-03-22 23:36                               ` Eric Dumazet
2016-03-23 23:57                                 ` Wei Wang
2016-03-24 18:32                                   ` Martin KaFai Lau
2016-03-24 19:45                                     ` Martin KaFai Lau
2016-03-25 23:55                                   ` Martin KaFai Lau
2016-03-26  0:16                                     ` Martin KaFai Lau
2016-03-28 22:39                                       ` Cong Wang
2016-03-28 23:44                                         ` Martin KaFai Lau
2016-03-24 19:23                                 ` Cong Wang
2016-03-22 18:19                           ` Cong Wang
2016-03-18  7:17 ` Martin KaFai Lau
  -- strict thread matches above, loose matches on Subject: below --
2016-03-02 19:19 Wei Wang
2016-03-06  5:55 ` David Miller
2016-03-07 17:19   ` Eric Dumazet
2016-03-07 17:35     ` Eric Dumazet
2016-03-07 21:28 ` Martin KaFai Lau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).