summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_output.c
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-07-02 19:22:22 +0000
committerrrs <rrs@FreeBSD.org>2007-07-02 19:22:22 +0000
commita400d04306bce1d90fa1fb76eb5ed9c3977a1c32 (patch)
tree1af5bea59680545d915388b260052ee36e2b1ab6 /sys/netinet/sctp_output.c
parentbb6f1c3d9ba9c5a3452440ffdafda555b482e1b2 (diff)
downloadFreeBSD-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.c20
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;
}
OpenPOWER on IntegriCloud