summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctputil.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctputil.c')
-rw-r--r--sys/netinet/sctputil.c250
1 files changed, 93 insertions, 157 deletions
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 707d05c..30cc9ed 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1,5 +1,7 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -47,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
#include <netinet/sctp_auth.h>
#include <netinet/sctp_asconf.h>
-#include <netinet/sctp_cc_functions.h>
#include <netinet/sctp_bsd_addr.h>
@@ -55,6 +56,9 @@ __FBSDID("$FreeBSD$");
#define KTR_SCTP KTR_SUBSYS
#endif
+extern struct sctp_cc_functions sctp_cc_functions[];
+extern struct sctp_ss_functions sctp_ss_functions[];
+
void
sctp_sblog(struct sockbuf *sb,
struct sctp_tcb *stcb, int from, int incr)
@@ -911,9 +915,11 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
/* init all variables to a known value. */
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
asoc->max_burst = m->sctp_ep.max_burst;
+ asoc->fr_max_burst = m->sctp_ep.fr_max_burst;
asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
asoc->cookie_life = m->sctp_ep.def_cookie_life;
asoc->sctp_cmt_on_off = m->sctp_cmt_on_off;
+ asoc->ecn_allowed = m->sctp_ecn_enable;
asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
asoc->sctp_cmt_pf = (uint8_t) SCTP_BASE_SYSCTL(sctp_cmt_pf);
asoc->sctp_frag_point = m->sctp_frag_point;
@@ -969,7 +975,6 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->last_net_cmt_send_started = NULL;
/* This will need to be adjusted */
- asoc->last_cwr_tsn = asoc->init_seq_number - 1;
asoc->last_acked_seq = asoc->init_seq_number - 1;
asoc->advanced_peer_ack_point = asoc->last_acked_seq;
asoc->asconf_seq_in = asoc->last_acked_seq;
@@ -986,16 +991,9 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->free_chunk_cnt = 0;
asoc->iam_blocking = 0;
- /* ECN Nonce initialization */
+
asoc->context = m->sctp_context;
asoc->def_send = m->def_send;
- asoc->ecn_nonce_allowed = 0;
- asoc->receiver_nonce_sum = 1;
- asoc->nonce_sum_expect_base = 1;
- asoc->nonce_sum_check = 1;
- asoc->nonce_resync_tsn = 0;
- asoc->nonce_wait_for_ecne = 0;
- asoc->nonce_wait_tsn = 0;
asoc->delayed_ack = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
asoc->sack_freq = m->sctp_ep.sctp_sack_freq;
asoc->pr_sctp_cnt = 0;
@@ -1044,68 +1042,11 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time;
- /*
- * JRS - Pick the default congestion control module based on the
- * sysctl.
- */
- switch (m->sctp_ep.sctp_default_cc_module) {
- /* JRS - Standard TCP congestion control */
- case SCTP_CC_RFC2581:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_RFC2581;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer;
- break;
- }
- /* JRS - High Speed TCP congestion control (Floyd) */
- case SCTP_CC_HSTCP:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_HSTCP;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_hs_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_hs_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer;
- break;
- }
- /* JRS - HTCP congestion control */
- case SCTP_CC_HTCP:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_HTCP;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_htcp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_htcp_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_htcp_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_htcp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_htcp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_htcp_cwnd_update_after_fr_timer;
- break;
- }
- /* JRS - By default, use RFC2581 */
- default:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_RFC2581;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer;
- break;
- }
- }
+ stcb->asoc.congestion_control_module = m->sctp_ep.sctp_default_cc_module;
+ stcb->asoc.cc_functions = sctp_cc_functions[m->sctp_ep.sctp_default_cc_module];
+
+ stcb->asoc.stream_scheduling_module = m->sctp_ep.sctp_default_ss_module;
+ stcb->asoc.ss_functions = sctp_ss_functions[m->sctp_ep.sctp_default_ss_module];
/*
* Now the stream parameters, here we allocate space for all streams
@@ -1134,9 +1075,10 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
TAILQ_INIT(&asoc->strmout[i].outqueue);
asoc->strmout[i].stream_no = i;
asoc->strmout[i].last_msg_incomplete = 0;
- asoc->strmout[i].next_spoke.tqe_next = 0;
- asoc->strmout[i].next_spoke.tqe_prev = 0;
+ asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
}
+ asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
+
/* Now the mapping array */
asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size,
@@ -1159,7 +1101,6 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
/* Now the init of the other outqueues */
TAILQ_INIT(&asoc->free_chunks);
- TAILQ_INIT(&asoc->out_wheel);
TAILQ_INIT(&asoc->control_send_queue);
TAILQ_INIT(&asoc->asconf_send_queue);
TAILQ_INIT(&asoc->send_queue);
@@ -1417,13 +1358,13 @@ no_stcb:
void
sctp_iterator_worker(void)
{
- struct sctp_iterator *it = NULL;
+ struct sctp_iterator *it, *nit;
/* This function is called with the WQ lock in place */
sctp_it_ctl.iterator_running = 1;
- sctp_it_ctl.cur_it = it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
- while (it) {
+ TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
+ sctp_it_ctl.cur_it = it;
/* now lets work on this one */
TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
SCTP_IPI_ITERATOR_WQ_UNLOCK();
@@ -1437,7 +1378,6 @@ sctp_iterator_worker(void)
break;
}
/* sa_ignore FREED_MEMORY */
- sctp_it_ctl.cur_it = it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
}
sctp_it_ctl.iterator_running = 0;
return;
@@ -1448,7 +1388,7 @@ static void
sctp_handle_addr_wq(void)
{
/* deal with the ADDR wq from the rtsock calls */
- struct sctp_laddr *wi;
+ struct sctp_laddr *wi, *nwi;
struct sctp_asconf_iterator *asc;
SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
@@ -1465,12 +1405,10 @@ sctp_handle_addr_wq(void)
asc->cnt = 0;
SCTP_WQ_ADDR_LOCK();
- wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq));
- while (wi != NULL) {
+ LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
LIST_REMOVE(wi, sctp_nxt_addr);
LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
asc->cnt++;
- wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq));
}
SCTP_WQ_ADDR_UNLOCK();
@@ -1664,8 +1602,7 @@ sctp_timeout_handler(void *t)
#endif
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
if ((stcb->asoc.num_send_timers_up == 0) &&
- (stcb->asoc.sent_queue_cnt > 0)
- ) {
+ (stcb->asoc.sent_queue_cnt > 0)) {
struct sctp_tmit_chunk *chk;
/*
@@ -2526,12 +2463,13 @@ sctp_mtu_size_reset(struct sctp_inpcb *inp,
* given an association and starting time of the current RTT period return
* RTO in number of msecs net should point to the current network
*/
+
uint32_t
sctp_calculate_rto(struct sctp_tcb *stcb,
struct sctp_association *asoc,
struct sctp_nets *net,
struct timeval *told,
- int safe)
+ int safe, int local_lan_determine)
{
/*-
* given an association and the starting time of the current RTT
@@ -2559,6 +2497,21 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
/************************/
/* get the current time */
(void)SCTP_GETTIME_TIMEVAL(&now);
+ /*
+ * Record the real time of the last RTT for use in DC-CC.
+ */
+ net->last_measured_rtt = now;
+ timevalsub(&net->last_measured_rtt, old);
+
+ /* Do we need to determine the lan type? */
+ if ((local_lan_determine == SCTP_DETERMINE_LL_OK) && (net->lan_type == SCTP_LAN_UNKNOWN)) {
+ if ((net->last_measured_rtt.tv_sec) ||
+ (net->last_measured_rtt.tv_usec > SCTP_LOCAL_LAN_RTT)) {
+ net->lan_type = SCTP_LAN_INTERNET;
+ } else {
+ net->lan_type = SCTP_LAN_LOCAL;
+ }
+ }
/* compute the RTT value */
if ((u_long)now.tv_sec > (u_long)old->tv_sec) {
calc_time = ((u_long)now.tv_sec - (u_long)old->tv_sec) * 1000;
@@ -3693,22 +3646,21 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
{
struct sctp_association *asoc;
struct sctp_stream_out *outs;
- struct sctp_tmit_chunk *chk;
- struct sctp_stream_queue_pending *sp;
+ struct sctp_tmit_chunk *chk, *nchk;
+ struct sctp_stream_queue_pending *sp, *nsp;
int i;
- asoc = &stcb->asoc;
-
if (stcb == NULL) {
return;
}
- if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ asoc = &stcb->asoc;
+ if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
/* already being freed */
return;
}
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
- (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
+ (asoc->state & SCTP_STATE_CLOSED_SOCKET)) {
return;
}
/* now through all the gunk freeing chunks */
@@ -3716,53 +3668,44 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
SCTP_TCB_SEND_LOCK(stcb);
}
/* sent queue SHOULD be empty */
- if (!TAILQ_EMPTY(&asoc->sent_queue)) {
- chk = TAILQ_FIRST(&asoc->sent_queue);
- while (chk) {
- TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
- asoc->sent_queue_cnt--;
- if (chk->data != NULL) {
- sctp_free_bufspace(stcb, asoc, chk, 1);
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
+ TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
+ TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
+ asoc->sent_queue_cnt--;
+ if (chk->data != NULL) {
+ sctp_free_bufspace(stcb, asoc, chk, 1);
+ sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
+ SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
}
- sctp_free_a_chunk(stcb, chk);
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->sent_queue);
}
+ sctp_free_a_chunk(stcb, chk);
+ /* sa_ignore FREED_MEMORY */
}
/* pending send queue SHOULD be empty */
- if (!TAILQ_EMPTY(&asoc->send_queue)) {
- chk = TAILQ_FIRST(&asoc->send_queue);
- while (chk) {
- TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
- asoc->send_queue_cnt--;
- if (chk->data != NULL) {
- sctp_free_bufspace(stcb, asoc, chk, 1);
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_UNSENT, chk, so_locked);
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
+ TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
+ TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
+ asoc->send_queue_cnt--;
+ if (chk->data != NULL) {
+ sctp_free_bufspace(stcb, asoc, chk, 1);
+ sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
+ SCTP_NOTIFY_DATAGRAM_UNSENT, chk, so_locked);
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
}
- sctp_free_a_chunk(stcb, chk);
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->send_queue);
}
+ sctp_free_a_chunk(stcb, chk);
+ /* sa_ignore FREED_MEMORY */
}
- for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ for (i = 0; i < asoc->streamoutcnt; i++) {
/* For each stream */
- outs = &stcb->asoc.strmout[i];
+ outs = &asoc->strmout[i];
/* clean up any sends there */
- stcb->asoc.locked_on_sending = NULL;
- sp = TAILQ_FIRST(&outs->outqueue);
- while (sp) {
- stcb->asoc.stream_queue_cnt--;
+ asoc->locked_on_sending = NULL;
+ TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
+ asoc->stream_queue_cnt--;
TAILQ_REMOVE(&outs->outqueue, sp, next);
sctp_free_spbufspace(stcb, asoc, sp);
if (sp->data) {
@@ -3780,7 +3723,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
/* Free the chunk */
sctp_free_a_strmoq(stcb, sp);
/* sa_ignore FREED_MEMORY */
- sp = TAILQ_FIRST(&outs->outqueue);
}
}
@@ -3847,6 +3789,11 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
+ SCTP_STAT_INCR_COUNTER32(sctps_aborted);
+ if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_4);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
@@ -4306,10 +4253,8 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
}
/* lock the socket buffers */
SCTP_INP_READ_LOCK(old_inp);
- control = TAILQ_FIRST(&old_inp->read_queue);
- /* Pull off all for out target stcb */
- while (control) {
- nctl = TAILQ_NEXT(control, next);
+ TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) {
+ /* Pull off all for out target stcb */
if (control->stcb == stcb) {
/* remove it we want it */
TAILQ_REMOVE(&old_inp->read_queue, control, next);
@@ -4326,17 +4271,14 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
m = SCTP_BUF_NEXT(m);
}
}
- control = nctl;
}
SCTP_INP_READ_UNLOCK(old_inp);
/* Remove the sb-lock on the old socket */
sbunlock(&old_so->so_rcv);
/* Now we move them over to the new socket buffer */
- control = TAILQ_FIRST(&tmp_queue);
SCTP_INP_READ_LOCK(new_inp);
- while (control) {
- nctl = TAILQ_NEXT(control, next);
+ TAILQ_FOREACH_SAFE(control, &tmp_queue, next, nctl) {
TAILQ_INSERT_TAIL(&new_inp->read_queue, control, next);
m = control->data;
while (m) {
@@ -4349,7 +4291,6 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
}
m = SCTP_BUF_NEXT(m);
}
- control = nctl;
}
SCTP_INP_READ_UNLOCK(new_inp);
}
@@ -4695,7 +4636,7 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
)
{
struct sctp_stream_out *strq;
- struct sctp_tmit_chunk *chk = NULL;
+ struct sctp_tmit_chunk *chk = NULL, *tp2;
struct sctp_stream_queue_pending *sp;
uint16_t stream = 0, seq = 0;
uint8_t foundeom = 0;
@@ -4749,15 +4690,11 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
* The multi-part message was scattered across the send and
* sent queue.
*/
-next_on_sent:
- tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
- /*
- * recurse throught the send_queue too, starting at the
- * beginning.
- */
- if ((tp1) &&
- (tp1->rec.data.stream_number == stream) &&
- (tp1->rec.data.stream_seq == seq)) {
+ TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) {
+ if ((tp1->rec.data.stream_number != stream) ||
+ (tp1->rec.data.stream_seq != seq)) {
+ break;
+ }
/*
* save to chk in case we have some on stream out
* queue. If so and we have an un-transmitted one we
@@ -4787,7 +4724,6 @@ next_on_sent:
sctp_next);
stcb->asoc.send_queue_cnt--;
stcb->asoc.sent_queue_cnt++;
- goto next_on_sent;
}
}
if (foundeom == 0) {
@@ -4797,8 +4733,11 @@ next_on_sent:
*/
strq = &stcb->asoc.strmout[stream];
SCTP_TCB_SEND_LOCK(stcb);
- sp = TAILQ_FIRST(&strq->outqueue);
- while (sp->strseq <= seq) {
+ TAILQ_FOREACH(sp, &strq->outqueue, next) {
+ /* FIXME: Shouldn't this be a serial number check? */
+ if (sp->strseq > seq) {
+ break;
+ }
/* Check if its our SEQ */
if (sp->strseq == seq) {
sp->discard_rest = 1;
@@ -4861,11 +4800,8 @@ next_on_sent:
sp->tail_mbuf = NULL;
}
break;
- } else {
- /* Next one please */
- sp = TAILQ_NEXT(sp, next);
}
- } /* End while */
+ } /* End tailq_foreach */
SCTP_TCB_SEND_UNLOCK(stcb);
}
if (do_wakeup_routine) {
OpenPOWER on IntegriCloud