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:
parent
40b0d2c4e5
commit
e091a23d8b
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user