diff options
author | tuexen <tuexen@FreeBSD.org> | 2010-08-28 17:59:51 +0000 |
---|---|---|
committer | tuexen <tuexen@FreeBSD.org> | 2010-08-28 17:59:51 +0000 |
commit | 8d90bd696f6ffe32185cc58c210e1cb2b6b40466 (patch) | |
tree | 3c18fb8c6c88a9d89b4532f1a0b0ed84a8db9c07 /sys/netinet | |
parent | 9d21e17f07e784c9d5c0c2ed6a0a0c75431f76eb (diff) | |
download | FreeBSD-src-8d90bd696f6ffe32185cc58c210e1cb2b6b40466.zip FreeBSD-src-8d90bd696f6ffe32185cc58c210e1cb2b6b40466.tar.gz |
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
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/sctp.h | 4 | ||||
-rw-r--r-- | sys/netinet/sctp_cc_functions.c | 48 | ||||
-rw-r--r-- | sys/netinet/sctp_indata.c | 27 | ||||
-rw-r--r-- | sys/netinet/sctp_input.c | 28 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 100 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 6 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.h | 1 | ||||
-rw-r--r-- | sys/netinet/sctp_peeloff.c | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_timer.c | 16 | ||||
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 95 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 6 |
11 files changed, 159 insertions, 174 deletions
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h index ce5ac0a..1335e82 100644 --- a/sys/netinet/sctp.h +++ b/sys/netinet/sctp.h @@ -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 diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c index 8beff19..1cba25a 100644 --- a/sys/netinet/sctp_cc_functions.c +++ b/sys/netinet/sctp_cc_functions.c @@ -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) { /* diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index e429da8..12fba8b 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -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 @@ done_with_it: * 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)) { diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 8b2a9d5..089c9b6 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -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 @@ process_control_chunks: 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 @@ process_control_chunks: 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 @@ process_control_chunks: * 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 @@ process_control_chunks: 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) { diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 7038067..aa771a6 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -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 @@ do_a_abort: 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 @@ again_one_more_time: 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 @@ again_one_more_time: } } /* 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 @@ again_one_more_time: 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 @@ no_data_fill: * 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 @@ skip_preblock: 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 @@ skip_out_eof: 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); diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index ad8bc52..846f55d 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -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; diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index 318b012..23ebc4f 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -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 diff --git a/sys/netinet/sctp_peeloff.c b/sys/netinet/sctp_peeloff.c index 6f899b4..69d04c0 100644 --- a/sys/netinet/sctp_peeloff.c +++ b/sys/netinet/sctp_peeloff.c @@ -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; diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index 2921272..e2bd5bb 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -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 @@ start_again: /* * 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 diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 46cfa3d..2ed66af 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -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 @@ flags_out: 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; - } - } 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; - } + 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; + 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; - } - } 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; - } + 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; + 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 */ diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index e390fb1..95bbe36 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -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; |