diff options
author | rrs <rrs@FreeBSD.org> | 2008-10-27 14:01:23 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2008-10-27 14:01:23 +0000 |
commit | 9cdcbb63a215971c54bd54e77fedf6c9de56c030 (patch) | |
tree | d872233f890b1a2562ccf325c77facec6a3bdfc4 | |
parent | 6313e0076defa950f11f13735975b99ca3a2a755 (diff) | |
download | FreeBSD-src-9cdcbb63a215971c54bd54e77fedf6c9de56c030.zip FreeBSD-src-9cdcbb63a215971c54bd54e77fedf6c9de56c030.tar.gz |
Two inter-related bugs.
- If we send EXACTLY the size left in the send buffer
and then send again, we end up with exactly 0 bytes and
don't hit the pre-block code to wait for more space.
- If we fall into the loop with our max_len == 0 (the bug
above) we then call in to copy out the data, setup the length
of the waiting to transmit data to 0 and call the mbuf copy routine
which 0 indicates copy all the data to the mbuf chain.. which it
does. This then leaves a "stuck" message on the stream queue with
its size exactly 0 bytes but all the data there and thus nothing
left in the uio structure. We then reach a stuck forever state
never being able to send data.
-rw-r--r-- | sys/netinet/sctp_output.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index f306f7e..2c6f769 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -11682,7 +11682,12 @@ sctp_copy_it_in(struct sctp_tcb *stcb, sp->put_last_out = 0; resv_in_first = sizeof(struct sctp_data_chunk); sp->data = sp->tail_mbuf = NULL; + if (sp->length == 0) { + *error = 0; + goto skip_copy; + } *error = sctp_copy_one(sp, uio, resv_in_first); +skip_copy: if (*error) { sctp_free_a_strmoq(stcb, sp); sp = NULL; @@ -12443,7 +12448,8 @@ sctp_lower_sosend(struct socket *so, goto skip_preblock; } if (((max_len <= local_add_more) && - (SCTP_SB_LIMIT_SND(so) > local_add_more)) || + (SCTP_SB_LIMIT_SND(so) >= local_add_more)) || + (max_len == 0) || ((stcb->asoc.chunks_on_out_queue + stcb->asoc.stream_queue_cnt) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { /* if */ /* No room right now ! */ SOCKBUF_LOCK(&so->so_snd); @@ -13058,7 +13064,7 @@ skip_out_eof: (void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out, &reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point, SCTP_SO_LOCKED); } - SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d", + SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d\n", queue_only, stcb->asoc.peers_rwnd, un_sent, stcb->asoc.total_flight, stcb->asoc.chunks_on_out_queue, stcb->asoc.total_output_queue_size, error); |