Commit ab3e5e7b authored by Vlad Yasevich's avatar Vlad Yasevich

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: default avatarVlad Yasevich <vladislav.yasevich@hp.com>
parent ea2dfb37
...@@ -1174,25 +1174,36 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len, ...@@ -1174,25 +1174,36 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
*/ */
void sctp_chunk_assign_ssn(struct sctp_chunk *chunk) void sctp_chunk_assign_ssn(struct sctp_chunk *chunk)
{ {
struct sctp_datamsg *msg;
struct sctp_chunk *lchunk;
struct sctp_stream *stream;
__u16 ssn; __u16 ssn;
__u16 sid; __u16 sid;
if (chunk->has_ssn) if (chunk->has_ssn)
return; return;
/* This is the last possible instant to assign a SSN. */ /* All fragments will be on the same stream */
if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { sid = ntohs(chunk->subh.data_hdr->stream);
ssn = 0; stream = &chunk->asoc->ssnmap->out;
} 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);
}
chunk->subh.data_hdr->ssn = htons(ssn); /* Now assign the sequence number to the entire message.
chunk->has_ssn = 1; * 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 /* Helper function to assign a TSN if needed. This assumes that both
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment