summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet/sctp_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet/sctp_timer.c')
-rw-r--r--freebsd/sys/netinet/sctp_timer.c72
1 files changed, 45 insertions, 27 deletions
diff --git a/freebsd/sys/netinet/sctp_timer.c b/freebsd/sys/netinet/sctp_timer.c
index 7d010c7b..c851317b 100644
--- a/freebsd/sys/netinet/sctp_timer.c
+++ b/freebsd/sys/netinet/sctp_timer.c
@@ -51,7 +51,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_input.h>
#include <netinet/sctp.h>
#include <netinet/sctp_uio.h>
+#if defined(INET) || defined(INET6)
#include <netinet/udp.h>
+#endif
void
@@ -85,7 +87,7 @@ sctp_audit_retranmission_queue(struct sctp_association *asoc)
asoc->sent_queue_cnt);
}
-int
+static int
sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net, uint16_t threshold)
{
@@ -110,8 +112,10 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
net->dest_state |= SCTP_ADDR_PF;
net->last_active = sctp_get_tick_count();
sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
- sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
+ inp, stcb, net,
+ SCTP_FROM_SCTP_TIMER + SCTP_LOC_1);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
}
}
}
@@ -151,9 +155,9 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* Abort notification sends a ULP notify */
struct mbuf *op_err;
- op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION,
- "Association error couter exceeded");
- inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_1;
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ "Association error counter exceeded");
+ inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_2;
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
return (1);
}
@@ -337,7 +341,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
return (NULL);
}
}
- do {
+ for (;;) {
alt = TAILQ_NEXT(mnet, sctp_next);
if (alt == NULL) {
once++;
@@ -356,7 +360,6 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
}
alt->src_addr_selected = 0;
}
- /* sa_ignore NO_NULL_CHK */
if (((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) &&
(alt->ro.ro_rt != NULL) &&
(!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))) {
@@ -364,14 +367,14 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
break;
}
mnet = alt;
- } while (alt != NULL);
+ }
if (alt == NULL) {
/* Case where NO insv network exists (dormant state) */
/* we rotate destinations */
once = 0;
mnet = net;
- do {
+ for (;;) {
if (mnet == NULL) {
return (TAILQ_FIRST(&stcb->asoc.nets));
}
@@ -382,15 +385,17 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
break;
}
alt = TAILQ_FIRST(&stcb->asoc.nets);
+ if (alt == NULL) {
+ break;
+ }
}
- /* sa_ignore NO_NULL_CHK */
if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
(alt != net)) {
/* Found an alternate address */
break;
}
mnet = alt;
- } while (alt != NULL);
+ }
}
if (alt == NULL) {
return (net);
@@ -405,7 +410,11 @@ sctp_backoff_on_timeout(struct sctp_tcb *stcb,
int num_marked, int num_abandoned)
{
if (net->RTO == 0) {
- net->RTO = stcb->asoc.minrto;
+ if (net->RTO_measured) {
+ net->RTO = stcb->asoc.minrto;
+ } else {
+ net->RTO = stcb->asoc.initial_rto;
+ }
}
net->RTO <<= 1;
if (net->RTO > stcb->asoc.maxrto) {
@@ -435,6 +444,11 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
}
}
+ if ((asoc->strmout[chk->rec.data.stream_number].chunks_on_queues == 0) &&
+ (asoc->strmout[chk->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) &&
+ TAILQ_EMPTY(&asoc->strmout[chk->rec.data.stream_number].outqueue)) {
+ asoc->trigger_reset = 1;
+ }
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
if (PR_SCTP_ENABLED(chk->flags)) {
if (asoc->pr_sctp_cnt != 0)
@@ -445,7 +459,7 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_m_freem(chk->data);
chk->data = NULL;
- if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(chk->flags)) {
+ if (asoc->prsctp_supported && PR_SCTP_BUF_ENABLED(chk->flags)) {
asoc->sent_queue_cnt_removeable--;
}
}
@@ -600,7 +614,7 @@ start_again:
continue;
}
}
- if (stcb->asoc.peer_supports_prsctp && PR_SCTP_TTL_ENABLED(chk->flags)) {
+ if (stcb->asoc.prsctp_supported && PR_SCTP_TTL_ENABLED(chk->flags)) {
/* Is it expired? */
if (timevalcmp(&now, &chk->rec.data.timetodrop, >)) {
/* Yes so drop it */
@@ -614,7 +628,7 @@ start_again:
continue;
}
}
- if (stcb->asoc.peer_supports_prsctp && PR_SCTP_RTX_ENABLED(chk->flags)) {
+ if (stcb->asoc.prsctp_supported && PR_SCTP_RTX_ENABLED(chk->flags)) {
/* Has it been retransmitted tv_sec times? */
if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) {
if (chk->data) {
@@ -650,7 +664,7 @@ start_again:
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND_TO,
chk->whoTo->flight_size,
chk->book_size,
- (uintptr_t) chk->whoTo,
+ (uint32_t) (uintptr_t) chk->whoTo,
chk->rec.data.TSN_seq);
}
sctp_flight_size_decrease(chk);
@@ -778,7 +792,7 @@ start_again:
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
chk->whoTo->flight_size,
chk->book_size,
- (uintptr_t) chk->whoTo,
+ (uint32_t) (uintptr_t) chk->whoTo,
chk->rec.data.TSN_seq);
}
sctp_flight_size_increase(chk);
@@ -957,7 +971,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
return (0);
}
- if (stcb->asoc.peer_supports_prsctp) {
+ if (stcb->asoc.prsctp_supported) {
struct sctp_tmit_chunk *lchk;
lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc);
@@ -1043,9 +1057,9 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
/* FOOBAR! */
struct mbuf *op_err;
- op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION,
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
"Cookie timer expired, but no cookie");
- inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_4;
+ inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_3;
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
} else {
#ifdef INVARIANTS
@@ -1064,8 +1078,8 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
return (1);
}
/*
- * cleared theshold management now lets backoff the address & select
- * an alternate
+ * Cleared threshold management, now lets backoff the address and
+ * select an alternate
*/
stcb->asoc.dropped_special_cnt = 0;
sctp_backoff_on_timeout(stcb, cookie->whoTo, 1, 0, 0);
@@ -1110,8 +1124,8 @@ sctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
return (1);
}
/*
- * cleared theshold management now lets backoff the address & select
- * an alternate
+ * Cleared threshold management, now lets backoff the address and
+ * select an alternate
*/
sctp_backoff_on_timeout(stcb, strrst->whoTo, 1, 0, 0);
alt = sctp_find_alternate_net(stcb, strrst->whoTo, 0);
@@ -1270,7 +1284,7 @@ sctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
{
struct sctp_nets *alt;
- /* first threshold managment */
+ /* first threshold management */
if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
/* Assoc is over */
return (1);
@@ -1293,7 +1307,7 @@ sctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
{
struct sctp_nets *alt;
- /* first threshold managment */
+ /* first threshold management */
if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
/* Assoc is over */
return (1);
@@ -1482,11 +1496,15 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp,
}
if (net->ro._s_addr) {
mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_rt);
+#if defined(INET) || defined(INET6)
if (net->port) {
mtu -= sizeof(struct udphdr);
}
+#endif
if (mtu > next_mtu) {
net->mtu = next_mtu;
+ } else {
+ net->mtu = mtu;
}
}
}