summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctputil.c
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2016-04-07 09:10:34 +0000
committerrrs <rrs@FreeBSD.org>2016-04-07 09:10:34 +0000
commit28010098ff581463a55af664c04cb7e237c28156 (patch)
tree1397194d23ebe0e55e3ff4a7bb2efaefc689843c /sys/netinet/sctputil.c
parent50189484f0e997ff7e620cf0a89c1ebae481e8ec (diff)
downloadFreeBSD-src-28010098ff581463a55af664c04cb7e237c28156.zip
FreeBSD-src-28010098ff581463a55af664c04cb7e237c28156.tar.gz
This is work done by Michael Tuexen and myself at the IETF. This
adds the new I-Data (Interleaved Data) message. This allows a user to be able to have complete freedom from Head Of Line blocking that was previously there due to the in-ability to send multiple large messages without the TSN's being in sequence. The code as been tested with Michaels various packet drill scripts as well as inter-networking between the IETF's location in Argentina and Germany.
Diffstat (limited to 'sys/netinet/sctputil.c')
-rw-r--r--sys/netinet/sctputil.c116
1 files changed, 60 insertions, 56 deletions
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 9434f06..87aa519 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -970,11 +970,13 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
asoc->ecn_supported = inp->ecn_supported;
asoc->prsctp_supported = inp->prsctp_supported;
+ asoc->idata_supported = inp->idata_supported;
asoc->auth_supported = inp->auth_supported;
asoc->asconf_supported = inp->asconf_supported;
asoc->reconfig_supported = inp->reconfig_supported;
asoc->nrsack_supported = inp->nrsack_supported;
asoc->pktdrop_supported = inp->pktdrop_supported;
+ asoc->idata_supported = inp->idata_supported;
asoc->sctp_cmt_pf = (uint8_t) 0;
asoc->sctp_frag_point = inp->sctp_frag_point;
asoc->sctp_features = inp->sctp_features;
@@ -1163,7 +1165,6 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
TAILQ_INIT(&asoc->asconf_send_queue);
TAILQ_INIT(&asoc->send_queue);
TAILQ_INIT(&asoc->sent_queue);
- TAILQ_INIT(&asoc->reasmqueue);
TAILQ_INIT(&asoc->resetHead);
asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome;
TAILQ_INIT(&asoc->asconf_queue);
@@ -2736,6 +2737,9 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
if (stcb->asoc.asconf_supported == 1) {
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
}
+ if (stcb->asoc.idata_supported == 1) {
+ sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_INTERLEAVING;
+ }
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
if (stcb->asoc.reconfig_supported == 1) {
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
@@ -4450,6 +4454,43 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
}
void
+sctp_wakeup_the_read_socket(struct sctp_inpcb *inp)
+{
+ if (inp && inp->sctp_socket) {
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
+ SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
+ } else {
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ struct socket *so;
+
+ so = SCTP_INP_SO(inp);
+ if (!so_locked) {
+ if (stcb) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_SOCKET_LOCK(so, 1);
+ if (stcb) {
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ }
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
+ SCTP_SOCKET_UNLOCK(so, 1);
+ return;
+ }
+ }
+#endif
+ sctp_sorwakeup(inp, inp->sctp_socket);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if (!so_locked) {
+ SCTP_SOCKET_UNLOCK(so, 1);
+ }
+#endif
+ }
+ }
+}
+
+void
sctp_add_to_readq(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_queued_to_read *control,
@@ -4484,7 +4525,7 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
sctp_m_freem(control->data);
control->data = NULL;
}
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
+ sctp_free_a_readq(stcb, control);
if (inp_read_lock_held == 0)
SCTP_INP_READ_UNLOCK(inp);
return;
@@ -4530,7 +4571,7 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
} else {
/* Everything got collapsed out?? */
sctp_free_remote_addr(control->whoFrom);
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
+ sctp_free_a_readq(stcb, control);
if (inp_read_lock_held == 0)
SCTP_INP_READ_UNLOCK(inp);
return;
@@ -4539,39 +4580,11 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
control->end_added = 1;
}
TAILQ_INSERT_TAIL(&inp->read_queue, control, next);
+ control->on_read_q = 1;
if (inp_read_lock_held == 0)
SCTP_INP_READ_UNLOCK(inp);
if (inp && inp->sctp_socket) {
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
- SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
- } else {
-#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- struct socket *so;
-
- so = SCTP_INP_SO(inp);
- if (!so_locked) {
- if (stcb) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- }
- SCTP_SOCKET_LOCK(so, 1);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- }
- if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
- SCTP_SOCKET_UNLOCK(so, 1);
- return;
- }
- }
-#endif
- sctp_sorwakeup(inp, inp->sctp_socket);
-#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if (!so_locked) {
- SCTP_SOCKET_UNLOCK(so, 1);
- }
-#endif
- }
+ sctp_wakeup_the_read_socket(inp);
}
}
@@ -5552,6 +5565,10 @@ restart_nosblocks:
sctp_m_free(control->aux_data);
control->aux_data = NULL;
}
+ if (control->on_strm_q) {
+ panic("About to free ctl:%p so:%p and its in %d",
+ control, so, control->on_strm_q);
+ }
sctp_free_remote_addr(control->whoFrom);
sctp_free_a_readq(stcb, control);
if (hold_rlock) {
@@ -5822,15 +5839,8 @@ get_more_data:
/* error we are out of here */
goto release;
}
- if ((SCTP_BUF_NEXT(m) == NULL) &&
- (cp_len >= SCTP_BUF_LEN(m)) &&
- ((control->end_added == 0) ||
- (control->end_added &&
- (TAILQ_NEXT(control, next) == NULL)))
- ) {
- SCTP_INP_READ_LOCK(inp);
- hold_rlock = 1;
- }
+ SCTP_INP_READ_LOCK(inp);
+ hold_rlock = 1;
if (cp_len == SCTP_BUF_LEN(m)) {
if ((SCTP_BUF_NEXT(m) == NULL) &&
(control->end_added)) {
@@ -5948,19 +5958,9 @@ get_more_data:
#endif
}
done_with_control:
- if (TAILQ_NEXT(control, next) == NULL) {
- /*
- * If we don't have a next we need a
- * lock, if there is a next
- * interrupt is filling ahead of us
- * and we don't need a lock to
- * remove this guy (which is the
- * head of the queue).
- */
- if (hold_rlock == 0) {
- SCTP_INP_READ_LOCK(inp);
- hold_rlock = 1;
- }
+ if (hold_rlock == 0) {
+ SCTP_INP_READ_LOCK(inp);
+ hold_rlock = 1;
}
TAILQ_REMOVE(&inp->read_queue, control, next);
/* Add back any hiddend data */
@@ -5976,6 +5976,10 @@ get_more_data:
no_rcv_needed = control->do_not_ref_stcb;
sctp_free_remote_addr(control->whoFrom);
control->data = NULL;
+ if (control->on_strm_q) {
+ panic("About to free ctl:%p so:%p and its in %d",
+ control, so, control->on_strm_q);
+ }
sctp_free_a_readq(stcb, control);
control = NULL;
if ((freed_so_far >= rwnd_req) &&
@@ -6096,7 +6100,7 @@ wait_some_more:
* corrupt?
*/
#ifdef INVARIANTS
- panic("Impossible data==NULL length !=0");
+ panic("Impossible data==NULL length !=0 control:%p stcb:%p length:%d", control, stcb, control->length);
#endif
out_flags |= MSG_EOR;
out_flags |= MSG_TRUNC;
OpenPOWER on IntegriCloud