SCTP: Assign stream sequence numbers to the entire message
Currently we only assign the sequence number to a packet that we are about to transmit. This however breaks the Partial Reliability extensions, because it's possible for us to never transmit a packet, i.e. it expires before we get to send it. In such cases, if the message contained multiple SCTP fragments, and we did manage to send the first part of the message, the Stream sequence numbers would get into invalid state and cause receiver to stall. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
This commit is contained in:
parent
ea2dfb3733
commit
ab3e5e7b65
|
@ -1174,25 +1174,36 @@ out:
|
|||
*/
|
||||
void sctp_chunk_assign_ssn(struct sctp_chunk *chunk)
|
||||
{
|
||||
struct sctp_datamsg *msg;
|
||||
struct sctp_chunk *lchunk;
|
||||
struct sctp_stream *stream;
|
||||
__u16 ssn;
|
||||
__u16 sid;
|
||||
|
||||
if (chunk->has_ssn)
|
||||
return;
|
||||
|
||||
/* This is the last possible instant to assign a SSN. */
|
||||
if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
|
||||
ssn = 0;
|
||||
} else {
|
||||
sid = ntohs(chunk->subh.data_hdr->stream);
|
||||
if (chunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
|
||||
ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid);
|
||||
else
|
||||
ssn = sctp_ssn_peek(&chunk->asoc->ssnmap->out, sid);
|
||||
}
|
||||
/* All fragments will be on the same stream */
|
||||
sid = ntohs(chunk->subh.data_hdr->stream);
|
||||
stream = &chunk->asoc->ssnmap->out;
|
||||
|
||||
chunk->subh.data_hdr->ssn = htons(ssn);
|
||||
chunk->has_ssn = 1;
|
||||
/* Now assign the sequence number to the entire message.
|
||||
* All fragments must have the same stream sequence number.
|
||||
*/
|
||||
msg = chunk->msg;
|
||||
list_for_each_entry(lchunk, &msg->chunks, frag_list) {
|
||||
if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
|
||||
ssn = 0;
|
||||
} else {
|
||||
if (lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
|
||||
ssn = sctp_ssn_next(stream, sid);
|
||||
else
|
||||
ssn = sctp_ssn_peek(stream, sid);
|
||||
}
|
||||
|
||||
lchunk->subh.data_hdr->ssn = htons(ssn);
|
||||
lchunk->has_ssn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function to assign a TSN if needed. This assumes that both
|
||||
|
|
Loading…
Reference in New Issue