summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctputil.c
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2016-08-11 10:14:03 +0000
committertuexen <tuexen@FreeBSD.org>2016-08-11 10:14:03 +0000
commit493f2f7fa067c0510b3050e4ac71d4fa6628b80d (patch)
tree1144c0b65740a7f9283b2f043b8ff9f4b9b2c2c7 /sys/netinet/sctputil.c
parent81d25dd54fcac16c33b36e2ebe8e82c2a70c5986 (diff)
downloadFreeBSD-src-493f2f7fa067c0510b3050e4ac71d4fa6628b80d.zip
FreeBSD-src-493f2f7fa067c0510b3050e4ac71d4fa6628b80d.tar.gz
MFC r303792:
Fix various bugs in relation to the I-DATA chunk support This is joint work with rrs. MFC r303793: Mark an unused parameter as such. MFC r303798: Don't modify a structure without holding a reference count on it. MFC r303813: Remove stream queue entry consistently from wheel. While there, improve the handling of drain. MFC r303819: Consistently check for unsent data on the stream queues. MFC r303831: Fix a locking issue found by stress testing with tsctp. The inp read lock neeeds to be held when considering control->do_not_ref_stcb. MFC r303834: Fix the sending of FORWARD-TSN and I-FORWARD-TSN chunks. The last SID/SSN pair wasn't filled in. Thanks to Julian Cordes for providing a packetdrill script triggering the issue and making me aware of the bug. Approved by: re (kib)
Diffstat (limited to 'sys/netinet/sctputil.c')
-rw-r--r--sys/netinet/sctputil.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 15c2dd1..148b047 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1077,7 +1077,6 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->minrto = inp->sctp_ep.sctp_minrto;
asoc->maxrto = inp->sctp_ep.sctp_maxrto;
- asoc->locked_on_sending = NULL;
asoc->stream_locked_on = 0;
asoc->ecn_echo_cnt_onq = 0;
asoc->stream_locked = 0;
@@ -1139,7 +1138,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->strmout[i].stream_no = i;
asoc->strmout[i].last_msg_incomplete = 0;
asoc->strmout[i].state = SCTP_STREAM_OPENING;
- asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
+ asoc->ss_functions.sctp_ss_init_stream(stcb, &asoc->strmout[i], NULL);
}
asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
@@ -3907,10 +3906,10 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock,
/* For each stream */
outs = &asoc->strmout[i];
/* clean up any sends there */
- asoc->locked_on_sending = NULL;
TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
- asoc->stream_queue_cnt--;
+ atomic_subtract_int(&asoc->stream_queue_cnt, 1);
TAILQ_REMOVE(&outs->outqueue, sp, next);
+ stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, outs, sp, holds_lock);
sctp_free_spbufspace(stcb, asoc, sp);
if (sp->data) {
sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb,
@@ -4878,6 +4877,9 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
stcb->asoc.pr_sctp_cnt++;
}
chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
+ if (sp->sinfo_flags & SCTP_UNORDERED) {
+ chk->rec.data.rcv_flags |= SCTP_DATA_UNORDERED;
+ }
if (stcb->asoc.idata_supported == 0) {
if ((sp->sinfo_flags & SCTP_UNORDERED) == 0) {
strq->next_mid_ordered++;
@@ -5495,20 +5497,16 @@ restart_nosblocks:
}
/* Clear the held length since there is something to read */
control->held_length = 0;
- if (hold_rlock) {
- SCTP_INP_READ_UNLOCK(inp);
- hold_rlock = 0;
- }
found_one:
/*
* If we reach here, control has a some data for us to read off.
* Note that stcb COULD be NULL.
*/
- control->some_taken++;
- if (hold_sblock) {
- SOCKBUF_UNLOCK(&so->so_rcv);
- hold_sblock = 0;
+ if (hold_rlock == 0) {
+ hold_rlock = 1;
+ SCTP_INP_READ_LOCK(inp);
}
+ control->some_taken++;
stcb = control->stcb;
if (stcb) {
if ((control->do_not_ref_stcb == 0) &&
@@ -5682,6 +5680,14 @@ found_one:
}
#endif
}
+ if (hold_rlock) {
+ SCTP_INP_READ_UNLOCK(inp);
+ hold_rlock = 0;
+ }
+ if (hold_sblock) {
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ hold_sblock = 0;
+ }
/* now copy out what data we can */
if (mp == NULL) {
/* copy out each mbuf in the chain up to length */
@@ -6097,9 +6103,9 @@ out:
goto stage_left;
#endif
}
- atomic_add_int(&stcb->asoc.refcnt, -1);
/* Save the value back for next time */
stcb->freed_by_sorcv_sincelast = freed_so_far;
+ atomic_add_int(&stcb->asoc.refcnt, -1);
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
if (stcb) {
OpenPOWER on IntegriCloud