summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_indata.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctp_indata.c')
-rw-r--r--sys/netinet/sctp_indata.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 7a2f42c..357a047 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -753,7 +753,7 @@ sctp_handle_old_data(struct sctp_tcb *stcb, struct sctp_association *asoc, struc
*/
struct sctp_tmit_chunk *chk, *lchk, *tchk;
uint32_t fsn;
- struct sctp_queued_to_read *nc = NULL;
+ struct sctp_queued_to_read *nc;
int cnt_added;
if (control->first_frag_seen == 0) {
@@ -768,6 +768,11 @@ restart:
TAILQ_FOREACH_SAFE(chk, &control->reasm, sctp_next, lchk) {
if (chk->rec.data.fsn_num == fsn) {
/* Ok lets add it */
+ sctp_alloc_a_readq(stcb, nc);
+ if (nc == NULL) {
+ break;
+ }
+ memset(nc, 0, sizeof(struct sctp_queued_to_read));
TAILQ_REMOVE(&control->reasm, chk, sctp_next);
sctp_add_chk_to_control(control, strm, stcb, asoc, chk);
fsn++;
@@ -781,7 +786,6 @@ restart:
* on the control queue to a new
* control.
*/
- sctp_alloc_a_readq(stcb, nc);
sctp_build_readq_entry_from_ctl(nc, control);
tchk = TAILQ_FIRST(&control->reasm);
if (tchk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) {
@@ -819,6 +823,7 @@ restart:
if (control->on_strm_q) {
TAILQ_REMOVE(&strm->uno_inqueue, control, next_instrm);
control->on_strm_q = 0;
+ SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
}
if (control->on_read_q == 0) {
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
@@ -826,16 +831,19 @@ restart:
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
}
sctp_wakeup_the_read_socket(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
- if ((nc) && (nc->first_frag_seen)) {
+ if ((nc->first_frag_seen) && !TAILQ_EMPTY(&nc->reasm)) {
/*
* Switch to the new guy and
* continue
*/
control = nc;
- nc = NULL;
goto restart;
+ } else {
+ sctp_free_a_readq(stcb, nc);
}
return (1);
+ } else {
+ sctp_free_a_readq(stcb, nc);
}
} else {
/* Can't add more */
@@ -961,11 +969,6 @@ place_chunk:
* should not happen since the FSN is a TSN and it
* should have been dropped earlier.
*/
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
- sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
sctp_abort_in_reasm(stcb, control, chk,
abort_flag,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_5);
@@ -1026,6 +1029,7 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc, s
control, control->on_strm_q);
}
#endif
+ SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
TAILQ_REMOVE(&strm->uno_inqueue, control, next_instrm);
control->on_strm_q = 0;
}
@@ -1080,6 +1084,7 @@ done_un:
control, control->on_strm_q);
}
#endif
+ SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
control->on_strm_q = 0;
}
@@ -1125,6 +1130,7 @@ deliver_more:
control, control->on_strm_q);
}
#endif
+ SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
control->on_strm_q = 0;
}
@@ -5277,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;
@@ -5295,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;
@@ -5427,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;
@@ -5452,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),
@@ -5462,6 +5476,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
}
stream = ntohs(stseq->stream);
sequence = (uint32_t) ntohs(stseq->sequence);
+ ordered = 1;
}
/* Convert */
@@ -5487,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)) {
OpenPOWER on IntegriCloud