Improve plausibility check in sctp_handle_sack().

Allow cmt_on_off to support values 0 (no CMT), 1 (CMT), and 2 (CMT/RP).

MFC after: 3 months.
This commit is contained in:
Michael Tuexen 2010-12-22 17:59:38 +00:00
parent baf7e5ea7b
commit 7c99d56fdf
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216669
8 changed files with 69 additions and 80 deletions

View File

@ -80,12 +80,12 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
struct sctp_nets *net;
/*-
* CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
* CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
* (net->fast_retran_loss_recovery == 0)))
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if ((asoc->fast_retran_loss_recovery == 0) ||
(asoc->sctp_cmt_on_off == 1)) {
(asoc->sctp_cmt_on_off > 0)) {
/* out of a RFC2582 Fast recovery window? */
if (net->net_ack > 0) {
/*
@ -250,7 +250,7 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
*
* Should we stop any running T3 timer here?
*/
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
(asoc->sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
net->dest_state &= ~SCTP_ADDR_PF;
@ -274,10 +274,9 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* CMT fast recovery code
*/
/*
* if (sctp_cmt_on_off == 1 &&
* net->fast_retran_loss_recovery &&
* net->will_exit_fast_recovery == 0) { @@@ Do something }
* else if (sctp_cmt_on_off == 0 &&
* if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery
* && net->will_exit_fast_recovery == 0) { @@@ Do something
* } else if (sctp_cmt_on_off == 0 &&
* asoc->fast_retran_loss_recovery && will_exit == 0) {
*/
#endif
@ -296,7 +295,7 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* moved.
*/
if (accum_moved ||
((asoc->sctp_cmt_on_off == 1) && net->new_pseudo_cumack)) {
((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
/* If the cumulative ack moved we can proceed */
if (net->cwnd <= net->ssthresh) {
/* We are in slow start */
@ -759,12 +758,12 @@ sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
struct sctp_nets *net;
/*
* CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
* CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
* (net->fast_retran_loss_recovery == 0)))
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if ((asoc->fast_retran_loss_recovery == 0) ||
(asoc->sctp_cmt_on_off == 1)) {
(asoc->sctp_cmt_on_off > 0)) {
/* out of a RFC2582 Fast recovery window? */
if (net->net_ack > 0) {
/*
@ -917,7 +916,7 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
*
* Should we stop any running T3 timer here?
*/
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
(asoc->sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
net->dest_state &= ~SCTP_ADDR_PF;
@ -937,10 +936,9 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
* CMT fast recovery code
*/
/*
* if (sctp_cmt_on_off == 1 &&
* net->fast_retran_loss_recovery &&
* net->will_exit_fast_recovery == 0) { @@@ Do something }
* else if (sctp_cmt_on_off == 0 &&
* if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery
* && net->will_exit_fast_recovery == 0) { @@@ Do something
* } else if (sctp_cmt_on_off == 0 &&
* asoc->fast_retran_loss_recovery && will_exit == 0) {
*/
#endif
@ -959,7 +957,7 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
* moved.
*/
if (accum_moved ||
((asoc->sctp_cmt_on_off == 1) && net->new_pseudo_cumack)) {
((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
/* If the cumulative ack moved we can proceed */
if (net->cwnd <= net->ssthresh) {
/* We are in slow start */
@ -1403,7 +1401,7 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
*
* Should we stop any running T3 timer here?
*/
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
(asoc->sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
net->dest_state &= ~SCTP_ADDR_PF;
@ -1423,10 +1421,9 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* CMT fast recovery code
*/
/*
* if (sctp_cmt_on_off == 1 &&
* net->fast_retran_loss_recovery &&
* net->will_exit_fast_recovery == 0) { @@@ Do something }
* else if (sctp_cmt_on_off == 0 &&
* if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery
* && net->will_exit_fast_recovery == 0) { @@@ Do something
* } else if (sctp_cmt_on_off == 0 &&
* asoc->fast_retran_loss_recovery && will_exit == 0) {
*/
#endif
@ -1445,7 +1442,7 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* moved.
*/
if (accum_moved ||
((asoc->sctp_cmt_on_off == 1) && net->new_pseudo_cumack)) {
((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
htcp_cong_avoid(stcb, net);
measure_achieved_throughput(stcb, net);
} else {
@ -1481,12 +1478,12 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
struct sctp_nets *net;
/*
* CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
* CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
* (net->fast_retran_loss_recovery == 0)))
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if ((asoc->fast_retran_loss_recovery == 0) ||
(asoc->sctp_cmt_on_off == 1)) {
(asoc->sctp_cmt_on_off > 0)) {
/* out of a RFC2582 Fast recovery window? */
if (net->net_ack > 0) {
/*

View File

@ -2476,7 +2476,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap, int *abort_flag)
(stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) /* hit limit of pkts */
) {
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
if ((stcb->asoc.sctp_cmt_on_off > 0) &&
(SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) &&
(stcb->asoc.send_sack == 0) &&
(stcb->asoc.numduptsns == 0) &&
@ -3242,7 +3242,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
/* CMT DAC algo: finding out if SACK is a mixed SACK */
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (net->saw_newack)
@ -3353,7 +3353,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
tp1->sent++;
}
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*
* CMT DAC algorithm: If SACK flag is set to
@ -3419,7 +3419,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tp1->sent++;
}
strike_flag = 1;
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*
* CMT DAC algorithm: If
@ -3480,7 +3480,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
tp1->sent++;
}
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*
* CMT DAC algorithm: If SACK flag is set to
@ -3560,7 +3560,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
SCTP_STAT_INCR(sctps_sendmultfastretrans);
}
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
if (asoc->sctp_cmt_on_off == 1) {
if (asoc->sctp_cmt_on_off > 0) {
/*
* CMT: Using RTX_SSTHRESH policy for CMT.
* If CMT is being used, then pick dest with
@ -4776,7 +4776,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
/*******************************************/
/* cancel ALL T3-send timer if accum moved */
/*******************************************/
if (asoc->sctp_cmt_on_off == 1) {
if (asoc->sctp_cmt_on_off > 0) {
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (net->new_pseudo_cumack)
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
@ -4797,10 +4797,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
/********************************************/
asoc->last_acked_seq = cum_ack;
tp1 = TAILQ_FIRST(&asoc->sent_queue);
if (tp1 == NULL)
goto done_with_it;
do {
TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
if (compare_with_wrap(tp1->rec.data.TSN_seq, cum_ack,
MAX_TSN)) {
break;
@ -4810,26 +4807,17 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
printf("Warning, tp1->sent == %d and its now acked?\n",
tp1->sent);
}
tp2 = TAILQ_NEXT(tp1, sctp_next);
TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
if (tp1->pr_sctp_on) {
if (asoc->pr_sctp_cnt != 0)
asoc->pr_sctp_cnt--;
}
if (TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->total_flight > 0)) {
#ifdef INVARIANTS
panic("Warning flight size is postive and should be 0");
#else
SCTP_PRINTF("Warning flight size incorrect should be 0 is %d\n",
asoc->total_flight);
#endif
asoc->total_flight = 0;
}
asoc->sent_queue_cnt--;
if (tp1->data) {
/* sa_ignore NO_NULL_CHK */
sctp_free_bufspace(stcb, asoc, tp1, 1);
sctp_m_freem(tp1->data);
tp1->data = NULL;
if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(tp1->flags)) {
asoc->sent_queue_cnt_removeable--;
}
@ -4842,14 +4830,18 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
0,
SCTP_LOG_FREE_SENT);
}
tp1->data = NULL;
asoc->sent_queue_cnt--;
sctp_free_a_chunk(stcb, tp1);
wake_him++;
tp1 = tp2;
} while (tp1 != NULL);
done_with_it:
}
if (TAILQ_EMPTY(&asoc->sent_queue) && (asoc->total_flight > 0)) {
#ifdef INVARIANTS
panic("Warning flight size is postive and should be 0");
#else
SCTP_PRINTF("Warning flight size incorrect should be 0 is %d\n",
asoc->total_flight);
#endif
asoc->total_flight = 0;
}
/* sa_ignore NO_NULL_CHK */
if ((wake_him) && (stcb->sctp_socket)) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@ -5077,7 +5069,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
* to be done. Setting this_sack_lowest_newack to the cum_ack will
* automatically ensure that.
*/
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac) &&
(cmt_dac_flag == 0)) {
this_sack_lowest_newack = cum_ack;

View File

@ -623,7 +623,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
* timer is running, for the destination, stop the timer because a
* PF-heartbeat was received.
*/
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
if ((stcb->asoc.sctp_cmt_on_off > 0) &&
(stcb->asoc.sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {

View File

@ -3686,7 +3686,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
* Stop any running T3
* timers here?
*/
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
if ((stcb->asoc.sctp_cmt_on_off > 0) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Destination %p moved from PF to unreachable.\n",
@ -7325,7 +7325,7 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
(net == stcb->asoc.primary_destination)) {
/* ran dry for primary network net */
SCTP_STAT_INCR(sctps_primary_randry);
} else if (stcb->asoc.sctp_cmt_on_off == 1) {
} else if (stcb->asoc.sctp_cmt_on_off > 0) {
/* ran dry with CMT on */
SCTP_STAT_INCR(sctps_cmt_randry);
}
@ -7526,7 +7526,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
*reason_code = 8;
return (0);
}
if (asoc->sctp_cmt_on_off == 1) {
if (asoc->sctp_cmt_on_off > 0) {
/* get the last start point */
start_at = asoc->last_net_cmt_send_started;
if (start_at == NULL) {
@ -8028,7 +8028,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
}
}
/* JRI: if dest is in PF state, do not send data to it */
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
(asoc->sctp_cmt_pf > 0) &&
(net->dest_state & SCTP_ADDR_PF)) {
goto no_data_fill;
@ -8036,7 +8036,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
if (net->flight_size >= net->cwnd) {
goto no_data_fill;
}
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
(SCTP_BASE_SYSCTL(sctp_buffer_splitting) & SCTP_RECV_BUFFER_SPLITTING) &&
(net->flight_size > max_rwnd_per_dest)) {
goto no_data_fill;
@ -8047,7 +8047,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
* net. For now, this is better than nothing and it disabled
* by default...
*/
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
(SCTP_BASE_SYSCTL(sctp_buffer_splitting) & SCTP_SEND_BUFFER_SPLITTING) &&
(max_send_per_dest > 0) &&
(net->flight_size > max_send_per_dest)) {
@ -8268,7 +8268,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
* restart it.
*/
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
} else if ((asoc->sctp_cmt_on_off == 1) &&
} else if ((asoc->sctp_cmt_on_off > 0) &&
(asoc->sctp_cmt_pf > 0) &&
pf_hbflag &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF) &&
@ -9576,7 +9576,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
*/
if (net->ref_count > 1)
sctp_move_chunks_from_net(stcb, net);
} else if ((asoc->sctp_cmt_on_off == 1) &&
} else if ((asoc->sctp_cmt_on_off > 0) &&
(asoc->sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
/*
@ -10073,7 +10073,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
else
flags = 0;
if ((asoc->sctp_cmt_on_off == 1) &&
if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*-
* CMT DAC algorithm: If 2 (i.e., 0x10) packets have been

View File

@ -325,9 +325,9 @@ struct sctp_sysctl {
#define SCTPCTL_OUTGOING_STREAMS_DEFAULT SCTP_OSTREAM_INITIAL
/* cmt_on_off: CMT on/off flag */
#define SCTPCTL_CMT_ON_OFF_DESC "CMT on/off flag"
#define SCTPCTL_CMT_ON_OFF_DESC "CMT settings"
#define SCTPCTL_CMT_ON_OFF_MIN 0
#define SCTPCTL_CMT_ON_OFF_MAX 1
#define SCTPCTL_CMT_ON_OFF_MAX 2
#define SCTPCTL_CMT_ON_OFF_DEFAULT 0
/* EY - nr_sack_on_off: NR_SACK on/off flag */

View File

@ -215,7 +215,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* not in PF state.
*/
/* Stop any running T3 timers here? */
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
if ((stcb->asoc.sctp_cmt_on_off > 0) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
@ -850,7 +850,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
/*
* CMT: Do not allow FRs on retransmitted TSNs.
*/
if (stcb->asoc.sctp_cmt_on_off == 1) {
if (stcb->asoc.sctp_cmt_on_off > 0) {
chk->no_fr_allowed = 1;
}
#ifdef THIS_SHOULD_NOT_BE_DONE
@ -1005,7 +1005,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
* addition, find an alternate destination with PF-based
* find_alt_net().
*/
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
if ((stcb->asoc.sctp_cmt_on_off > 0) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
if ((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF) {
net->dest_state |= SCTP_ADDR_PF;
@ -1014,7 +1014,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
net);
}
alt = sctp_find_alternate_net(stcb, net, 2);
} else if (stcb->asoc.sctp_cmt_on_off == 1) {
} else if (stcb->asoc.sctp_cmt_on_off > 0) {
/*
* CMT: Using RTX_SSTHRESH policy for CMT. If CMT is being
* used, then pick dest with largest ssthresh for any
@ -1129,7 +1129,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
}
}
} else if ((stcb->asoc.sctp_cmt_on_off == 1) &&
} else if ((stcb->asoc.sctp_cmt_on_off > 0) &&
(stcb->asoc.sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
/*

View File

@ -292,7 +292,7 @@ sctp_notify(struct sctp_inpcb *inp,
* PF state.
*/
/* Stop any running T3 timers here? */
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
if ((stcb->asoc.sctp_cmt_on_off > 0) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
@ -2840,17 +2840,17 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
if (av->assoc_value != 0)
stcb->asoc.sctp_cmt_on_off = 1;
else
stcb->asoc.sctp_cmt_on_off = 0;
stcb->asoc.sctp_cmt_on_off = av->assoc_value;
if (stcb->asoc.sctp_cmt_on_off > 2) {
stcb->asoc.sctp_cmt_on_off = 2;
}
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_INP_WLOCK(inp);
if (av->assoc_value != 0)
inp->sctp_cmt_on_off = 1;
else
inp->sctp_cmt_on_off = 0;
inp->sctp_cmt_on_off = av->assoc_value;
if (inp->sctp_cmt_on_off > 2) {
inp->sctp_cmt_on_off = 2;
}
SCTP_INP_WUNLOCK(inp);
}
} else {

View File

@ -426,7 +426,7 @@ sctp6_notify(struct sctp_inpcb *inp,
* PF state.
*/
/* Stop any running T3 timers here? */
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
if ((stcb->asoc.sctp_cmt_on_off > 0) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",