aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-08-02 16:51:42 -0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2007-08-29 13:34:34 -0400
commitab3e5e7b65dde661f5eb86b445496c5967283333 (patch)
treec371de81c5b7de518360ba0af337627e21d43d24 /net/sctp
parentea2dfb3733d53ac98b17756435d1f99e25490357 (diff)
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>
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/sm_make_chunk.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 51c4d7fef1d2..2b1129a7a94a 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1174,25 +1174,36 @@ out:
1174 */ 1174 */
1175void sctp_chunk_assign_ssn(struct sctp_chunk *chunk) 1175void sctp_chunk_assign_ssn(struct sctp_chunk *chunk)
1176{ 1176{
1177 struct sctp_datamsg *msg;
1178 struct sctp_chunk *lchunk;
1179 struct sctp_stream *stream;
1177 __u16 ssn; 1180 __u16 ssn;
1178 __u16 sid; 1181 __u16 sid;
1179 1182
1180 if (chunk->has_ssn) 1183 if (chunk->has_ssn)
1181 return; 1184 return;
1182 1185
1183 /* This is the last possible instant to assign a SSN. */ 1186 /* All fragments will be on the same stream */
1184 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { 1187 sid = ntohs(chunk->subh.data_hdr->stream);
1185 ssn = 0; 1188 stream = &chunk->asoc->ssnmap->out;
1186 } else {
1187 sid = ntohs(chunk->subh.data_hdr->stream);
1188 if (chunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
1189 ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid);
1190 else
1191 ssn = sctp_ssn_peek(&chunk->asoc->ssnmap->out, sid);
1192 }
1193 1189
1194 chunk->subh.data_hdr->ssn = htons(ssn); 1190 /* Now assign the sequence number to the entire message.
1195 chunk->has_ssn = 1; 1191 * All fragments must have the same stream sequence number.
1192 */
1193 msg = chunk->msg;
1194 list_for_each_entry(lchunk, &msg->chunks, frag_list) {
1195 if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
1196 ssn = 0;
1197 } else {
1198 if (lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
1199 ssn = sctp_ssn_next(stream, sid);
1200 else
1201 ssn = sctp_ssn_peek(stream, sid);
1202 }
1203
1204 lchunk->subh.data_hdr->ssn = htons(ssn);
1205 lchunk->has_ssn = 1;
1206 }
1196} 1207}
1197 1208
1198/* Helper function to assign a TSN if needed. This assumes that both 1209/* Helper function to assign a TSN if needed. This assumes that both