diff options
author | rrs <rrs@FreeBSD.org> | 2007-07-02 19:22:22 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2007-07-02 19:22:22 +0000 |
commit | a400d04306bce1d90fa1fb76eb5ed9c3977a1c32 (patch) | |
tree | 1af5bea59680545d915388b260052ee36e2b1ab6 /sys/netinet/sctp_output.c | |
parent | bb6f1c3d9ba9c5a3452440ffdafda555b482e1b2 (diff) | |
download | FreeBSD-src-a400d04306bce1d90fa1fb76eb5ed9c3977a1c32.zip FreeBSD-src-a400d04306bce1d90fa1fb76eb5ed9c3977a1c32.tar.gz |
- Consolidate the code that free's chunks to actually also
call the sctp_free_remote_address() function.
- Assure that when we allocate a chunk the whoTo is NULL,
also when we free it and place it into the cache we NULL
it (that way the consolidation code will always work).
- Fix a small race, when a empty data holder is left on the stream
out queue, and both sides do a shutdown, the empty data holder
would prevent us from sending a SHUTDOWN-ACK and at the same time we
never would cleanup the empty holder (since nothing was ever in queue).
We now add a utility function that a) cleans up empty holders and
b) properly determines if there are still pending data chunks on
the stream out wheel.
Approved by: re@freebsd.org (Ken Smith)
Diffstat (limited to 'sys/netinet/sctp_output.c')
-rw-r--r-- | sys/netinet/sctp_output.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index ac2da30..7234ce7 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_asconf.h> #include <netinet/sctp_indata.h> #include <netinet/sctp_bsd_addr.h> +#include <netinet/sctp_input.h> @@ -5642,9 +5643,13 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, asoc = &stcb->asoc; if (ca->sndrcv.sinfo_flags & SCTP_EOF) { /* shutdown this assoc */ + int cnt; + + cnt = sctp_is_there_unsent_data(stcb); + if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue) && - (asoc->stream_queue_cnt == 0)) { + (cnt == 0)) { if (asoc->locked_on_sending) { goto abort_anyway; } @@ -5887,8 +5892,6 @@ sctp_toss_old_cookies(struct sctp_tcb *stcb, struct sctp_association *asoc) chk->data = NULL; } asoc->ctrl_queue_cnt--; - if (chk->whoTo) - sctp_free_remote_addr(chk->whoTo); sctp_free_a_chunk(stcb, chk); } chk = nchk; @@ -5914,8 +5917,6 @@ sctp_toss_old_asconf(struct sctp_tcb *stcb) chk->data = NULL; } asoc->ctrl_queue_cnt--; - if (chk->whoTo) - sctp_free_remote_addr(chk->whoTo); sctp_free_a_chunk(stcb, chk); } } @@ -6037,7 +6038,6 @@ sctp_clean_up_ctl(struct sctp_tcb *stcb, struct sctp_association *asoc) chk->data = NULL; } asoc->ctrl_queue_cnt--; - sctp_free_remote_addr(chk->whoTo); sctp_free_a_chunk(stcb, chk); } else if (chk->rec.chunk_id.id == SCTP_STREAM_RESET) { /* special handling, we must look into the param */ @@ -8989,8 +8989,6 @@ sctp_send_sack(struct sctp_tcb *stcb) sctp_m_freem(a_chk->data); a_chk->data = NULL; } - if (a_chk->whoTo) - atomic_subtract_int(&a_chk->whoTo->ref_count, 1); sctp_free_a_chunk(stcb, a_chk); if (stcb->asoc.delayed_ack) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, @@ -9576,7 +9574,6 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net) * to the Q's style as defined in the RFC and not my * alternate style defined in the RFC. */ - atomic_subtract_int(&chk->whoTo->ref_count, 1); if (chk->data != NULL) { sctp_m_freem(chk->data); chk->data = NULL; @@ -11576,15 +11573,18 @@ dataless_eof: (got_all_of_the_send == 1) && (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) ) { + int cnt; + SCTP_STAT_INCR(sctps_sends_with_eof); error = 0; if (hold_tcblock == 0) { SCTP_TCB_LOCK(stcb); hold_tcblock = 1; } + cnt = sctp_is_there_unsent_data(stcb); if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue) && - (asoc->stream_queue_cnt == 0)) { + (cnt == 0)) { if (asoc->locked_on_sending) { goto abort_anyway; } |