From 8e1b295f09433385acabe355e24bba9bdd2bee20 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Sun, 17 Jul 2016 13:14:51 +0000 Subject: [PATCH] Fix the PR-SCTP behaviour. This is done by rrs@. MFC after: 3 days --- sys/netinet/sctp_constants.h | 1 + sys/netinet/sctp_header.h | 2 +- sys/netinet/sctp_indata.c | 15 ++++++++++++--- sys/netinet/sctp_output.c | 9 ++++++--- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h index a58c2060b2e8..ecde4fee544f 100644 --- a/sys/netinet/sctp_constants.h +++ b/sys/netinet/sctp_constants.h @@ -345,6 +345,7 @@ __FBSDID("$FreeBSD$"); #define SCTP_RTT_FROM_NON_DATA 0 #define SCTP_RTT_FROM_DATA 1 +#define PR_SCTP_UNORDERED_FLAG 0x0001 /* IP hdr (20/40) + 12+2+2 (enet) + sctp common 12 */ #define SCTP_FIRST_MBUF_RESV 68 diff --git a/sys/netinet/sctp_header.h b/sys/netinet/sctp_header.h index 850290d52f52..3f4948ddeb41 100644 --- a/sys/netinet/sctp_header.h +++ b/sys/netinet/sctp_header.h @@ -397,7 +397,7 @@ struct sctp_strseq { struct sctp_strseq_mid { uint16_t stream; - uint16_t reserved; + uint16_t flags; uint32_t msg_id; }; diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index f784c56acfb7..31b74c2eb594 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -5283,10 +5283,11 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, } } + static void sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb, struct sctp_association *asoc, - uint16_t stream, uint32_t seq) + uint16_t stream, uint32_t seq, int ordered, int old) { struct sctp_queued_to_read *control; struct sctp_stream_in *strm; @@ -5301,7 +5302,7 @@ sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb, * queue. */ strm = &asoc->strmin[stream]; - control = find_reasm_entry(strm, (uint32_t) seq, 0, 0); + control = find_reasm_entry(strm, (uint32_t) seq, ordered, old); if (control == NULL) { /* Not found */ return; @@ -5433,6 +5434,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, unsigned int num_str; uint32_t sequence; uint16_t stream; + uint16_t ordered, flags; int old; struct sctp_strseq *stseq, strseqbuf; struct sctp_strseq_mid *stseq_m, strseqbuf_m; @@ -5458,6 +5460,12 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, } stream = ntohs(stseq_m->stream); sequence = ntohl(stseq_m->msg_id); + flags = ntohs(stseq_m->flags); + if (flags & PR_SCTP_UNORDERED_FLAG) { + ordered = 0; + } else { + ordered = 1; + } } else { stseq = (struct sctp_strseq *)sctp_m_getptr(m, offset, sizeof(struct sctp_strseq), @@ -5468,6 +5476,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, } stream = ntohs(stseq->stream); sequence = (uint32_t) ntohs(stseq->sequence); + ordered = 1; } /* Convert */ @@ -5493,7 +5502,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, asoc->fragmented_delivery_inprogress = 0; } strm = &asoc->strmin[stream]; - sctp_flush_reassm_for_str_seq(stcb, asoc, stream, sequence); + sctp_flush_reassm_for_str_seq(stcb, asoc, stream, sequence, ordered, old); TAILQ_FOREACH(ctl, &stcb->sctp_ep->read_queue, next) { if ((ctl->sinfo_stream == stream) && (ctl->sinfo_ssn == sequence)) { diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index d8c3caef6ff4..078d5fd17c0b 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -10383,7 +10383,7 @@ send_forward_tsn(struct sctp_tcb *stcb, /* no more to look at */ break; } - if (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED) { + if ((at->rec.data.rcv_flags & SCTP_DATA_UNORDERED) && old) { /* We don't report these */ continue; } @@ -10504,7 +10504,7 @@ send_forward_tsn(struct sctp_tcb *stcb, tp1 = TAILQ_NEXT(at, sctp_next); if (tp1 == NULL) break; - if (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED) { + if (old && (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) { /* We don't report these */ i--; at = tp1; @@ -10519,8 +10519,11 @@ send_forward_tsn(struct sctp_tcb *stcb, strseq++; } else { strseq_m->stream = ntohs(at->rec.data.stream_number); - strseq_m->reserved = ntohs(0); strseq_m->msg_id = ntohl(at->rec.data.stream_seq); + if (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED) + strseq_m->flags = ntohs(PR_SCTP_UNORDERED_FLAG); + else + strseq_m->flags = 0; strseq_m++; } at = tp1;