Skip to content

Commit

Permalink
Merge branch 'SCTP-PMTU-discovery-fixes'
Browse files Browse the repository at this point in the history
Marcelo Ricardo Leitner says:

====================
SCTP PMTU discovery fixes

This patchset fixes 2 issues with PMTU discovery that can lead to flood
of retransmissions.
The first patch fixes the issue for when PMTUD is disabled by the
application, while the second fixes it for when its enabled.

Please consider these to stable.
====================

Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 8, 2018
2 parents b707fda + b6c5734 commit 313c86d
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 23 deletions.
2 changes: 1 addition & 1 deletion include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ void sctp_transport_burst_limited(struct sctp_transport *);
void sctp_transport_burst_reset(struct sctp_transport *);
unsigned long sctp_transport_timeout(struct sctp_transport *);
void sctp_transport_reset(struct sctp_transport *t);
void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu);
bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu);
void sctp_transport_immediate_rtx(struct sctp_transport *);
void sctp_transport_dst_release(struct sctp_transport *t);
void sctp_transport_dst_confirm(struct sctp_transport *t);
Expand Down
28 changes: 16 additions & 12 deletions net/sctp/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,20 +399,24 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
return;
}

if (t->param_flags & SPP_PMTUD_ENABLE) {
/* Update transports view of the MTU */
sctp_transport_update_pmtu(t, pmtu);

/* Update association pmtu. */
sctp_assoc_sync_pmtu(asoc);
}
if (!(t->param_flags & SPP_PMTUD_ENABLE))
/* We can't allow retransmitting in such case, as the
* retransmission would be sized just as before, and thus we
* would get another icmp, and retransmit again.
*/
return;

/* Retransmit with the new pmtu setting.
* Normally, if PMTU discovery is disabled, an ICMP Fragmentation
* Needed will never be sent, but if a message was sent before
* PMTU discovery was disabled that was larger than the PMTU, it
* would not be fragmented, so it must be re-transmitted fragmented.
/* Update transports view of the MTU. Return if no update was needed.
* If an update wasn't needed/possible, it also doesn't make sense to
* try to retransmit now.
*/
if (!sctp_transport_update_pmtu(t, pmtu))
return;

/* Update association pmtu. */
sctp_assoc_sync_pmtu(asoc);

/* Retransmit with the new pmtu setting. */
sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD);
}

Expand Down
29 changes: 19 additions & 10 deletions net/sctp/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,28 +248,37 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk)
transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
}

void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
{
struct dst_entry *dst = sctp_transport_dst_check(t);
bool change = true;

if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
pr_warn("%s: Reported pmtu %d too low, using default minimum of %d\n",
__func__, pmtu, SCTP_DEFAULT_MINSEGMENT);
/* Use default minimum segment size and disable
* pmtu discovery on this transport.
*/
t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
} else {
t->pathmtu = pmtu;
pr_warn_ratelimited("%s: Reported pmtu %d too low, using default minimum of %d\n",
__func__, pmtu, SCTP_DEFAULT_MINSEGMENT);
/* Use default minimum segment instead */
pmtu = SCTP_DEFAULT_MINSEGMENT;
}
pmtu = SCTP_TRUNC4(pmtu);

if (dst) {
dst->ops->update_pmtu(dst, t->asoc->base.sk, NULL, pmtu);
dst = sctp_transport_dst_check(t);
}

if (!dst)
if (!dst) {
t->af_specific->get_dst(t, &t->saddr, &t->fl, t->asoc->base.sk);
dst = t->dst;
}

if (dst) {
/* Re-fetch, as under layers may have a higher minimum size */
pmtu = SCTP_TRUNC4(dst_mtu(dst));
change = t->pathmtu != pmtu;
}
t->pathmtu = pmtu;

return change;
}

/* Caches the dst entry and source address for a transport's destination
Expand Down

0 comments on commit 313c86d

Please sign in to comment.