Author: tuexen
Date: Wed Jun  8 17:57:42 2016
New Revision: 301666
URL: https://svnweb.freebsd.org/changeset/base/301666

Log:
  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

Modified:
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_output.c
  head/sys/netinet/sctp_structs.h
  head/sys/netinet/sctputil.c

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c       Wed Jun  8 17:51:21 2016        
(r301665)
+++ head/sys/netinet/sctp_input.c       Wed Jun  8 17:57:42 2016        
(r301666)
@@ -1969,7 +1969,8 @@ sctp_process_cookie_existing(struct mbuf
                        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 *
                                /* 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);

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c      Wed Jun  8 17:51:21 2016        
(r301665)
+++ head/sys/netinet/sctp_output.c      Wed Jun  8 17:57:42 2016        
(r301666)
@@ -3643,7 +3643,8 @@ sctp_process_cmsgs_for_init(struct sctp_
                                        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 @@ dont_do_it:
        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 @@ dont_do_it:
                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 @@ dont_do_it:
                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 
                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->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;

Modified: head/sys/netinet/sctp_structs.h
==============================================================================
--- head/sys/netinet/sctp_structs.h     Wed Jun  8 17:51:21 2016        
(r301665)
+++ head/sys/netinet/sctp_structs.h     Wed Jun  8 17:57:42 2016        
(r301666)
@@ -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;

Modified: head/sys/netinet/sctputil.c
==============================================================================
--- head/sys/netinet/sctputil.c Wed Jun  8 17:51:21 2016        (r301665)
+++ head/sys/netinet/sctputil.c Wed Jun  8 17:57:42 2016        (r301666)
@@ -1123,7 +1123,8 @@ sctp_init_asoc(struct sctp_inpcb *inp, s
                 * 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_t
                                        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_t
                                TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, 
sctp_next);
                                stcb->asoc.sent_queue_cnt++;
                                stcb->asoc.pr_sctp_cnt++;
+                       }
+                       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 {
-                               chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
+                               if (sp->sinfo_flags & SCTP_UNORDERED) {
+                                       strq->next_mid_unordered++;
+                               } else {
+                                       strq->next_mid_ordered++;
+                               }
                        }
-                       strq->next_sequence_send++;
        oh_well:
                        if (sp->data) {
                                /*
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to