summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctp_timer.c')
-rw-r--r--sys/netinet/sctp_timer.c71
1 files changed, 57 insertions, 14 deletions
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 62de925..1d6902e 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <netinet6/sctp6_var.h>
#endif
#include <netinet/sctp_var.h>
+#include <netinet/sctp_sysctl.h>
#include <netinet/sctp_timer.h>
#include <netinet/sctputil.h>
#include <netinet/sctp_output.h>
@@ -51,13 +52,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_uio.h>
-#ifdef SCTP_DEBUG
-extern uint32_t sctp_debug_on;
-
-#endif /* SCTP_DEBUG */
-
-
-extern unsigned int sctp_early_fr_msec;
void
sctp_early_fr_timer(struct sctp_inpcb *inp,
@@ -224,6 +218,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (net->dest_state & SCTP_ADDR_REACHABLE) {
net->dest_state &= ~SCTP_ADDR_REACHABLE;
net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
+ net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY;
if (net == stcb->asoc.primary_destination) {
net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
}
@@ -368,6 +363,10 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
if (sin6->sin6_family == AF_INET6) {
(void)sa6_recoverscope(sin6);
}
+ if (alt->ro._s_addr) {
+ sctp_free_ifa(alt->ro._s_addr);
+ alt->ro._s_addr = NULL;
+ }
alt->src_addr_selected = 0;
}
if (
@@ -441,8 +440,6 @@ sctp_backoff_on_timeout(struct sctp_tcb *stcb,
}
}
-extern int sctp_peer_chunk_oh;
-
static int
sctp_mark_all_for_resend(struct sctp_tcb *stcb,
struct sctp_nets *net,
@@ -635,6 +632,11 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
}
if (stcb->asoc.total_flight_count > 0)
stcb->asoc.total_flight_count--;
+ if (chk->rec.data.chunk_was_revoked) {
+ /* deflate the cwnd */
+ chk->whoTo->cwnd -= chk->book_size;
+ chk->rec.data.chunk_was_revoked = 0;
+ }
chk->sent = SCTP_DATAGRAM_RESEND;
SCTP_STAT_INCR(sctps_markedretrans);
net->marked_retrans++;
@@ -934,6 +936,10 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
(struct sockaddr *)NULL,
alt) == 0) {
net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
+ if (net->ro._s_addr) {
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
+ }
net->src_addr_selected = 0;
}
}
@@ -1387,6 +1393,15 @@ sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
{
if (net) {
if (net->hb_responded == 0) {
+ if (net->ro._s_addr) {
+ /*
+ * Invalidate the src address if we did not
+ * get a response last time.
+ */
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
+ net->src_addr_selected = 0;
+ }
sctp_backoff_on_timeout(stcb, net, 1, 0);
}
/* Zero PBA, if it needs it */
@@ -1415,10 +1430,18 @@ sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
(net->dest_state & SCTP_ADDR_REACHABLE)) {
cnt_sent++;
+ if (net->hb_responded == 0) {
+ /* Did we respond last time? */
+ if (net->ro._s_addr) {
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
+ net->src_addr_selected = 0;
+ }
+ }
if (sctp_send_hb(stcb, 1, net) == 0) {
break;
}
- if (cnt_sent >= stcb->asoc.max_burst)
+ if (cnt_sent >= sctp_hb_maxburst)
break;
}
}
@@ -1598,6 +1621,7 @@ void
sctp_iterator_timer(struct sctp_iterator *it)
{
int iteration_count = 0;
+ int inp_skip = 0;
/*
* only one iterator can run at a time. This is the only way we can
@@ -1610,7 +1634,7 @@ sctp_iterator_timer(struct sctp_iterator *it)
done_with_iterator:
SCTP_ITERATOR_UNLOCK();
SCTP_INP_INFO_WLOCK();
- LIST_REMOVE(it, sctp_nxt_itr);
+ TAILQ_REMOVE(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr);
/* stopping the callout is not needed, in theory */
SCTP_INP_INFO_WUNLOCK();
SCTP_OS_TIMER_STOP(&it->tmr.timer);
@@ -1650,14 +1674,24 @@ select_a_new_ep:
SCTP_INP_WUNLOCK(it->inp);
SCTP_INP_RLOCK(it->inp);
/* now go through each assoc which is in the desired state */
+ if (it->done_current_ep == 0) {
+ if (it->function_inp != NULL)
+ inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val);
+ it->done_current_ep = 1;
+ }
if (it->stcb == NULL) {
/* run the per instance function */
- if (it->function_inp != NULL)
- (*it->function_inp) (it->inp, it->pointer, it->val);
-
it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
}
SCTP_INP_RUNLOCK(it->inp);
+ if ((inp_skip) || it->stcb == NULL) {
+ if (it->function_inp_end != NULL) {
+ inp_skip = (*it->function_inp_end) (it->inp,
+ it->pointer,
+ it->val);
+ }
+ goto no_stcb;
+ }
if ((it->stcb) &&
(it->stcb->asoc.stcb_starting_point_for_iterator == it)) {
it->stcb->asoc.stcb_starting_point_for_iterator = NULL;
@@ -1695,8 +1729,17 @@ select_a_new_ep:
SCTP_TCB_UNLOCK(it->stcb);
next_assoc:
it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
+ if (it->stcb == NULL) {
+ if (it->function_inp_end != NULL) {
+ inp_skip = (*it->function_inp_end) (it->inp,
+ it->pointer,
+ it->val);
+ }
+ }
}
+no_stcb:
/* done with all assocs on this endpoint, move on to next endpoint */
+ it->done_current_ep = 0;
SCTP_INP_WLOCK(it->inp);
it->inp->inp_starting_point_for_iterator = NULL;
SCTP_INP_WUNLOCK(it->inp);
OpenPOWER on IntegriCloud