Skip to content

Commit 4017124

Browse files
lxindavem330
authored andcommitted
sctp: allow IP fragmentation when PLPMTUD enters Error state
Currently when PLPMTUD enters Error state, transport pathmtu will be set to MIN_PLPMTU(512) while probe is continuing with BASE_PLPMTU(1200). It will cause pathmtu to stay in a very small value, even if the real pmtu is some value like 1000. RFC8899 doesn't clearly say how to set the value in Error state. But one possibility could be keep using BASE_PLPMTU for the real pmtu, but allow to do IP fragmentation when it's in Error state. As it says in rfc8899#section-5.4: Some paths could be unable to sustain packets of the BASE_PLPMTU size. The Error State could be implemented to provide robustness to such paths. This allows fallback to a smaller than desired PLPMTU rather than suffer connectivity failure. This could utilize methods such as endpoint IP fragmentation to enable the PL sender to communicate using packets smaller than the BASE_PLPMTU. This patch is to set pmtu to BASE_PLPMTU instead of MIN_PLPMTU for Error state in sctp_transport_pl_send/toobig(), and set packet ipfragok for non-probe packets when it's in Error state. Fixes: 1dc68c1 ("sctp: do state transition when PROBE_COUNT == MAX_PROBES on HB send path") Reported-by: Ying Xu <[email protected]> Signed-off-by: Xin Long <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 411a44c commit 4017124

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

net/sctp/output.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -581,13 +581,16 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
581581
chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list);
582582
sk = chunk->skb->sk;
583583

584-
/* check gso */
585584
if (packet->size > tp->pathmtu && !packet->ipfragok && !chunk->pmtu_probe) {
586-
if (!sk_can_gso(sk)) {
587-
pr_err_once("Trying to GSO but underlying device doesn't support it.");
588-
goto out;
585+
if (tp->pl.state == SCTP_PL_ERROR) { /* do IP fragmentation if in Error state */
586+
packet->ipfragok = 1;
587+
} else {
588+
if (!sk_can_gso(sk)) { /* check gso */
589+
pr_err_once("Trying to GSO but underlying device doesn't support it.");
590+
goto out;
591+
}
592+
gso = 1;
589593
}
590-
gso = 1;
591594
}
592595

593596
/* alloc head skb */

net/sctp/transport.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ bool sctp_transport_pl_send(struct sctp_transport *t)
269269
if (t->pl.probe_size == SCTP_BASE_PLPMTU) { /* BASE_PLPMTU Confirmation Failed */
270270
t->pl.state = SCTP_PL_ERROR; /* Base -> Error */
271271

272-
t->pl.pmtu = SCTP_MIN_PLPMTU;
272+
t->pl.pmtu = SCTP_BASE_PLPMTU;
273273
t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t);
274274
sctp_assoc_sync_pmtu(t->asoc);
275275
}
@@ -366,7 +366,7 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu)
366366
if (pmtu >= SCTP_MIN_PLPMTU && pmtu < SCTP_BASE_PLPMTU) {
367367
t->pl.state = SCTP_PL_ERROR; /* Base -> Error */
368368

369-
t->pl.pmtu = SCTP_MIN_PLPMTU;
369+
t->pl.pmtu = SCTP_BASE_PLPMTU;
370370
t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t);
371371
}
372372
} else if (t->pl.state == SCTP_PL_SEARCH) {

0 commit comments

Comments
 (0)