Fix the switching on/off of CMT using sysctl and socket option.

Fix the switching on/off of PF and NR-SACKs using sysctl.
Add minor improvement in handling malloc failures.
Improve the address checks when sending.

MFC after: 4 weeks
This commit is contained in:
Michael Tuexen 2010-08-28 17:59:51 +00:00
parent 6d8fedda2c
commit 20083c2eb1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=211944
12 changed files with 165 additions and 175 deletions

View File

@ -155,10 +155,8 @@ struct sctp_paramhdr {
/* CMT ON/OFF socket option */
#define SCTP_CMT_ON_OFF 0x00001200
#define SCTP_CMT_USE_DAC 0x00001201
/* EY - NR_SACK on/off socket option */
#define SCTP_NR_SACK_ON_OFF 0x00001300
/* JRS - Pluggable Congestion Control Socket option */
#define SCTP_PLUGGABLE_CC 0x00001202
#define SCTP_PLUGGABLE_CC 0x00001202
/* read only */
#define SCTP_GET_SNDBUF_USE 0x00001101

View File

@ -71,7 +71,8 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
* (net->fast_retran_loss_recovery == 0)))
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if ((asoc->fast_retran_loss_recovery == 0) || (SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 1)) {
if ((asoc->fast_retran_loss_recovery == 0) ||
(asoc->sctp_cmt_on_off == 1)) {
/* out of a RFC2582 Fast recovery window? */
if (net->net_ack > 0) {
/*
@ -232,11 +233,11 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
*
* Should we stop any running T3 timer here?
*/
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
if ((asoc->sctp_cmt_on_off == 1) &&
(asoc->sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
net->dest_state &= ~SCTP_ADDR_PF;
net->cwnd = net->mtu * SCTP_BASE_SYSCTL(sctp_cmt_pf);
net->cwnd = net->mtu * asoc->sctp_cmt_pf;
SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
net, net->cwnd);
/*
@ -260,7 +261,9 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
*/
#endif
if (asoc->fast_retran_loss_recovery && will_exit == 0 && SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) {
if (asoc->fast_retran_loss_recovery &&
(will_exit == 0) &&
(asoc->sctp_cmt_on_off == 0)) {
/*
* If we are in loss recovery we skip any cwnd
* update
@ -271,7 +274,8 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* CMT: CUC algorithm. Update cwnd if pseudo-cumack has
* moved.
*/
if (accum_moved || (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && net->new_pseudo_cumack)) {
if (accum_moved ||
((asoc->sctp_cmt_on_off == 1) && net->new_pseudo_cumack)) {
/* If the cumulative ack moved we can proceed */
if (net->cwnd <= net->ssthresh) {
/* We are in slow start */
@ -697,7 +701,8 @@ sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
* (net->fast_retran_loss_recovery == 0)))
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if ((asoc->fast_retran_loss_recovery == 0) || (SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 1)) {
if ((asoc->fast_retran_loss_recovery == 0) ||
(asoc->sctp_cmt_on_off == 1)) {
/* out of a RFC2582 Fast recovery window? */
if (net->net_ack > 0) {
/*
@ -850,11 +855,11 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
*
* Should we stop any running T3 timer here?
*/
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
if ((asoc->sctp_cmt_on_off == 1) &&
(asoc->sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
net->dest_state &= ~SCTP_ADDR_PF;
net->cwnd = net->mtu * SCTP_BASE_SYSCTL(sctp_cmt_pf);
net->cwnd = net->mtu * asoc->sctp_cmt_pf;
SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
net, net->cwnd);
/*
@ -878,7 +883,9 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
*/
#endif
if (asoc->fast_retran_loss_recovery && will_exit == 0 && SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) {
if (asoc->fast_retran_loss_recovery &&
(will_exit == 0) &&
(asoc->sctp_cmt_on_off == 0)) {
/*
* If we are in loss recovery we skip any cwnd
* update
@ -889,7 +896,8 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
* CMT: CUC algorithm. Update cwnd if pseudo-cumack has
* moved.
*/
if (accum_moved || (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && net->new_pseudo_cumack)) {
if (accum_moved ||
((asoc->sctp_cmt_on_off == 1) && net->new_pseudo_cumack)) {
/* If the cumulative ack moved we can proceed */
if (net->cwnd <= net->ssthresh) {
/* We are in slow start */
@ -1333,11 +1341,11 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
*
* Should we stop any running T3 timer here?
*/
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
if ((asoc->sctp_cmt_on_off == 1) &&
(asoc->sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
net->dest_state &= ~SCTP_ADDR_PF;
net->cwnd = net->mtu * SCTP_BASE_SYSCTL(sctp_cmt_pf);
net->cwnd = net->mtu * asoc->sctp_cmt_pf;
SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
net, net->cwnd);
/*
@ -1361,7 +1369,9 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
*/
#endif
if (asoc->fast_retran_loss_recovery && will_exit == 0 && SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) {
if (asoc->fast_retran_loss_recovery &&
will_exit == 0 &&
(asoc->sctp_cmt_on_off == 0)) {
/*
* If we are in loss recovery we skip any cwnd
* update
@ -1372,7 +1382,8 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* CMT: CUC algorithm. Update cwnd if pseudo-cumack has
* moved.
*/
if (accum_moved || (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && net->new_pseudo_cumack)) {
if (accum_moved ||
((asoc->sctp_cmt_on_off == 1) && net->new_pseudo_cumack)) {
htcp_cong_avoid(stcb, net);
measure_achieved_throughput(stcb, net);
} else {
@ -1412,7 +1423,8 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
* (net->fast_retran_loss_recovery == 0)))
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if ((asoc->fast_retran_loss_recovery == 0) || (SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 1)) {
if ((asoc->fast_retran_loss_recovery == 0) ||
(asoc->sctp_cmt_on_off == 1)) {
/* out of a RFC2582 Fast recovery window? */
if (net->net_ack > 0) {
/*

View File

@ -2475,7 +2475,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 ((SCTP_BASE_SYSCTL(sctp_cmt_on_off)) &&
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
(SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) &&
(stcb->asoc.send_sack == 0) &&
(stcb->asoc.numduptsns == 0) &&
@ -3265,7 +3265,8 @@ 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 (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
if ((asoc->sctp_cmt_on_off == 1) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (net->saw_newack)
num_dests_sacked++;
@ -3381,7 +3382,8 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
tp1->sent++;
}
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
if ((asoc->sctp_cmt_on_off == 1) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*
* CMT DAC algorithm: If SACK flag is set to
* 0, then lowest_newack test will not pass
@ -3405,7 +3407,8 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tp1->sent++;
}
}
} else if ((tp1->rec.data.doing_fast_retransmit) && (SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0)) {
} else if ((tp1->rec.data.doing_fast_retransmit) &&
(asoc->sctp_cmt_on_off == 0)) {
/*
* For those that have done a FR we must take
* special consideration if we strike. I.e the
@ -3445,7 +3448,8 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tp1->sent++;
}
strike_flag = 1;
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
if ((asoc->sctp_cmt_on_off == 1) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*
* CMT DAC algorithm: If
* SACK flag is set to 0,
@ -3505,7 +3509,8 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
tp1->sent++;
}
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
if ((asoc->sctp_cmt_on_off == 1) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*
* CMT DAC algorithm: If SACK flag is set to
* 0, then lowest_newack test will not pass
@ -3584,7 +3589,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 (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
if (asoc->sctp_cmt_on_off == 1) {
/*
* CMT: Using RTX_SSTHRESH policy for CMT.
* If CMT is being used, then pick dest with
@ -3593,7 +3598,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tp1->no_fr_allowed = 1;
alt = tp1->whoTo;
/* sa_ignore NO_NULL_CHK */
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_pf)) {
if (asoc->sctp_cmt_pf > 0) {
/*
* JRS 5/18/07 - If CMT PF is on,
* use the PF version of
@ -4800,7 +4805,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
/*******************************************/
/* cancel ALL T3-send timer if accum moved */
/*******************************************/
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
if (asoc->sctp_cmt_on_off == 1) {
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (net->new_pseudo_cumack)
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
@ -5100,7 +5105,9 @@ 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 (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_use_dac) && (cmt_dac_flag == 0)) {
if ((asoc->sctp_cmt_on_off == 1) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac) &&
(cmt_dac_flag == 0)) {
this_sack_lowest_newack = cum_ack;
}
if ((num_seg > 0) || (num_nr_seg > 0)) {

View File

@ -618,16 +618,16 @@ 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 (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
(net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF) {
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
(stcb->asoc.sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_5);
}
net->dest_state &= ~SCTP_ADDR_PF;
net->cwnd = net->mtu * SCTP_BASE_SYSCTL(sctp_cmt_pf);
net->cwnd = net->mtu * stcb->asoc.sctp_cmt_pf;
SCTPDBG(SCTP_DEBUG_INPUT1, "Destination %p moved from PF to reachable with cwnd %d.\n",
net, net->cwnd);
}
@ -2723,6 +2723,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features;
inp->sctp_socket = so;
inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
inp->partial_delivery_point = (*inp_p)->partial_delivery_point;
inp->sctp_context = (*inp_p)->sctp_context;
inp->inp_starting_point_for_iterator = NULL;
@ -3067,7 +3068,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
struct sctp_nets *net, uint8_t flg)
{
switch (desc->chunk_type) {
case SCTP_DATA:
case SCTP_DATA:
/* find the tsn to resend (possibly */
{
uint32_t tsn;
@ -4586,8 +4587,6 @@ __attribute__((noinline))
return (NULL);
break;
case SCTP_SELECTIVE_ACK:
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n");
SCTP_STAT_INCR(sctps_recvsacks);
{
struct sctp_sack_chunk *sack;
int abort_now = 0;
@ -4597,6 +4596,8 @@ __attribute__((noinline))
int offset_seg, offset_dup;
int nonce_sum_flag;
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n");
SCTP_STAT_INCR(sctps_recvsacks);
if (stcb == NULL) {
SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n");
break;
@ -4673,8 +4674,6 @@ __attribute__((noinline))
* nr_sack chunk
*/
case SCTP_NR_SELECTIVE_ACK:
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n");
SCTP_STAT_INCR(sctps_recvsacks);
{
struct sctp_nr_sack_chunk *nr_sack;
int abort_now = 0;
@ -4684,13 +4683,10 @@ __attribute__((noinline))
int offset_seg, offset_dup;
int nonce_sum_flag;
/*
* EY nr_sacks have not been negotiated but
* the peer end sent an nr_sack, silently
* discard the chunk
*/
if (!(SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
stcb->asoc.peer_supports_nr_sack)) {
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n");
SCTP_STAT_INCR(sctps_recvsacks);
if ((stcb->asoc.sctp_nr_sack_on_off == 0) ||
(stcb->asoc.peer_supports_nr_sack == 0)) {
goto unknown_chunk;
}
if (stcb == NULL) {

View File

@ -3686,7 +3686,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
* Stop any running T3
* timers here?
*/
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_pf)) {
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Destination %p moved from PF to unreachable.\n",
net);
@ -4323,11 +4324,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
}
/*
* EY if the initiator supports nr_sacks, need to report that to
* responder in INIT chunk
*/
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) {
if (stcb->asoc.sctp_nr_sack_on_off == 1) {
pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
}
p_len = sizeof(*pr_supported) + num_ext;
@ -5447,10 +5444,6 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
if (!SCTP_BASE_SYSCTL(sctp_auth_disable))
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
/*
* EY if the sysctl variable is set, tell the assoc. initiator that
* we do nr_sack
*/
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off))
pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
p_len = sizeof(*pr_supported) + num_ext;
@ -7267,7 +7260,8 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
if (sp == NULL) {
break;
}
if ((sp->net != net) && (SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0)) {
if ((sp->net != net) &&
(asoc->sctp_cmt_on_off == 0)) {
/* none for this network */
if (locked) {
break;
@ -7326,11 +7320,11 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
*quit_now = 1;
if (total_moved == 0) {
if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) &&
if ((stcb->asoc.sctp_cmt_on_off == 0) &&
(net == stcb->asoc.primary_destination)) {
/* ran dry for primary network net */
SCTP_STAT_INCR(sctps_primary_randry);
} else if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
} else if (stcb->asoc.sctp_cmt_on_off == 1) {
/* ran dry with CMT on */
SCTP_STAT_INCR(sctps_cmt_randry);
}
@ -7363,7 +7357,8 @@ sctp_move_to_an_alt(struct sctp_tcb *stcb,
* destination using the PF algorithm for finding alternate
* destinations.
*/
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_pf)) {
if ((asoc->sctp_cmt_on_off == 1) &&
(asoc->sctp_cmt_pf > 0)) {
a_net = sctp_find_alternate_net(stcb, net, 2);
} else {
a_net = sctp_find_alternate_net(stcb, net, 0);
@ -7499,7 +7494,8 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
}
continue;
}
if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) && (net->ref_count < 2)) {
if ((asoc->sctp_cmt_on_off == 0) &&
(net->ref_count < 2)) {
/* nothing can be in queue for this guy */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
sctp_log_cwnd(stcb, net, 2,
@ -7534,7 +7530,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
*reason_code = 8;
return (0);
}
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
if (asoc->sctp_cmt_on_off == 1) {
/* get the last start point */
start_at = asoc->last_net_cmt_send_started;
if (start_at == NULL) {
@ -7560,7 +7556,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
break;
}
tsns_sent = 0xa;
if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) && (net->ref_count < 2)) {
if ((asoc->sctp_cmt_on_off == 0) && (net->ref_count < 2)) {
/*
* Ref-count of 1 so we cannot have data or control
* queued to this address. Skip it (non-CMT).
@ -8034,15 +8030,15 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
}
}
/* JRI: if dest is in PF state, do not send data to it */
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
if ((asoc->sctp_cmt_on_off == 1) &&
(asoc->sctp_cmt_pf > 0) &&
(net->dest_state & SCTP_ADDR_PF)) {
goto no_data_fill;
}
if (net->flight_size >= net->cwnd) {
goto no_data_fill;
}
if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off)) &&
if ((asoc->sctp_cmt_on_off == 1) &&
(net->flight_size > max_rwnd_per_dest)) {
goto no_data_fill;
}
@ -8096,7 +8092,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
break;
}
nchk = TAILQ_NEXT(chk, sctp_next);
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
if (asoc->sctp_cmt_on_off == 1) {
if (chk->whoTo != net) {
/*
* For CMT, steal the data
@ -8271,8 +8267,8 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
* restart it.
*/
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
} else if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
} else if ((asoc->sctp_cmt_on_off == 1) &&
(asoc->sctp_cmt_pf > 0) &&
pf_hbflag &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF) &&
(!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer))) {
@ -9579,8 +9575,8 @@ sctp_chunk_output(struct sctp_inpcb *inp,
*/
if (net->ref_count > 1)
sctp_move_to_an_alt(stcb, asoc, net);
} else if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
} else if ((asoc->sctp_cmt_on_off == 1) &&
(asoc->sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
/*
* JRS 5/14/07 - If CMT PF is on and the current
@ -9926,8 +9922,8 @@ sctp_send_sack(struct sctp_tcb *stcb)
uint8_t flags;
uint8_t type;
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
stcb->asoc.peer_supports_nr_sack) {
if ((stcb->asoc.sctp_nr_sack_on_off == 1) &&
(stcb->asoc.peer_supports_nr_sack == 1)) {
type = SCTP_NR_SELECTIVE_ACK;
} else {
type = SCTP_SELECTIVE_ACK;
@ -10071,7 +10067,8 @@ sctp_send_sack(struct sctp_tcb *stcb)
else
flags = 0;
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
if ((asoc->sctp_cmt_on_off == 1) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*-
* CMT DAC algorithm: If 2 (i.e., 0x10) packets have been
* received, then set high bit to 1, else 0. Reset
@ -10839,7 +10836,8 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net)
* heartbeat is being sent is in PF state, do NOT do threshold
* management.
*/
if ((SCTP_BASE_SYSCTL(sctp_cmt_pf) == 0) || ((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF)) {
if ((stcb->asoc.sctp_cmt_pf == 0) ||
((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF)) {
/* ok we have a destination that needs a beat */
/* lets do the theshold management Qiaobing style */
if (sctp_threshold_management(stcb->sctp_ep, stcb, net,
@ -12105,7 +12103,7 @@ sctp_sosend(struct socket *so,
struct sctp_sndrcvinfo srcv;
struct sockaddr *addr_to_use;
#ifdef INET6
#if defined(INET) && defined(INET6)
struct sockaddr_in sin;
#endif
@ -12120,7 +12118,7 @@ sctp_sosend(struct socket *so,
}
}
addr_to_use = addr;
#if defined(INET6) && !defined(__Userspace__) /* TODO port in6_sin6_2_sin */
#if defined(INET) && defined(INET6)
if ((addr) && (addr->sa_family == AF_INET6)) {
struct sockaddr_in6 *sin6;
@ -12212,20 +12210,33 @@ sctp_lower_sosend(struct socket *so,
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %d\n",
addr,
sndlen);
/*-
/**
* Pre-screen address, if one is given the sin-len
* must be set correctly!
*/
if (addr) {
if ((addr->sa_family == AF_INET) &&
(addr->sa_len != sizeof(struct sockaddr_in))) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
} else if ((addr->sa_family == AF_INET6) &&
(addr->sa_len != sizeof(struct sockaddr_in6))) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
switch (addr->sa_family) {
#if defined(INET)
case AF_INET:
if (addr->sa_len != sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
break;
#endif
#if defined(INET6)
case AF_INET6:
if (addr->sa_len != sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
break;
#endif
default:
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAFNOSUPPORT);
error = EAFNOSUPPORT;
goto out_unlocked;
}
}
@ -12657,7 +12668,8 @@ sctp_lower_sosend(struct socket *so,
error = EINVAL;
goto out_unlocked;
}
if ((net->flight_size > net->cwnd) && (SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0)) {
if ((net->flight_size > net->cwnd) &&
(asoc->sctp_cmt_on_off == 0)) {
/*-
* CMT: Added check for CMT above. net above is the primary
* dest. If CMT is ON, sender should always attempt to send
@ -13075,7 +13087,7 @@ sctp_lower_sosend(struct socket *so,
goto skip_out_eof;
}
if ((net->flight_size > net->cwnd) &&
(SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0)) {
(asoc->sctp_cmt_on_off == 0)) {
queue_only = 1;
} else if (asoc->ifp_had_enobuf) {
SCTP_STAT_INCR(sctps_ifnomemqueued);
@ -13349,7 +13361,7 @@ sctp_lower_sosend(struct socket *so,
some_on_control = 1;
}
if ((net->flight_size > net->cwnd) &&
(SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0)) {
(stcb->asoc.sctp_cmt_on_off == 0)) {
queue_only = 1;
} else if (asoc->ifp_had_enobuf) {
SCTP_STAT_INCR(sctps_ifnomemqueued);

View File

@ -2385,6 +2385,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
inp->sctp_associd_counter = 1;
inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT;
inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
/* init the small hash table we use to track asocid <-> tcb */
inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark);
if (inp->sctp_asocidhash == NULL) {
@ -6241,10 +6242,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
stcb->asoc.peer_supports_pktdrop = 1;
break;
case SCTP_NR_SELECTIVE_ACK:
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off))
stcb->asoc.peer_supports_nr_sack = 1;
else
stcb->asoc.peer_supports_nr_sack = 0;
stcb->asoc.peer_supports_nr_sack = 1;
break;
case SCTP_STREAM_RESET:
stcb->asoc.peer_supports_strreset = 1;

View File

@ -389,6 +389,7 @@ struct sctp_inpcb {
uint32_t sctp_frag_point;
uint32_t partial_delivery_point;
uint32_t sctp_context;
uint32_t sctp_cmt_on_off;
struct sctp_nonpad_sndrcvinfo def_send;
/*-
* These three are here for the sosend_dgram

View File

@ -112,6 +112,7 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
n_inp->sctp_features = inp->sctp_features;
n_inp->sctp_mobility_features = inp->sctp_mobility_features;
n_inp->sctp_frag_point = inp->sctp_frag_point;
n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
n_inp->partial_delivery_point = inp->partial_delivery_point;
n_inp->sctp_context = inp->sctp_context;
n_inp->inp_starting_point_for_iterator = NULL;
@ -183,6 +184,7 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
(SCTP_PCB_COPY_FLAGS & inp->sctp_flags));
n_inp->sctp_features = inp->sctp_features;
n_inp->sctp_frag_point = inp->sctp_frag_point;
n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
n_inp->partial_delivery_point = inp->partial_delivery_point;
n_inp->sctp_context = inp->sctp_context;
n_inp->inp_starting_point_for_iterator = NULL;

View File

@ -215,7 +215,8 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* not in PF state.
*/
/* Stop any running T3 timers here? */
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_pf)) {
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
net);
@ -419,7 +420,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
return (net);
}
min_errors_net->dest_state &= ~SCTP_ADDR_PF;
min_errors_net->cwnd = min_errors_net->mtu * SCTP_BASE_SYSCTL(sctp_cmt_pf);
min_errors_net->cwnd = min_errors_net->mtu * stcb->asoc.sctp_cmt_pf;
if (SCTP_OS_TIMER_PENDING(&min_errors_net->rxt_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, min_errors_net,
@ -843,7 +844,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
/*
* CMT: Do not allow FRs on retransmitted TSNs.
*/
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 1) {
if (stcb->asoc.sctp_cmt_on_off == 1) {
chk->no_fr_allowed = 1;
}
#ifdef THIS_SHOULD_NOT_BE_DONE
@ -1038,7 +1039,8 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
* addition, find an alternate destination with PF-based
* find_alt_net().
*/
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_pf)) {
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
if ((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF) {
net->dest_state |= SCTP_ADDR_PF;
net->last_active = sctp_get_tick_count();
@ -1046,7 +1048,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
net);
}
alt = sctp_find_alternate_net(stcb, net, 2);
} else if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
} else if (stcb->asoc.sctp_cmt_on_off == 1) {
/*
* CMT: Using RTX_SSTHRESH policy for CMT. If CMT is being
* used, then pick dest with largest ssthresh for any
@ -1162,7 +1164,9 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
}
}
} else if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_pf) && (net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF) {
} else if ((stcb->asoc.sctp_cmt_on_off == 1) &&
(stcb->asoc.sctp_cmt_pf > 0) &&
((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
/*
* JRS 5/14/07 - If the destination hasn't failed completely
* but is in PF state, a PF-heartbeat needs to be sent

View File

@ -300,7 +300,8 @@ sctp_notify(struct sctp_inpcb *inp,
* PF state.
*/
/* Stop any running T3 timers here? */
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_pf)) {
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
net);
@ -1736,42 +1737,14 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
struct sctp_assoc_value *av;
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
av->assoc_value = stcb->asoc.sctp_cmt_on_off;
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
av->assoc_value = stcb->asoc.sctp_cmt_on_off;
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
}
*optsize = sizeof(*av);
}
break;
/* EY - set socket option for nr_sacks */
case SCTP_NR_SACK_ON_OFF:
{
struct sctp_assoc_value *av;
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) {
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
av->assoc_value = stcb->asoc.sctp_nr_sack_on_off;
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
SCTP_INP_RLOCK(inp);
av->assoc_value = inp->sctp_cmt_on_off;
SCTP_INP_RUNLOCK(inp);
}
*optsize = sizeof(*av);
}
@ -2846,44 +2819,28 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
break;
case SCTP_CMT_ON_OFF:
{
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
struct sctp_assoc_value *av;
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
stcb->asoc.sctp_cmt_on_off = (uint8_t) av->assoc_value;
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
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;
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
}
}
break;
/* EY nr_sack_on_off socket option */
case SCTP_NR_SACK_ON_OFF:
{
struct sctp_assoc_value *av;
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) {
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
stcb->asoc.sctp_nr_sack_on_off = (uint8_t) av->assoc_value;
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
SCTP_INP_WLOCK(inp);
if (av->assoc_value != 0)
inp->sctp_cmt_on_off = 1;
else
inp->sctp_cmt_on_off = 0;
SCTP_INP_WUNLOCK(inp);
}
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
}
break;
/* JRS - Set socket option for pluggable congestion control */

View File

@ -893,10 +893,8 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->max_burst = m->sctp_ep.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 = (uint8_t) SCTP_BASE_SYSCTL(sctp_cmt_on_off);
/* EY Init nr_sack variable */
asoc->sctp_cmt_on_off = m->sctp_cmt_on_off;
asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
/* JRS 5/21/07 - Init CMT PF variables */
asoc->sctp_cmt_pf = (uint8_t) SCTP_BASE_SYSCTL(sctp_cmt_pf);
asoc->sctp_frag_point = m->sctp_frag_point;
#ifdef INET
@ -4213,7 +4211,7 @@ void
sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh)
{
switch (iph->ip_v) {
case IPVERSION:
case IPVERSION:
{
struct sockaddr_in lsa, fsa;

View File

@ -414,7 +414,8 @@ sctp6_notify(struct sctp_inpcb *inp,
* PF state.
*/
/* Stop any running T3 timers here? */
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_pf)) {
if ((stcb->asoc.sctp_cmt_on_off == 1) &&
(stcb->asoc.sctp_cmt_pf > 0)) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
net);
@ -1069,6 +1070,8 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
* Do the malloc first in case it blocks.
*/
SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
if (sin6 == NULL)
return ENOMEM;
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
@ -1173,6 +1176,8 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
return (ENOTCONN);
}
SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
if (sin6 == NULL)
return (ENOMEM);
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);