Use a separate MID counter for ordered und unordered messages for each

outgoing stream.

Thanks to Jens Hoelscher for reporting the issue.

MFC after: 1 week
This commit is contained in:
tuexen 2016-06-08 17:57:42 +00:00
parent 40b0d2c4e5
commit e091a23d8b
4 changed files with 70 additions and 24 deletions

View File

@ -1969,7 +1969,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
asoc->strmout[i].abandoned_unsent[0] = 0;
#endif
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].next_sequence_send = 0;
stcb->asoc.strmout[i].next_mid_ordered = 0;
stcb->asoc.strmout[i].next_mid_unordered = 0;
stcb->asoc.strmout[i].last_msg_incomplete = 0;
}
/* process the INIT-ACK info (my info) */
@ -3521,11 +3522,13 @@ sctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t
/* no such stream */
continue;
}
stcb->asoc.strmout[temp].next_sequence_send = 0;
stcb->asoc.strmout[temp].next_mid_ordered = 0;
stcb->asoc.strmout[temp].next_mid_unordered = 0;
}
} else {
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
stcb->asoc.strmout[i].next_sequence_send = 0;
stcb->asoc.strmout[i].next_mid_ordered = 0;
stcb->asoc.strmout[i].next_mid_unordered = 0;
}
}
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);

View File

@ -3643,7 +3643,8 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
stcb->asoc.strmout[i].chunks_on_queues = 0;
stcb->asoc.strmout[i].next_sequence_send = 0;
stcb->asoc.strmout[i].next_mid_ordered = 0;
stcb->asoc.strmout[i].next_mid_unordered = 0;
#if defined(SCTP_DETAILED_STR_STATS)
for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
stcb->asoc.strmout[i].abandoned_sent[j] = 0;
@ -6381,7 +6382,6 @@ sctp_msg_append(struct sctp_tcb *stcb,
sp->ppid = srcv->sinfo_ppid;
sp->context = srcv->sinfo_context;
sp->fsn = 0;
sp->msg_id = atomic_fetchadd_int(&stcb->asoc.assoc_msg_id, 1);
if (sp->sinfo_flags & SCTP_ADDR_OVER) {
sp->net = net;
atomic_add_int(&sp->net->ref_count, 1);
@ -7568,10 +7568,28 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
chk->asoc = &stcb->asoc;
chk->pad_inplace = 0;
chk->no_fr_allowed = 0;
chk->rec.data.stream_seq = strq->next_sequence_send;
if ((rcv_flags & SCTP_DATA_LAST_FRAG) &&
!(rcv_flags & SCTP_DATA_UNORDERED)) {
strq->next_sequence_send++;
if (stcb->asoc.idata_supported == 0) {
if (rcv_flags & SCTP_DATA_UNORDERED) {
/* Just use 0. The receiver ignores the values. */
chk->rec.data.stream_seq = 0;
} else {
chk->rec.data.stream_seq = strq->next_mid_ordered;
if (rcv_flags & SCTP_DATA_LAST_FRAG) {
strq->next_mid_ordered++;
}
}
} else {
if (rcv_flags & SCTP_DATA_UNORDERED) {
chk->rec.data.stream_seq = strq->next_mid_unordered;
if (rcv_flags & SCTP_DATA_LAST_FRAG) {
strq->next_mid_unordered++;
}
} else {
chk->rec.data.stream_seq = strq->next_mid_ordered;
if (rcv_flags & SCTP_DATA_LAST_FRAG) {
strq->next_mid_ordered++;
}
}
}
chk->rec.data.stream_number = sp->stream;
chk->rec.data.payloadtype = sp->ppid;
@ -7630,7 +7648,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
dchkh->ch.chunk_flags = chk->rec.data.rcv_flags;
dchkh->dp.tsn = htonl(chk->rec.data.TSN_seq);
dchkh->dp.stream_id = htons((strq->stream_no & 0x0000ffff));
dchkh->dp.stream_sequence = htons(chk->rec.data.stream_seq);
dchkh->dp.stream_sequence = htons((uint16_t) chk->rec.data.stream_seq);
dchkh->dp.protocol_id = chk->rec.data.payloadtype;
dchkh->ch.chunk_length = htons(chk->send_size);
} else {
@ -7638,9 +7656,8 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
ndchkh->ch.chunk_flags = chk->rec.data.rcv_flags;
ndchkh->dp.tsn = htonl(chk->rec.data.TSN_seq);
ndchkh->dp.stream_id = htons(strq->stream_no);
/* WHAT DO WE DO HERE??? */
ndchkh->dp.reserved = htons(0);
ndchkh->dp.msg_id = htonl(sp->msg_id);
ndchkh->dp.msg_id = htonl(chk->rec.data.stream_seq);
if (sp->fsn == 0)
ndchkh->dp.ppid_fsn.protocol_id = chk->rec.data.payloadtype;
else
@ -12235,7 +12252,8 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
stcb->asoc.strmout[i].chunks_on_queues = oldstream[i].chunks_on_queues;
stcb->asoc.strmout[i].next_sequence_send = oldstream[i].next_sequence_send;
stcb->asoc.strmout[i].next_mid_ordered = oldstream[i].next_mid_ordered;
stcb->asoc.strmout[i].next_mid_unordered = oldstream[i].next_mid_unordered;
stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete;
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].state = oldstream[i].state;
@ -12267,7 +12285,8 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
stcb->asoc.strmout[i].abandoned_sent[0] = 0;
stcb->asoc.strmout[i].abandoned_unsent[0] = 0;
#endif
stcb->asoc.strmout[i].next_sequence_send = 0x0;
stcb->asoc.strmout[i].next_mid_ordered = 0;
stcb->asoc.strmout[i].next_mid_unordered = 0;
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].last_msg_incomplete = 0;
stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
@ -12425,7 +12444,6 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
sp->ppid = srcv->sinfo_ppid;
sp->context = srcv->sinfo_context;
sp->fsn = 0;
sp->msg_id = atomic_fetchadd_int(&stcb->asoc.assoc_msg_id, 1);
(void)SCTP_GETTIME_TIMEVAL(&sp->ts);
sp->stream = srcv->sinfo_stream;

View File

@ -522,7 +522,6 @@ struct sctp_stream_queue_pending {
TAILQ_ENTRY(sctp_stream_queue_pending) next;
TAILQ_ENTRY(sctp_stream_queue_pending) ss_next;
uint32_t fsn;
uint32_t msg_id;
uint32_t length;
uint32_t timetolive;
uint32_t ppid;
@ -619,7 +618,12 @@ struct sctp_stream_out {
uint32_t abandoned_unsent[1];
uint32_t abandoned_sent[1];
#endif
uint32_t next_sequence_send; /* next one I expect to send out */
/*
* For associations using DATA chunks, the lower 16-bit of
* next_mid_ordered are used as the next SSN.
*/
uint32_t next_mid_ordered;
uint32_t next_mid_unordered;
uint16_t stream_no;
uint8_t last_msg_incomplete;
uint8_t state;
@ -893,7 +897,6 @@ struct sctp_association {
uint32_t stream_scheduling_module;
uint32_t vrf_id;
uint32_t assoc_msg_id;
uint32_t cookie_preserve_req;
/* ASCONF next seq I am sending out, inits at init-tsn */
uint32_t asconf_seq_out;

View File

@ -1123,7 +1123,8 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* that were dropped must be notified to the upper layer as
* failed to send.
*/
asoc->strmout[i].next_sequence_send = 0x0;
asoc->strmout[i].next_mid_ordered = 0;
asoc->strmout[i].next_mid_unordered = 0;
TAILQ_INIT(&asoc->strmout[i].outqueue);
asoc->strmout[i].chunks_on_queues = 0;
#if defined(SCTP_DETAILED_STR_STATS)
@ -4836,10 +4837,22 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
goto oh_well;
}
memset(chk, 0, sizeof(*chk));
chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG;
chk->rec.data.rcv_flags = 0;
chk->sent = SCTP_FORWARD_TSN_SKIP;
chk->asoc = &stcb->asoc;
chk->rec.data.stream_seq = strq->next_sequence_send;
if (stcb->asoc.idata_supported == 0) {
if (sp->sinfo_flags & SCTP_UNORDERED) {
chk->rec.data.stream_seq = 0;
} else {
chk->rec.data.stream_seq = strq->next_mid_ordered;
}
} else {
if (sp->sinfo_flags & SCTP_UNORDERED) {
chk->rec.data.stream_seq = strq->next_mid_unordered;
} else {
chk->rec.data.stream_seq = strq->next_mid_ordered;
}
}
chk->rec.data.stream_number = sp->stream;
chk->rec.data.payloadtype = sp->ppid;
chk->rec.data.context = sp->context;
@ -4850,10 +4863,19 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
stcb->asoc.sent_queue_cnt++;
stcb->asoc.pr_sctp_cnt++;
} else {
chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
}
strq->next_sequence_send++;
chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
if (stcb->asoc.idata_supported == 0) {
if ((sp->sinfo_flags & SCTP_UNORDERED) == 0) {
strq->next_mid_ordered++;
}
} else {
if (sp->sinfo_flags & SCTP_UNORDERED) {
strq->next_mid_unordered++;
} else {
strq->next_mid_ordered++;
}
}
oh_well:
if (sp->data) {
/*