diff options
| -rw-r--r-- | include/net/sctp/structs.h | 2 | ||||
| -rw-r--r-- | net/sctp/input.c | 8 | ||||
| -rw-r--r-- | net/sctp/transport.c | 29 |
3 files changed, 26 insertions, 13 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 2f8f93da5dc2..9a5ccf03a59b 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
| @@ -966,7 +966,7 @@ void sctp_transport_burst_limited(struct sctp_transport *); | |||
| 966 | void sctp_transport_burst_reset(struct sctp_transport *); | 966 | void sctp_transport_burst_reset(struct sctp_transport *); |
| 967 | unsigned long sctp_transport_timeout(struct sctp_transport *); | 967 | unsigned long sctp_transport_timeout(struct sctp_transport *); |
| 968 | void sctp_transport_reset(struct sctp_transport *t); | 968 | void sctp_transport_reset(struct sctp_transport *t); |
| 969 | void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu); | 969 | bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu); |
| 970 | void sctp_transport_immediate_rtx(struct sctp_transport *); | 970 | void sctp_transport_immediate_rtx(struct sctp_transport *); |
| 971 | void sctp_transport_dst_release(struct sctp_transport *t); | 971 | void sctp_transport_dst_release(struct sctp_transport *t); |
| 972 | void sctp_transport_dst_confirm(struct sctp_transport *t); | 972 | void sctp_transport_dst_confirm(struct sctp_transport *t); |
diff --git a/net/sctp/input.c b/net/sctp/input.c index 9320661cc41d..141c9c466ec1 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
| @@ -406,8 +406,12 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, | |||
| 406 | */ | 406 | */ |
| 407 | return; | 407 | return; |
| 408 | 408 | ||
| 409 | /* Update transports view of the MTU */ | 409 | /* Update transports view of the MTU. Return if no update was needed. |
| 410 | sctp_transport_update_pmtu(t, pmtu); | 410 | * If an update wasn't needed/possible, it also doesn't make sense to |
| 411 | * try to retransmit now. | ||
| 412 | */ | ||
| 413 | if (!sctp_transport_update_pmtu(t, pmtu)) | ||
| 414 | return; | ||
| 411 | 415 | ||
| 412 | /* Update association pmtu. */ | 416 | /* Update association pmtu. */ |
| 413 | sctp_assoc_sync_pmtu(asoc); | 417 | sctp_assoc_sync_pmtu(asoc); |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 1e5a22430cf5..47f82bd794d9 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -248,28 +248,37 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) | |||
| 248 | transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; | 248 | transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) | 251 | bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) |
| 252 | { | 252 | { |
| 253 | struct dst_entry *dst = sctp_transport_dst_check(t); | 253 | struct dst_entry *dst = sctp_transport_dst_check(t); |
| 254 | bool change = true; | ||
| 254 | 255 | ||
| 255 | if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) { | 256 | if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) { |
| 256 | pr_warn("%s: Reported pmtu %d too low, using default minimum of %d\n", | 257 | pr_warn_ratelimited("%s: Reported pmtu %d too low, using default minimum of %d\n", |
| 257 | __func__, pmtu, SCTP_DEFAULT_MINSEGMENT); | 258 | __func__, pmtu, SCTP_DEFAULT_MINSEGMENT); |
| 258 | /* Use default minimum segment size and disable | 259 | /* Use default minimum segment instead */ |
| 259 | * pmtu discovery on this transport. | 260 | pmtu = SCTP_DEFAULT_MINSEGMENT; |
| 260 | */ | ||
| 261 | t->pathmtu = SCTP_DEFAULT_MINSEGMENT; | ||
| 262 | } else { | ||
| 263 | t->pathmtu = pmtu; | ||
| 264 | } | 261 | } |
| 262 | pmtu = SCTP_TRUNC4(pmtu); | ||
| 265 | 263 | ||
| 266 | if (dst) { | 264 | if (dst) { |
| 267 | dst->ops->update_pmtu(dst, t->asoc->base.sk, NULL, pmtu); | 265 | dst->ops->update_pmtu(dst, t->asoc->base.sk, NULL, pmtu); |
| 268 | dst = sctp_transport_dst_check(t); | 266 | dst = sctp_transport_dst_check(t); |
| 269 | } | 267 | } |
| 270 | 268 | ||
| 271 | if (!dst) | 269 | if (!dst) { |
| 272 | t->af_specific->get_dst(t, &t->saddr, &t->fl, t->asoc->base.sk); | 270 | t->af_specific->get_dst(t, &t->saddr, &t->fl, t->asoc->base.sk); |
| 271 | dst = t->dst; | ||
| 272 | } | ||
| 273 | |||
| 274 | if (dst) { | ||
| 275 | /* Re-fetch, as under layers may have a higher minimum size */ | ||
| 276 | pmtu = SCTP_TRUNC4(dst_mtu(dst)); | ||
| 277 | change = t->pathmtu != pmtu; | ||
| 278 | } | ||
| 279 | t->pathmtu = pmtu; | ||
| 280 | |||
| 281 | return change; | ||
| 273 | } | 282 | } |
| 274 | 283 | ||
| 275 | /* Caches the dst entry and source address for a transport's destination | 284 | /* Caches the dst entry and source address for a transport's destination |
