summaryrefslogtreecommitdiff
path: root/sys/netinet/sctp_output.c
diff options
context:
space:
mode:
authorRandall Stewart <rrs@FreeBSD.org>2007-04-15 11:58:26 +0000
committerRandall Stewart <rrs@FreeBSD.org>2007-04-15 11:58:26 +0000
commit478d3f0901c589952363a6fb122fd9b893358818 (patch)
tree66b3a65021698d30bae86cfd4452df34a0c14ca2 /sys/netinet/sctp_output.c
parenta3859aa3860c9662bab4a958a5d3195e27f96d53 (diff)
downloadsrc-test2-478d3f0901c589952363a6fb122fd9b893358818.tar.gz
src-test2-478d3f0901c589952363a6fb122fd9b893358818.zip
Notes
Diffstat (limited to 'sys/netinet/sctp_output.c')
-rw-r--r--sys/netinet/sctp_output.c390
1 files changed, 171 insertions, 219 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index e417d02221f4..e1ee546baccd 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -3166,55 +3166,28 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
int how, int allonebuf, int type)
{
struct mbuf *m = NULL;
- int aloc_size;
- int index = 0;
- int mbuf_threshold;
- if (want_header) {
- MGETHDR(m, how, type);
- } else {
- MGET(m, how, type);
- }
- if (m == NULL) {
- return (NULL);
- }
- if (allonebuf == 0)
- mbuf_threshold = sctp_mbuf_threshold_count;
- else
- mbuf_threshold = 1;
-
-
- if (space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) {
-try_again:
- index = 4;
- if (space_needed <= MCLBYTES) {
- aloc_size = MCLBYTES;
- } else if (space_needed <= MJUMPAGESIZE) {
- aloc_size = MJUMPAGESIZE;
- index = 5;
- } else if (space_needed <= MJUM9BYTES) {
- aloc_size = MJUM9BYTES;
- index = 6;
+ m = m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0);
+ if (allonebuf) {
+ int siz;
+
+ if (SCTP_BUF_IS_EXTENDED(m)) {
+ siz = SCTP_BUF_EXTEND_SIZE(m);
} else {
- aloc_size = MJUM16BYTES;
- index = 7;
- }
- m_cljget(m, how, aloc_size);
- if (m == NULL) {
- return (NULL);
+ if (want_header)
+ siz = MHLEN;
+ else
+ siz = MLEN;
}
- if (SCTP_BUF_IS_EXTENDED(m) == 0) {
- if ((aloc_size != MCLBYTES) &&
- (allonebuf == 0)) {
- aloc_size -= 10;
- goto try_again;
- }
- sctp_m_freem(m);
+ if (siz < space_needed) {
+ m_freem(m);
return (NULL);
}
}
- SCTP_BUF_LEN(m) = 0;
- SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL;
+ if (SCTP_BUF_NEXT(m)) {
+ sctp_m_freem(SCTP_BUF_NEXT(m));
+ SCTP_BUF_NEXT(m) = NULL;
+ }
#ifdef SCTP_MBUF_LOGGING
if (SCTP_BUF_IS_EXTENDED(m)) {
sctp_log_mb(m, SCTP_MBUF_IALLOC);
@@ -5393,7 +5366,7 @@ sctp_msg_append(struct sctp_tcb *stcb,
error = ECONNRESET;
goto out_now;
}
- sp = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq, struct sctp_stream_queue_pending);
+ sctp_alloc_a_strmoq(stcb, sp);
if (sp == NULL) {
error = ENOMEM;
goto out_now;
@@ -5434,7 +5407,7 @@ sctp_msg_append(struct sctp_tcb *stcb,
}
SCTP_TCB_SEND_LOCK(stcb);
sctp_snd_sb_alloc(stcb, sp->length);
- stcb->asoc.stream_queue_cnt++;
+ atomic_add_int(&stcb->asoc.stream_queue_cnt, 1);
TAILQ_INSERT_TAIL(&strm->outqueue, sp, next);
if ((srcv->sinfo_flags & SCTP_UNORDERED) == 0) {
sp->strseq = strm->next_sequence_sent;
@@ -6098,47 +6071,43 @@ sctp_can_we_split_this(struct sctp_tcb *stcb,
{
/*
* Make a decision on if I should split a msg into multiple parts.
+ * This is only asked of incomplete messages.
*/
- if (goal_mtu < sctp_min_split_point) {
- /* you don't want enough */
- return (0);
- }
- if ((sp->length <= goal_mtu) || ((sp->length - goal_mtu) < sctp_min_residual)) {
- /* Sub-optimial residual don't split */
- return (0);
- }
- if (sp->msg_is_complete == 0) {
- if (eeor_on) {
- /*
- * If we are doing EEOR we need to always send it if
- * its the entire thing.
+ if (eeor_on) {
+ /*
+ * If we are doing EEOR we need to always send it if its the
+ * entire thing, since it might be all the guy is putting in
+ * the hopper.
+ */
+ if (goal_mtu >= sp->length) {
+ /*-
+ * If we have data outstanding,
+ * we get another chance when the sack
+ * arrives to transmit - wait for more data
+ *
+ * Could this be optimized to be aware of
+ * two packets?
+ *
*/
- if (goal_mtu >= sp->length)
+ if (stcb->asoc.total_flight > 0)
+ return (0);
+ else
return (sp->length);
} else {
- if (goal_mtu >= sp->length) {
- /*
- * If we cannot fill the amount needed there
- * is no sense of splitting the chunk.
- */
- return (0);
- }
+ /* You can fill the rest */
+ return (goal_mtu);
}
- /*
- * If we reach here sp->length is larger than the goal_mtu.
- * Do we wish to split it for the sake of packet putting
- * together?
- */
- if (goal_mtu >= min(sctp_min_split_point, stcb->asoc.smallest_mtu)) {
- /* Its ok to split it */
- return (min(goal_mtu, frag_point));
- }
- } else {
- /* We can always split a complete message to make it fit */
- if (goal_mtu >= sp->length)
- /* Take it all */
- return (sp->length);
-
+ }
+ if ((sp->length <= goal_mtu) || ((sp->length - goal_mtu) < sctp_min_residual)) {
+ /* Sub-optimial residual don't split in non-eeor mode. */
+ return (0);
+ }
+ /*
+ * If we reach here sp->length is larger than the goal_mtu. Do we
+ * wish to split it for the sake of packet putting together?
+ */
+ if (goal_mtu >= min(sctp_min_split_point, frag_point)) {
+ /* Its ok to split it */
return (min(goal_mtu, frag_point));
}
/* Nope, can't split */
@@ -6164,13 +6133,20 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
uint8_t rcv_flags = 0;
uint8_t some_taken;
uint8_t took_all = 0;
+ uint8_t send_lock_up = 0;
SCTP_TCB_LOCK_ASSERT(stcb);
asoc = &stcb->asoc;
+one_more_time:
sp = TAILQ_FIRST(&strq->outqueue);
if (sp == NULL) {
*locked = 0;
SCTP_TCB_SEND_LOCK(stcb);
+ sp = TAILQ_FIRST(&strq->outqueue);
+ if (sp) {
+ SCTP_TCB_SEND_UNLOCK(stcb);
+ goto one_more_time;
+ }
if (strq->last_msg_incomplete) {
printf("Huh? Stream:%d lm_in_c=%d but queue is NULL\n",
strq->stream_no, strq->last_msg_incomplete);
@@ -6179,16 +6155,52 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
SCTP_TCB_SEND_UNLOCK(stcb);
return (0);
}
- SCTP_TCB_SEND_LOCK(stcb);
- if ((sp->length == 0) && (sp->msg_is_complete == 0)) {
- /* Must wait for more data, must be last msg */
- *locked = 1;
- *giveup = 1;
- SCTP_TCB_SEND_UNLOCK(stcb);
- return (0);
- } else if (sp->length == 0) {
- /* This should not happen */
- panic("sp length is 0?");
+ if (sp->msg_is_complete) {
+ if (sp->length == 0) {
+ if (sp->sender_all_done) {
+ /*
+ * We are doing deffered cleanup. Last time
+ * through when we took all the data the
+ * sender_all_done was not set.
+ */
+ SCTP_TCB_SEND_LOCK(stcb);
+ send_lock_up = 1;
+ atomic_subtract_int(&asoc->stream_queue_cnt, 1);
+ TAILQ_REMOVE(&strq->outqueue, sp, next);
+ sctp_free_remote_addr(sp->net);
+ if (sp->data) {
+ sctp_m_freem(sp->data);
+ sp->data = NULL;
+ }
+ sctp_free_a_strmoq(stcb, sp);
+
+ /* we can't be locked to it */
+ *locked = 0;
+ stcb->asoc.locked_on_sending = NULL;
+ if (send_lock_up) {
+ SCTP_TCB_SEND_UNLOCK(stcb);
+ send_lock_up = 0;
+ }
+ /* back to get the next msg */
+ goto one_more_time;
+ } else {
+ /*
+ * sender just finished this but still holds
+ * a reference
+ */
+ *locked = 1;
+ *giveup = 1;
+ return (0);
+ }
+ }
+ } else {
+ /* is there some to get */
+ if (sp->length == 0) {
+ /* no */
+ *locked = 1;
+ *giveup = 1;
+ return (0);
+ }
}
some_taken = sp->some_taken;
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
@@ -6227,16 +6239,19 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
*locked = 1;
}
*giveup = 1;
- SCTP_TCB_SEND_UNLOCK(stcb);
return (0);
}
}
- SCTP_TCB_SEND_UNLOCK(stcb);
+
/* If we reach here, we can copy out a chunk */
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
/* No chunk memory */
out_gu:
+ if (send_lock_up) {
+ SCTP_TCB_SEND_UNLOCK(stcb);
+ send_lock_up = 0;
+ }
*giveup = 1;
return (0);
}
@@ -6250,12 +6265,19 @@ out_gu:
/* clear out the chunk before setting up */
memset(chk, sizeof(*chk), 0);
chk->rec.data.rcv_flags = rcv_flags;
- SCTP_TCB_SEND_LOCK(stcb);
if (SCTP_BUF_IS_EXTENDED(sp->data)) {
chk->copy_by_ref = 1;
} else {
chk->copy_by_ref = 0;
}
+ if ((sp->msg_is_complete == 0) &&
+ (to_move >= sp->length)) {
+ SCTP_TCB_SEND_LOCK(stcb);
+ send_lock_up = 1;
+ } else {
+ send_lock_up = 0;
+ }
+
if (to_move >= sp->length) {
/* we can steal the whole thing */
chk->data = sp->data;
@@ -6271,7 +6293,6 @@ out_gu:
if (chk->data == NULL) {
sp->some_taken = some_taken;
sctp_free_a_chunk(stcb, chk);
- SCTP_TCB_SEND_UNLOCK(stcb);
goto out_gu;
}
/* Pull off the data */
@@ -6283,6 +6304,7 @@ out_gu:
SCTP_BUF_NEXT(m) = NULL;
if (sp->tail_mbuf == m) {
/* freeing tail */
+ printf("Huh, freeing tail? - TSNH\n");
sp->tail_mbuf = sp->data;
}
sctp_m_free(m);
@@ -6292,9 +6314,8 @@ out_gu:
if (to_move > sp->length) {
panic("Huh, how can to_move be larger?");
} else {
- sp->length -= to_move;
+ atomic_subtract_int(&sp->length, to_move);
}
-
if (M_LEADINGSPACE(chk->data) < sizeof(struct sctp_data_chunk)) {
/* Not enough room for a chunk header, get some */
struct mbuf *m;
@@ -6306,6 +6327,10 @@ out_gu:
* all the data if there is no leading space, so we
* must put the data back and restore.
*/
+ if (send_lock_up == 0) {
+ SCTP_TCB_SEND_LOCK(stcb);
+ send_lock_up = 1;
+ }
if (took_all) {
/* unsteal the data */
sp->data = chk->data;
@@ -6322,7 +6347,6 @@ out_gu:
sp->length += to_move;
chk->data = NULL;
sctp_free_a_chunk(stcb, chk);
- SCTP_TCB_SEND_UNLOCK(stcb);
goto out_gu;
} else {
SCTP_BUF_LEN(m) = 0;
@@ -6334,8 +6358,8 @@ out_gu:
SCTP_BUF_PREPEND(chk->data, sizeof(struct sctp_data_chunk), M_DONTWAIT);
if (chk->data == NULL) {
/* HELP */
+ printf("prepend fails HELP?\n");
sctp_free_a_chunk(stcb, chk);
- SCTP_TCB_SEND_UNLOCK(stcb);
goto out_gu;
}
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
@@ -6423,9 +6447,13 @@ out_gu:
if (sp->pr_sctp_on) {
sctp_set_prsctp_policy(stcb, sp);
}
- if (sp->msg_is_complete && (sp->length == 0)) {
+ if (sp->msg_is_complete && (sp->length == 0) && (sp->sender_all_done)) {
/* All done pull and kill the message */
- asoc->stream_queue_cnt--;
+ atomic_subtract_int(&asoc->stream_queue_cnt, 1);
+ if (send_lock_up == 0) {
+ SCTP_TCB_SEND_LOCK(stcb);
+ send_lock_up = 1;
+ }
TAILQ_REMOVE(&strq->outqueue, sp, next);
sctp_free_remote_addr(sp->net);
if (sp->data) {
@@ -6450,7 +6478,10 @@ out_gu:
}
TAILQ_INSERT_TAIL(&asoc->send_queue, chk, sctp_next);
asoc->send_queue_cnt++;
- SCTP_TCB_SEND_UNLOCK(stcb);
+ if (send_lock_up) {
+ SCTP_TCB_SEND_UNLOCK(stcb);
+ send_lock_up = 0;
+ }
return (to_move);
}
@@ -7009,8 +7040,8 @@ again_one_more_time:
no_fragmentflg, 0, NULL, asconf))) {
if (error == ENOBUFS) {
asoc->ifp_had_enobuf = 1;
+ SCTP_STAT_INCR(sctps_lowlevelerr);
}
- SCTP_STAT_INCR(sctps_lowlevelerr);
if (from_where == 0) {
SCTP_STAT_INCR(sctps_lowlevelerrusr);
}
@@ -7279,9 +7310,9 @@ again_one_more_time:
asconf))) {
/* error, we could not output */
if (error == ENOBUFS) {
+ SCTP_STAT_INCR(sctps_lowlevelerr);
asoc->ifp_had_enobuf = 1;
}
- SCTP_STAT_INCR(sctps_lowlevelerr);
if (from_where == 0) {
SCTP_STAT_INCR(sctps_lowlevelerrusr);
}
@@ -10317,13 +10348,8 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp,
uint32_t * sndout,
struct mbuf **new_tail)
{
-
-/*#if defined(__FreeBSD__) && __FreeBSD_version >= 602000*/
-#if defined(_NOT_YET_)
-
struct mbuf *m;
-/* take out max_hdr */
m = m_uiotombuf(uio, M_WAITOK, max_send_len, 0,
(M_PKTHDR | (user_marks_eor ? M_EOR : 0)));
if (m == NULL)
@@ -10332,55 +10358,6 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp,
*sndout = m_length(m, NULL);
*new_tail = m_last(m);
return (m);
-#else
- int left, cancpy, willcpy;
- struct mbuf *m, *prev, *head;
-
- left = min(uio->uio_resid, max_send_len);
- /* Always get a header just in case */
- head = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 0, MT_DATA);
- cancpy = M_TRAILINGSPACE(head);
- willcpy = min(cancpy, left);
- *error = uiomove(mtod(head, caddr_t), willcpy, uio);
- if (*error) {
- sctp_m_freem(head);
- return (NULL);
- }
- *sndout += willcpy;
- left -= willcpy;
- SCTP_BUF_LEN(head) = willcpy;
- m = head;
- *new_tail = head;
- while (left > 0) {
- /* move in user data */
- SCTP_BUF_NEXT(m) = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 0, MT_DATA);
- if (SCTP_BUF_NEXT(m) == NULL) {
- sctp_m_freem(head);
- *new_tail = NULL;
- *error = ENOMEM;
- return (NULL);
- }
- prev = m;
- m = SCTP_BUF_NEXT(m);
- cancpy = M_TRAILINGSPACE(m);
- willcpy = min(cancpy, left);
- *error = uiomove(mtod(m, caddr_t), willcpy, uio);
- if (*error) {
- sctp_m_freem(head);
- *new_tail = NULL;
- *error = EFAULT;
- return (NULL);
- }
- SCTP_BUF_LEN(m) = willcpy;
- left -= willcpy;
- *sndout += willcpy;
- *new_tail = m;
- if (left == 0) {
- SCTP_BUF_NEXT(m) = NULL;
- }
- }
- return (head);
-#endif
}
static int
@@ -10390,65 +10367,14 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp,
{
int left;
-/*#if defined(__FreeBSD__) && __FreeBSD_version >= 602000*/
-#if defined(_NOT_YET_)
left = sp->length;
- sp->data = m_uiotombuf(uio, M_WAITOK, 0, resv_upfront, M_PKTHDR);
+ sp->data = m_uiotombuf(uio, M_WAITOK, sp->length,
+ resv_upfront, M_PKTHDR);
if (sp->data == NULL)
return (ENOMEM);
- sp->length = m_length(sp->data, NULL);
- sp->tail_mbuf = m_last(sp->data);
- return (0);
-#else
- int cancpy, willcpy, error;
- struct mbuf *m, *head;
- int cpsz = 0;
- /* First one gets a header */
- left = sp->length;
- head = m = sctp_get_mbuf_for_msg((left + resv_upfront), 0, M_WAIT, 0, MT_DATA);
- if (m == NULL) {
- return (ENOMEM);
- }
- /*-
- * Add this one for m in now, that way if the alloc fails we won't
- * have a bad cnt.
- */
- SCTP_BUF_RESV_UF(m, resv_upfront);
- cancpy = M_TRAILINGSPACE(m);
- willcpy = min(cancpy, left);
- while (left > 0) {
- /* move in user data */
- error = uiomove(mtod(m, caddr_t), willcpy, uio);
- if (error) {
- sctp_m_freem(head);
- return (error);
- }
- SCTP_BUF_LEN(m) = willcpy;
- left -= willcpy;
- cpsz += willcpy;
- if (left > 0) {
- SCTP_BUF_NEXT(m) = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 0, MT_DATA);
- if (SCTP_BUF_NEXT(m) == NULL) {
- /*
- * the head goes back to caller, he can free
- * the rest
- */
- sctp_m_freem(head);
- return (ENOMEM);
- }
- m = SCTP_BUF_NEXT(m);
- cancpy = M_TRAILINGSPACE(m);
- willcpy = min(cancpy, left);
- } else {
- sp->tail_mbuf = m;
- SCTP_BUF_NEXT(m) = NULL;
- }
- }
- sp->data = head;
- sp->length = cpsz;
+ sp->tail_mbuf = m_last(sp->data);
return (0);
-#endif
}
@@ -10491,13 +10417,14 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
*error = ECONNRESET;
goto out_now;
}
- sp = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq, struct sctp_stream_queue_pending);
+ sctp_alloc_a_strmoq(stcb, sp);
if (sp == NULL) {
*error = ENOMEM;
goto out_now;
}
SCTP_INCR_STRMOQ_COUNT();
sp->act_flags = 0;
+ sp->sender_all_done = 0;
sp->sinfo_flags = srcv->sinfo_flags;
sp->timetolive = srcv->sinfo_timetolive;
sp->ppid = srcv->sinfo_ppid;
@@ -10516,6 +10443,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
} else {
sp->msg_is_complete = 0;
}
+ sp->sender_all_done = 0;
sp->some_taken = 0;
resv_in_first = sizeof(struct sctp_data_chunk);
sp->data = sp->tail_mbuf = NULL;
@@ -10541,6 +10469,8 @@ out_now:
}
+
+
int
sctp_sosend(struct socket *so,
struct sockaddr *addr,
@@ -11122,6 +11052,11 @@ sctp_lower_sosend(struct socket *so,
atomic_add_int(&stcb->total_sends, 1);
if (top == NULL) {
struct sctp_stream_queue_pending *sp;
+
+#ifdef INVARIANTS
+ struct sctp_stream_queue_pending *msp;
+
+#endif
struct sctp_stream_out *strm;
uint32_t sndout, initial_out;
int user_marks_eor;
@@ -11151,6 +11086,11 @@ sctp_lower_sosend(struct socket *so,
goto out;
}
SCTP_TCB_SEND_LOCK(stcb);
+#ifdef INVARIANTS
+ msp = TAILQ_LAST(&strm->outqueue, sctp_streamhead);
+ if (msp && (msp->msg_is_complete == 0))
+ panic("Huh, new mesg and old not done?");
+#endif
if (sp->msg_is_complete) {
strm->last_msg_incomplete = 0;
asoc->stream_locked = 0;
@@ -11162,10 +11102,11 @@ sctp_lower_sosend(struct socket *so,
strm->last_msg_incomplete = 1;
asoc->stream_locked = 1;
asoc->stream_locked_on = srcv->sinfo_stream;
+ sp->sender_all_done = 0;
}
sctp_snd_sb_alloc(stcb, sp->length);
- asoc->stream_queue_cnt++;
+ atomic_add_int(&asoc->stream_queue_cnt, 1);
TAILQ_INSERT_TAIL(&strm->outqueue, sp, next);
if ((srcv->sinfo_flags & SCTP_UNORDERED) == 0) {
sp->strseq = strm->next_sequence_sent;
@@ -11186,7 +11127,9 @@ sctp_lower_sosend(struct socket *so,
}
SCTP_TCB_SEND_UNLOCK(stcb);
} else {
+ SCTP_TCB_SEND_LOCK(stcb);
sp = TAILQ_LAST(&strm->outqueue, sctp_streamhead);
+ SCTP_TCB_SEND_UNLOCK(stcb);
if (sp == NULL) {
/* ???? Huh ??? last msg is gone */
#ifdef INVARIANTS
@@ -11233,6 +11176,7 @@ sctp_lower_sosend(struct socket *so,
sctp_m_freem(mm);
if (stcb->asoc.state & SCTP_PCB_FLAGS_WAS_ABORTED)
error = ECONNRESET;
+ SCTP_TCB_SEND_UNLOCK(stcb);
goto out;
}
if (sp->tail_mbuf) {
@@ -11245,8 +11189,9 @@ sctp_lower_sosend(struct socket *so,
sp->tail_mbuf = new_tail;
}
sctp_snd_sb_alloc(stcb, sndout);
- sp->length += sndout;
+ atomic_add_int(&sp->length, sndout);
len += sndout;
+
/* Did we reach EOR? */
if ((uio->uio_resid == 0) &&
((user_marks_eor == 0) ||
@@ -11428,13 +11373,20 @@ sctp_lower_sosend(struct socket *so,
}
}
SCTP_TCB_SEND_LOCK(stcb);
- if (sp->msg_is_complete == 0) {
- strm->last_msg_incomplete = 1;
- asoc->stream_locked = 1;
- asoc->stream_locked_on = srcv->sinfo_stream;
+ if (sp) {
+ if (sp->msg_is_complete == 0) {
+ strm->last_msg_incomplete = 1;
+ asoc->stream_locked = 1;
+ asoc->stream_locked_on = srcv->sinfo_stream;
+ } else {
+ sp->sender_all_done = 1;
+ strm->last_msg_incomplete = 0;
+ asoc->stream_locked = 0;
+ }
} else {
strm->last_msg_incomplete = 0;
asoc->stream_locked = 0;
+
}
SCTP_TCB_SEND_UNLOCK(stcb);
if (uio->uio_resid == 0) {