diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index f5ea529effca..c07019c965c6 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -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); diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 6d71f7d1e653..3544d6942ce0 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -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; diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index c64d2b6c4feb..ad9d9783a4ab 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -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; diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index cc18d9f05198..3f6ec551d480 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -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) { /*