aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMartin KaFai Lau <kafai@fb.com>2016-04-11 18:29:37 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-14 16:29:53 -0400
commite646b657f6983017783914a951039e323120dc55 (patch)
tree4e761d6859d0784b6e24fb1f30cc85467053eba2 /net
parent33c162a980fe03498fcecb917f618ad7e7c55e61 (diff)
ipv6: udp: Do a route lookup and update during release_cb
This patch adds a release_cb for UDPv6. It does a route lookup and updates sk->sk_dst_cache if it is needed. It picks up the left-over job from ip6_sk_update_pmtu() if the sk was owned by user during the pmtu update. It takes a rcu_read_lock to protect the __sk_dst_get() operations because another thread may do ip6_dst_store() without taking the sk lock (e.g. sendmsg). Fixes: 45e4fd26683c ("ipv6: Only create RTF_CACHE routes after encountering pmtu exception") Signed-off-by: Martin KaFai Lau <kafai@fb.com> Reported-by: Wei Wang <weiwan@google.com> Cc: Cong Wang <xiyou.wangcong@gmail.com> Cc: Eric Dumazet <edumazet@google.com> Cc: Wei Wang <weiwan@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/datagram.c20
-rw-r--r--net/ipv6/udp.c1
2 files changed, 21 insertions, 0 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 59e01f27db9f..9dd3882fe6bf 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -119,6 +119,26 @@ out:
119 return err; 119 return err;
120} 120}
121 121
122void ip6_datagram_release_cb(struct sock *sk)
123{
124 struct dst_entry *dst;
125
126 if (ipv6_addr_v4mapped(&sk->sk_v6_daddr))
127 return;
128
129 rcu_read_lock();
130 dst = __sk_dst_get(sk);
131 if (!dst || !dst->obsolete ||
132 dst->ops->check(dst, inet6_sk(sk)->dst_cookie)) {
133 rcu_read_unlock();
134 return;
135 }
136 rcu_read_unlock();
137
138 ip6_datagram_dst_update(sk, false);
139}
140EXPORT_SYMBOL_GPL(ip6_datagram_release_cb);
141
122static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) 142static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
123{ 143{
124 struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; 144 struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 8125931106be..6bc5c664fa46 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1539,6 +1539,7 @@ struct proto udpv6_prot = {
1539 .sendmsg = udpv6_sendmsg, 1539 .sendmsg = udpv6_sendmsg,
1540 .recvmsg = udpv6_recvmsg, 1540 .recvmsg = udpv6_recvmsg,
1541 .backlog_rcv = __udpv6_queue_rcv_skb, 1541 .backlog_rcv = __udpv6_queue_rcv_skb,
1542 .release_cb = ip6_datagram_release_cb,
1542 .hash = udp_lib_hash, 1543 .hash = udp_lib_hash,
1543 .unhash = udp_lib_unhash, 1544 .unhash = udp_lib_unhash,
1544 .rehash = udp_v6_rehash, 1545 .rehash = udp_v6_rehash,