diff options
author | David S. Miller <davem@davemloft.net> | 2012-07-16 06:44:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-16 06:44:56 -0400 |
commit | 35ad9b9cf7d8a2e6259a0d24022e910adb6f3489 (patch) | |
tree | d9772467e072f3f1d142aa0ce2fc56ef69c57cb7 /net | |
parent | 80d0a69fc57715dc9080c0567df1ed911b78abea (diff) |
ipv6: Add helper inet6_csk_update_pmtu().
This is the ipv6 version of inet_csk_update_pmtu().
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/dccp/ipv6.c | 35 | ||||
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 49 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 37 |
3 files changed, 43 insertions, 78 deletions
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 090c0800ce03..3ee0342e1cec 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -145,39 +145,12 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
145 | if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED)) | 145 | if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED)) |
146 | goto out; | 146 | goto out; |
147 | 147 | ||
148 | /* icmp should have updated the destination cache entry */ | 148 | dst = inet6_csk_update_pmtu(sk, ntohl(info)); |
149 | dst = __sk_dst_check(sk, np->dst_cookie); | 149 | if (!dst) |
150 | if (dst == NULL) { | 150 | goto out; |
151 | struct inet_sock *inet = inet_sk(sk); | ||
152 | struct flowi6 fl6; | ||
153 | |||
154 | /* BUGGG_FUTURE: Again, it is not clear how | ||
155 | to handle rthdr case. Ignore this complexity | ||
156 | for now. | ||
157 | */ | ||
158 | memset(&fl6, 0, sizeof(fl6)); | ||
159 | fl6.flowi6_proto = IPPROTO_DCCP; | ||
160 | fl6.daddr = np->daddr; | ||
161 | fl6.saddr = np->saddr; | ||
162 | fl6.flowi6_oif = sk->sk_bound_dev_if; | ||
163 | fl6.fl6_dport = inet->inet_dport; | ||
164 | fl6.fl6_sport = inet->inet_sport; | ||
165 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | ||
166 | |||
167 | dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false); | ||
168 | if (IS_ERR(dst)) { | ||
169 | sk->sk_err_soft = -PTR_ERR(dst); | ||
170 | goto out; | ||
171 | } | ||
172 | } else | ||
173 | dst_hold(dst); | ||
174 | |||
175 | dst->ops->update_pmtu(dst, ntohl(info)); | ||
176 | 151 | ||
177 | if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) { | 152 | if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) |
178 | dccp_sync_mss(sk, dst_mtu(dst)); | 153 | dccp_sync_mss(sk, dst_mtu(dst)); |
179 | } /* else let the usual retransmit timer handle it */ | ||
180 | dst_release(dst); | ||
181 | goto out; | 154 | goto out; |
182 | } | 155 | } |
183 | 156 | ||
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index bceb14450a1d..62539a4b2dc7 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -203,15 +203,13 @@ struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) | |||
203 | return dst; | 203 | return dst; |
204 | } | 204 | } |
205 | 205 | ||
206 | int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | 206 | static struct dst_entry *inet6_csk_route_socket(struct sock *sk) |
207 | { | 207 | { |
208 | struct sock *sk = skb->sk; | ||
209 | struct inet_sock *inet = inet_sk(sk); | 208 | struct inet_sock *inet = inet_sk(sk); |
210 | struct ipv6_pinfo *np = inet6_sk(sk); | 209 | struct ipv6_pinfo *np = inet6_sk(sk); |
211 | struct flowi6 fl6; | ||
212 | struct dst_entry *dst; | ||
213 | struct in6_addr *final_p, final; | 210 | struct in6_addr *final_p, final; |
214 | int res; | 211 | struct dst_entry *dst; |
212 | struct flowi6 fl6; | ||
215 | 213 | ||
216 | memset(&fl6, 0, sizeof(fl6)); | 214 | memset(&fl6, 0, sizeof(fl6)); |
217 | fl6.flowi6_proto = sk->sk_protocol; | 215 | fl6.flowi6_proto = sk->sk_protocol; |
@@ -228,18 +226,29 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | |||
228 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 226 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
229 | 227 | ||
230 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); | 228 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
231 | 229 | if (!dst) { | |
232 | if (dst == NULL) { | ||
233 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); | 230 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
234 | 231 | ||
235 | if (IS_ERR(dst)) { | 232 | if (!IS_ERR(dst)) |
236 | sk->sk_err_soft = -PTR_ERR(dst); | 233 | __inet6_csk_dst_store(sk, dst, NULL, NULL); |
237 | sk->sk_route_caps = 0; | 234 | } |
238 | kfree_skb(skb); | 235 | return dst; |
239 | return PTR_ERR(dst); | 236 | } |
240 | } | ||
241 | 237 | ||
242 | __inet6_csk_dst_store(sk, dst, NULL, NULL); | 238 | int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) |
239 | { | ||
240 | struct sock *sk = skb->sk; | ||
241 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
242 | struct flowi6 fl6; | ||
243 | struct dst_entry *dst; | ||
244 | int res; | ||
245 | |||
246 | dst = inet6_csk_route_socket(sk); | ||
247 | if (IS_ERR(dst)) { | ||
248 | sk->sk_err_soft = -PTR_ERR(dst); | ||
249 | sk->sk_route_caps = 0; | ||
250 | kfree_skb(skb); | ||
251 | return PTR_ERR(dst); | ||
243 | } | 252 | } |
244 | 253 | ||
245 | rcu_read_lock(); | 254 | rcu_read_lock(); |
@@ -253,3 +262,15 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | |||
253 | return res; | 262 | return res; |
254 | } | 263 | } |
255 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); | 264 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); |
265 | |||
266 | struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu) | ||
267 | { | ||
268 | struct dst_entry *dst = inet6_csk_route_socket(sk); | ||
269 | |||
270 | if (IS_ERR(dst)) | ||
271 | return NULL; | ||
272 | dst->ops->update_pmtu(dst, mtu); | ||
273 | |||
274 | return inet6_csk_route_socket(sk); | ||
275 | } | ||
276 | EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu); | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3071f377145c..ecdf241cad02 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -378,43 +378,14 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
378 | if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) | 378 | if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) |
379 | goto out; | 379 | goto out; |
380 | 380 | ||
381 | /* icmp should have updated the destination cache entry */ | 381 | dst = inet6_csk_update_pmtu(sk, ntohl(info)); |
382 | dst = __sk_dst_check(sk, np->dst_cookie); | 382 | if (!dst) |
383 | 383 | goto out; | |
384 | if (dst == NULL) { | ||
385 | struct inet_sock *inet = inet_sk(sk); | ||
386 | struct flowi6 fl6; | ||
387 | |||
388 | /* BUGGG_FUTURE: Again, it is not clear how | ||
389 | to handle rthdr case. Ignore this complexity | ||
390 | for now. | ||
391 | */ | ||
392 | memset(&fl6, 0, sizeof(fl6)); | ||
393 | fl6.flowi6_proto = IPPROTO_TCP; | ||
394 | fl6.daddr = np->daddr; | ||
395 | fl6.saddr = np->saddr; | ||
396 | fl6.flowi6_oif = sk->sk_bound_dev_if; | ||
397 | fl6.flowi6_mark = sk->sk_mark; | ||
398 | fl6.fl6_dport = inet->inet_dport; | ||
399 | fl6.fl6_sport = inet->inet_sport; | ||
400 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); | ||
401 | |||
402 | dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false); | ||
403 | if (IS_ERR(dst)) { | ||
404 | sk->sk_err_soft = -PTR_ERR(dst); | ||
405 | goto out; | ||
406 | } | ||
407 | |||
408 | } else | ||
409 | dst_hold(dst); | ||
410 | |||
411 | dst->ops->update_pmtu(dst, ntohl(info)); | ||
412 | 384 | ||
413 | if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) { | 385 | if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) { |
414 | tcp_sync_mss(sk, dst_mtu(dst)); | 386 | tcp_sync_mss(sk, dst_mtu(dst)); |
415 | tcp_simple_retransmit(sk); | 387 | tcp_simple_retransmit(sk); |
416 | } /* else let the usual retransmit timer handle it */ | 388 | } |
417 | dst_release(dst); | ||
418 | goto out; | 389 | goto out; |
419 | } | 390 | } |
420 | 391 | ||