More ECN fixes:
1) We now remove ECN-Nonce since it will no longer continue as a I-D 2) Eliminate last_tsn_echo, this tied us to an assoc not the net and thus we were not doing m-homing on the ECN-Echo senders side right. 3) Increment the count going out even if the TSN in lower in the pending ECN-Echo, this way the receiver knows exactly how many packets were marked even with network re-ordering 4) Fix so we DO NOT stop doing delayed sack if a ECN Echo is in queue MFC after: 1 month
This commit is contained in:
parent
c61aa7e8b3
commit
493d8e5a83
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=218129
@ -168,13 +168,6 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
|
||||
net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable Nonce Sum Checking and store the
|
||||
* resync tsn
|
||||
*/
|
||||
asoc->nonce_sum_check = 0;
|
||||
asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
|
||||
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
|
||||
stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
|
||||
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
|
||||
@ -489,25 +482,28 @@ sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
|
||||
}
|
||||
|
||||
static void
|
||||
sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net)
|
||||
sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
int in_window, int num_pkt_lost)
|
||||
{
|
||||
int old_cwnd = net->cwnd;
|
||||
|
||||
SCTP_STAT_INCR(sctps_ecnereducedcwnd);
|
||||
net->ssthresh = net->cwnd / 2;
|
||||
if (net->ssthresh < net->mtu) {
|
||||
net->ssthresh = net->mtu;
|
||||
/* here back off the timer as well, to slow us down */
|
||||
net->RTO <<= 1;
|
||||
}
|
||||
net->cwnd = net->ssthresh;
|
||||
SDT_PROBE(sctp, cwnd, net, ecn,
|
||||
stcb->asoc.my_vtag,
|
||||
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
|
||||
net,
|
||||
old_cwnd, net->cwnd);
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
|
||||
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
|
||||
if (in_window == 0) {
|
||||
SCTP_STAT_INCR(sctps_ecnereducedcwnd);
|
||||
net->ssthresh = net->cwnd / 2;
|
||||
if (net->ssthresh < net->mtu) {
|
||||
net->ssthresh = net->mtu;
|
||||
/* here back off the timer as well, to slow us down */
|
||||
net->RTO <<= 1;
|
||||
}
|
||||
net->cwnd = net->ssthresh;
|
||||
SDT_PROBE(sctp, cwnd, net, ecn,
|
||||
stcb->asoc.my_vtag,
|
||||
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
|
||||
net,
|
||||
old_cwnd, net->cwnd);
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
|
||||
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -888,13 +884,6 @@ sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
|
||||
net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable Nonce Sum Checking and store the
|
||||
* resync tsn
|
||||
*/
|
||||
asoc->nonce_sum_check = 0;
|
||||
asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
|
||||
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
|
||||
stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
|
||||
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
|
||||
@ -1609,13 +1598,6 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
|
||||
net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable Nonce Sum Checking and store the
|
||||
* resync tsn
|
||||
*/
|
||||
asoc->nonce_sum_check = 0;
|
||||
asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
|
||||
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
|
||||
stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
|
||||
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
|
||||
@ -1673,24 +1655,26 @@ sctp_htcp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
|
||||
|
||||
static void
|
||||
sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
|
||||
struct sctp_nets *net)
|
||||
struct sctp_nets *net, int in_window, int num_pkt_lost)
|
||||
{
|
||||
int old_cwnd;
|
||||
|
||||
old_cwnd = net->cwnd;
|
||||
|
||||
/* JRS - reset hctp as if state changed */
|
||||
htcp_reset(&net->htcp_ca);
|
||||
SCTP_STAT_INCR(sctps_ecnereducedcwnd);
|
||||
net->ssthresh = htcp_recalc_ssthresh(stcb, net);
|
||||
if (net->ssthresh < net->mtu) {
|
||||
net->ssthresh = net->mtu;
|
||||
/* here back off the timer as well, to slow us down */
|
||||
net->RTO <<= 1;
|
||||
}
|
||||
net->cwnd = net->ssthresh;
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
|
||||
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
|
||||
if (in_window == 0) {
|
||||
htcp_reset(&net->htcp_ca);
|
||||
SCTP_STAT_INCR(sctps_ecnereducedcwnd);
|
||||
net->ssthresh = htcp_recalc_ssthresh(stcb, net);
|
||||
if (net->ssthresh < net->mtu) {
|
||||
net->ssthresh = net->mtu;
|
||||
/* here back off the timer as well, to slow us down */
|
||||
net->RTO <<= 1;
|
||||
}
|
||||
net->cwnd = net->ssthresh;
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
|
||||
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,8 +411,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
/*************0x8000 series*************/
|
||||
#define SCTP_ECN_CAPABLE 0x8000
|
||||
/* ECN Nonce: draft-ladha-sctp-ecn-nonce */
|
||||
#define SCTP_ECN_NONCE_SUPPORTED 0x8001
|
||||
|
||||
/* draft-ietf-tsvwg-auth-xxx */
|
||||
#define SCTP_RANDOM 0x8002
|
||||
#define SCTP_CHUNK_LIST 0x8003
|
||||
|
@ -142,12 +142,6 @@ struct sctp_supported_chunk_types_param {
|
||||
} SCTP_PACKED;
|
||||
|
||||
|
||||
/* ECN Nonce: draft-ladha-sctp-ecn-nonce */
|
||||
struct sctp_ecn_nonce_supported_param {
|
||||
struct sctp_paramhdr ph;/* type = 0x8001 len = 4 */
|
||||
} SCTP_PACKED;
|
||||
|
||||
|
||||
/*
|
||||
* Structures for DATA chunks
|
||||
*/
|
||||
|
@ -2386,7 +2386,6 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap, int *abort_flag)
|
||||
{
|
||||
@ -2857,11 +2856,6 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
|
||||
* must be held until
|
||||
* cum-ack passes
|
||||
*/
|
||||
/*-
|
||||
* ECN Nonce: Add the nonce
|
||||
* value to the sender's
|
||||
* nonce sum
|
||||
*/
|
||||
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
|
||||
/*-
|
||||
* If it is less than RESEND, it is
|
||||
@ -2967,8 +2961,6 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
|
||||
}
|
||||
}
|
||||
if (tp1->sent <= SCTP_DATAGRAM_RESEND) {
|
||||
(*ecn_seg_sums) += tp1->rec.data.ect_nonce;
|
||||
(*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM;
|
||||
if (SCTP_TSN_GT(tp1->rec.data.TSN_seq,
|
||||
stcb->asoc.this_sack_highest_gap)) {
|
||||
stcb->asoc.this_sack_highest_gap =
|
||||
@ -3152,23 +3144,6 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
|
||||
if (tp1->sent == SCTP_DATAGRAM_UNSENT)
|
||||
break;
|
||||
}
|
||||
if (tot_revoked > 0) {
|
||||
/*
|
||||
* Setup the ecn nonce re-sync point. We do this since once
|
||||
* data is revoked we begin to retransmit things, which do
|
||||
* NOT have the ECN bits set. This means we are now out of
|
||||
* sync and must wait until we get back in sync with the
|
||||
* peer to check ECN bits.
|
||||
*/
|
||||
tp1 = TAILQ_FIRST(&asoc->send_queue);
|
||||
if (tp1 == NULL) {
|
||||
asoc->nonce_resync_tsn = asoc->sending_seq;
|
||||
} else {
|
||||
asoc->nonce_resync_tsn = tp1->rec.data.TSN_seq;
|
||||
}
|
||||
asoc->nonce_wait_for_ecne = 0;
|
||||
asoc->nonce_sum_check = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3604,17 +3579,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tot_retrans > 0) {
|
||||
/*
|
||||
* Setup the ecn nonce re-sync point. We do this since once
|
||||
* we go to FR something we introduce a Karn's rule scenario
|
||||
* and won't know the totals for the ECN bits.
|
||||
*/
|
||||
asoc->nonce_resync_tsn = sending_seq;
|
||||
asoc->nonce_wait_for_ecne = 0;
|
||||
asoc->nonce_sum_check = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct sctp_tmit_chunk *
|
||||
@ -3787,7 +3751,7 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb,
|
||||
|
||||
void
|
||||
sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
uint32_t rwnd, int nonce_sum_flag, int *abort_now)
|
||||
uint32_t rwnd, int *abort_now)
|
||||
{
|
||||
struct sctp_nets *net;
|
||||
struct sctp_association *asoc;
|
||||
@ -3901,11 +3865,6 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
if (tp1->sent == SCTP_DATAGRAM_UNSENT) {
|
||||
printf("Warning, an unsent is now acked?\n");
|
||||
}
|
||||
/*
|
||||
* ECN Nonce: Add the nonce to the sender's
|
||||
* nonce sum
|
||||
*/
|
||||
asoc->nonce_sum_expect_base += tp1->rec.data.ect_nonce;
|
||||
if (tp1->sent < SCTP_DATAGRAM_ACKED) {
|
||||
/*
|
||||
* If it is less than ACKED, it is
|
||||
@ -4049,53 +4008,6 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
asoc->total_flight = 0;
|
||||
asoc->total_flight_count = 0;
|
||||
}
|
||||
/* ECN Nonce updates */
|
||||
if (asoc->ecn_nonce_allowed) {
|
||||
if (asoc->nonce_sum_check) {
|
||||
if (nonce_sum_flag != ((asoc->nonce_sum_expect_base) & SCTP_SACK_NONCE_SUM)) {
|
||||
if (asoc->nonce_wait_for_ecne == 0) {
|
||||
struct sctp_tmit_chunk *lchk;
|
||||
|
||||
lchk = TAILQ_FIRST(&asoc->send_queue);
|
||||
asoc->nonce_wait_for_ecne = 1;
|
||||
if (lchk) {
|
||||
asoc->nonce_wait_tsn = lchk->rec.data.TSN_seq;
|
||||
} else {
|
||||
asoc->nonce_wait_tsn = asoc->sending_seq;
|
||||
}
|
||||
} else {
|
||||
if (SCTP_TSN_GE(asoc->last_acked_seq, asoc->nonce_wait_tsn)) {
|
||||
/*
|
||||
* Misbehaving peer. We need
|
||||
* to react to this guy
|
||||
*/
|
||||
asoc->ecn_allowed = 0;
|
||||
asoc->ecn_nonce_allowed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* See if Resynchronization Possible */
|
||||
if (SCTP_TSN_GT(asoc->last_acked_seq, asoc->nonce_resync_tsn)) {
|
||||
asoc->nonce_sum_check = 1;
|
||||
/*
|
||||
* Now we must calculate what the base is.
|
||||
* We do this based on two things, we know
|
||||
* the total's for all the segments
|
||||
* gap-acked in the SACK (none). We also
|
||||
* know the SACK's nonce sum, its in
|
||||
* nonce_sum_flag. So we can build a truth
|
||||
* table to back-calculate the new value of
|
||||
* asoc->nonce_sum_expect_base:
|
||||
*
|
||||
* SACK-flag-Value Seg-Sums Base 0 0 0
|
||||
* 1 0 1 0 1 1 1
|
||||
* 1 0
|
||||
*/
|
||||
asoc->nonce_sum_expect_base = (0 ^ nonce_sum_flag) & SCTP_SACK_NONCE_SUM;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* RWND update */
|
||||
asoc->peers_rwnd = sctp_sbspace_sub(rwnd,
|
||||
(uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh))));
|
||||
@ -4297,18 +4209,10 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
/* C3. See if we need to send a Fwd-TSN */
|
||||
if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cumack)) {
|
||||
/*
|
||||
* ISSUE with ECN, see FWD-TSN processing for notes
|
||||
* on issues that will occur when the ECN NONCE
|
||||
* stuff is put into SCTP for cross checking.
|
||||
* ISSUE with ECN, see FWD-TSN processing.
|
||||
*/
|
||||
if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, old_adv_peer_ack_point)) {
|
||||
send_forward_tsn(stcb, asoc);
|
||||
/*
|
||||
* ECN Nonce: Disable Nonce Sum check when
|
||||
* FWD TSN is sent and store resync tsn
|
||||
*/
|
||||
asoc->nonce_sum_check = 0;
|
||||
asoc->nonce_resync_tsn = asoc->advanced_peer_ack_point;
|
||||
} else if (lchk) {
|
||||
/* try to FR fwd-tsn's that get lost too */
|
||||
if (lchk->rec.data.fwd_tsn_cnt >= 3) {
|
||||
@ -4351,7 +4255,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
|
||||
int win_probe_recovery = 0;
|
||||
int win_probe_recovered = 0;
|
||||
struct sctp_nets *net = NULL;
|
||||
int nonce_sum_flag, ecn_seg_sums = 0;
|
||||
int ecn_seg_sums = 0;
|
||||
int done_once;
|
||||
uint8_t reneged_all = 0;
|
||||
uint8_t cmt_dac_flag;
|
||||
@ -4383,7 +4287,6 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
|
||||
j = 0;
|
||||
SCTP_STAT_INCR(sctps_slowpath_sack);
|
||||
last_tsn = cum_ack;
|
||||
nonce_sum_flag = flags & SCTP_SACK_NONCE_SUM;
|
||||
cmt_dac_flag = flags & SCTP_SACK_CMT_DAC;
|
||||
#ifdef SCTP_ASOCLOG_OF_TSNS
|
||||
stcb->asoc.cumack_log[stcb->asoc.cumack_log_at] = cum_ack;
|
||||
@ -4545,11 +4448,6 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
|
||||
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
|
||||
if (SCTP_TSN_GE(last_tsn, tp1->rec.data.TSN_seq)) {
|
||||
if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
|
||||
/*
|
||||
* ECN Nonce: Add the nonce to the sender's
|
||||
* nonce sum
|
||||
*/
|
||||
asoc->nonce_sum_expect_base += tp1->rec.data.ect_nonce;
|
||||
accum_moved = 1;
|
||||
if (tp1->sent < SCTP_DATAGRAM_ACKED) {
|
||||
/*
|
||||
@ -4999,60 +4897,6 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
|
||||
/* JRS - Use the congestion control given in the CC module */
|
||||
asoc->cc_functions.sctp_cwnd_update_after_fr(stcb, asoc);
|
||||
|
||||
/******************************************************************
|
||||
* Here we do the stuff with ECN Nonce checking.
|
||||
* We basically check to see if the nonce sum flag was incorrect
|
||||
* or if resynchronization needs to be done. Also if we catch a
|
||||
* misbehaving receiver we give him the kick.
|
||||
******************************************************************/
|
||||
|
||||
if (asoc->ecn_nonce_allowed) {
|
||||
if (asoc->nonce_sum_check) {
|
||||
if (nonce_sum_flag != ((asoc->nonce_sum_expect_base + ecn_seg_sums) & SCTP_SACK_NONCE_SUM)) {
|
||||
if (asoc->nonce_wait_for_ecne == 0) {
|
||||
struct sctp_tmit_chunk *lchk;
|
||||
|
||||
lchk = TAILQ_FIRST(&asoc->send_queue);
|
||||
asoc->nonce_wait_for_ecne = 1;
|
||||
if (lchk) {
|
||||
asoc->nonce_wait_tsn = lchk->rec.data.TSN_seq;
|
||||
} else {
|
||||
asoc->nonce_wait_tsn = asoc->sending_seq;
|
||||
}
|
||||
} else {
|
||||
if (SCTP_TSN_GE(asoc->last_acked_seq, asoc->nonce_wait_tsn)) {
|
||||
/*
|
||||
* Misbehaving peer. We need
|
||||
* to react to this guy
|
||||
*/
|
||||
asoc->ecn_allowed = 0;
|
||||
asoc->ecn_nonce_allowed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* See if Resynchronization Possible */
|
||||
if (SCTP_TSN_GT(asoc->last_acked_seq, asoc->nonce_resync_tsn)) {
|
||||
asoc->nonce_sum_check = 1;
|
||||
/*
|
||||
* now we must calculate what the base is.
|
||||
* We do this based on two things, we know
|
||||
* the total's for all the segments
|
||||
* gap-acked in the SACK, its stored in
|
||||
* ecn_seg_sums. We also know the SACK's
|
||||
* nonce sum, its in nonce_sum_flag. So we
|
||||
* can build a truth table to back-calculate
|
||||
* the new value of
|
||||
* asoc->nonce_sum_expect_base:
|
||||
*
|
||||
* SACK-flag-Value Seg-Sums Base 0 0 0
|
||||
* 1 0 1 0 1 1 1
|
||||
* 1 0
|
||||
*/
|
||||
asoc->nonce_sum_expect_base = (ecn_seg_sums ^ nonce_sum_flag) & SCTP_SACK_NONCE_SUM;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Now are we exiting loss recovery ? */
|
||||
if (will_exit_fast_recovery) {
|
||||
/* Ok, we must exit fast recovery */
|
||||
@ -5190,9 +5034,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
|
||||
/* C3. See if we need to send a Fwd-TSN */
|
||||
if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cum_ack)) {
|
||||
/*
|
||||
* ISSUE with ECN, see FWD-TSN processing for notes
|
||||
* on issues that will occur when the ECN NONCE
|
||||
* stuff is put into SCTP for cross checking.
|
||||
* ISSUE with ECN, see FWD-TSN processing.
|
||||
*/
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
|
||||
sctp_misc_ints(SCTP_FWD_TSN_CHECK,
|
||||
@ -5200,14 +5042,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
|
||||
old_adv_peer_ack_point);
|
||||
}
|
||||
if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, old_adv_peer_ack_point)) {
|
||||
|
||||
send_forward_tsn(stcb, asoc);
|
||||
/*
|
||||
* ECN Nonce: Disable Nonce Sum check when
|
||||
* FWD TSN is sent and store resync tsn
|
||||
*/
|
||||
asoc->nonce_sum_check = 0;
|
||||
asoc->nonce_resync_tsn = asoc->advanced_peer_ack_point;
|
||||
} else if (lchk) {
|
||||
/* try to FR fwd-tsn's that get lost too */
|
||||
if (lchk->rec.data.fwd_tsn_cnt >= 3) {
|
||||
@ -5242,7 +5077,7 @@ sctp_update_acked(struct sctp_tcb *stcb, struct sctp_shutdown_chunk *cp,
|
||||
a_rwnd = stcb->asoc.peers_rwnd + stcb->asoc.total_flight;
|
||||
|
||||
/* Now call the express sack handling */
|
||||
sctp_express_handle_sack(stcb, cum_ack, a_rwnd, 0, abort_flag);
|
||||
sctp_express_handle_sack(stcb, cum_ack, a_rwnd, abort_flag);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5384,17 +5219,6 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
|
||||
struct sctp_forward_tsn_chunk *fwd,
|
||||
int *abort_flag, struct mbuf *m, int offset)
|
||||
{
|
||||
/*
|
||||
* ISSUES that MUST be fixed for ECN! When we are the sender of the
|
||||
* forward TSN, when the SACK comes back that acknowledges the
|
||||
* FWD-TSN we must reset the NONCE sum to match correctly. This will
|
||||
* get quite tricky since we may have sent more data interveneing
|
||||
* and must carefully account for what the SACK says on the nonce
|
||||
* and any gaps that are reported. This work will NOT be done here,
|
||||
* but I note it here since it is really related to PR-SCTP and
|
||||
* FWD-TSN's
|
||||
*/
|
||||
|
||||
/* The pr-sctp fwd tsn */
|
||||
/*
|
||||
* here we will perform all the data receiver side steps for
|
||||
@ -5482,7 +5306,6 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
|
||||
sctp_log_map(0, 3, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
|
||||
}
|
||||
asoc->last_echo_tsn = asoc->highest_tsn_inside_map;
|
||||
} else {
|
||||
SCTP_TCB_LOCK_ASSERT(stcb);
|
||||
for (i = 0; i <= gap; i++) {
|
||||
|
@ -93,7 +93,7 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc);
|
||||
|
||||
void
|
||||
sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
uint32_t rwnd, int nonce_sum_flag, int *abort_now);
|
||||
uint32_t rwnd, int *abort_now);
|
||||
|
||||
void
|
||||
sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
|
||||
|
@ -264,11 +264,13 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
|
||||
/* save off parameters */
|
||||
asoc->peer_vtag = ntohl(init->initiate_tag);
|
||||
asoc->peers_rwnd = ntohl(init->a_rwnd);
|
||||
/* init tsn's */
|
||||
asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1;
|
||||
|
||||
if (!TAILQ_EMPTY(&asoc->nets)) {
|
||||
/* update any ssthresh's that may have a default */
|
||||
TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) {
|
||||
lnet->ssthresh = asoc->peers_rwnd;
|
||||
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
|
||||
sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION);
|
||||
}
|
||||
@ -328,8 +330,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
|
||||
}
|
||||
SCTP_TCB_SEND_UNLOCK(stcb);
|
||||
asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams;
|
||||
/* init tsn's */
|
||||
asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1;
|
||||
|
||||
/* EY - nr_sack: initialize highest tsn in nr_mapping_array */
|
||||
asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map;
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
|
||||
@ -340,7 +341,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
|
||||
|
||||
asoc->mapping_array_base_tsn = ntohl(init->initial_tsn);
|
||||
asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in;
|
||||
asoc->last_echo_tsn = asoc->asconf_seq_in;
|
||||
|
||||
asoc->advanced_peer_ack_point = asoc->last_acked_seq;
|
||||
/* open the requested streams */
|
||||
|
||||
@ -1044,11 +1045,6 @@ sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
|
||||
case SCTP_HAS_NAT_SUPPORT:
|
||||
stcb->asoc.peer_supports_nat = 0;
|
||||
break;
|
||||
case SCTP_ECN_NONCE_SUPPORTED:
|
||||
stcb->asoc.peer_supports_ecn_nonce = 0;
|
||||
stcb->asoc.ecn_nonce_allowed = 0;
|
||||
stcb->asoc.ecn_allowed = 0;
|
||||
break;
|
||||
case SCTP_ADD_IP_ADDRESS:
|
||||
case SCTP_DEL_IP_ADDRESS:
|
||||
case SCTP_SET_PRIM_ADDR:
|
||||
@ -2931,16 +2927,12 @@ sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
|
||||
SCTP_STAT_INCR(sctps_recvecne);
|
||||
tsn = ntohl(cp->tsn);
|
||||
pkt_cnt = ntohl(cp->num_pkts_since_cwr);
|
||||
/* ECN Nonce stuff: need a resync and disable the nonce sum check */
|
||||
/* Also we make sure we disable the nonce_wait */
|
||||
lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead);
|
||||
if (lchk == NULL) {
|
||||
window_data_tsn = stcb->asoc.nonce_resync_tsn = stcb->asoc.sending_seq - 1;
|
||||
window_data_tsn = stcb->asoc.sending_seq - 1;
|
||||
} else {
|
||||
window_data_tsn = stcb->asoc.nonce_resync_tsn = lchk->rec.data.TSN_seq;
|
||||
window_data_tsn = lchk->rec.data.TSN_seq;
|
||||
}
|
||||
stcb->asoc.nonce_wait_for_ecne = 0;
|
||||
stcb->asoc.nonce_sum_check = 0;
|
||||
|
||||
/* Find where it was sent to if possible. */
|
||||
net = NULL;
|
||||
@ -2974,7 +2966,8 @@ sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
|
||||
override_bit = SCTP_CWR_REDUCE_OVERRIDE;
|
||||
}
|
||||
out:
|
||||
if (SCTP_TSN_GT(tsn, net->cwr_window_tsn)) {
|
||||
if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) &&
|
||||
((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) {
|
||||
/*
|
||||
* JRS - Use the congestion control given in the pluggable
|
||||
* CC module
|
||||
@ -2982,7 +2975,7 @@ sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
|
||||
int ocwnd;
|
||||
|
||||
ocwnd = net->cwnd;
|
||||
stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net);
|
||||
stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt);
|
||||
/*
|
||||
* We reduce once every RTT. So we will only lower cwnd at
|
||||
* the next sending seq i.e. the window_data_tsn
|
||||
@ -2993,18 +2986,26 @@ sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
|
||||
net->last_cwr_tsn = tsn;
|
||||
} else {
|
||||
override_bit |= SCTP_CWR_IN_SAME_WINDOW;
|
||||
if (SCTP_TSN_GT(tsn, net->last_cwr_tsn)) {
|
||||
if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) &&
|
||||
((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) {
|
||||
/*
|
||||
* Another loss in the same window update how man
|
||||
* marks we have had
|
||||
* Another loss in the same window update how many
|
||||
* marks/packets lost we have had.
|
||||
*/
|
||||
int cnt = 1;
|
||||
|
||||
if (pkt_cnt > net->lost_cnt) {
|
||||
/* Should be the case */
|
||||
net->ecn_ce_pkt_cnt += (pkt_cnt - net->lost_cnt);
|
||||
net->lost_cnt = pkt_cnt;
|
||||
cnt = (pkt_cnt - net->lost_cnt);
|
||||
net->ecn_ce_pkt_cnt += cnt;
|
||||
}
|
||||
net->lost_cnt = pkt_cnt;
|
||||
net->last_cwr_tsn = tsn;
|
||||
/*
|
||||
* Most CC functions will ignore this call, since we
|
||||
* are in-window yet of the initial CE the peer saw.
|
||||
*/
|
||||
stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -3184,11 +3185,6 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We zero out the nonce so resync not
|
||||
* needed
|
||||
*/
|
||||
tp1->rec.data.ect_nonce = 0;
|
||||
|
||||
if (tp1->do_rtt) {
|
||||
/*
|
||||
@ -4643,7 +4639,6 @@ __attribute__((noinline))
|
||||
uint16_t num_seg, num_dup;
|
||||
uint8_t flags;
|
||||
int offset_seg, offset_dup;
|
||||
int nonce_sum_flag;
|
||||
|
||||
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n");
|
||||
SCTP_STAT_INCR(sctps_recvsacks);
|
||||
@ -4665,7 +4660,6 @@ __attribute__((noinline))
|
||||
}
|
||||
sack = (struct sctp_sack_chunk *)ch;
|
||||
flags = ch->chunk_flags;
|
||||
nonce_sum_flag = flags & SCTP_SACK_NONCE_SUM;
|
||||
cum_ack = ntohl(sack->sack.cum_tsn_ack);
|
||||
num_seg = ntohs(sack->sack.num_gap_ack_blks);
|
||||
num_dup = ntohs(sack->sack.num_dup_tsns);
|
||||
@ -4697,8 +4691,7 @@ __attribute__((noinline))
|
||||
* with no missing segments to go
|
||||
* this way too.
|
||||
*/
|
||||
sctp_express_handle_sack(stcb, cum_ack, a_rwnd, nonce_sum_flag,
|
||||
&abort_now);
|
||||
sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now);
|
||||
} else {
|
||||
if (netp && *netp)
|
||||
sctp_handle_sack(m, offset_seg, offset_dup,
|
||||
@ -4730,7 +4723,6 @@ __attribute__((noinline))
|
||||
uint16_t num_seg, num_nr_seg, num_dup;
|
||||
uint8_t flags;
|
||||
int offset_seg, offset_dup;
|
||||
int nonce_sum_flag;
|
||||
|
||||
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n");
|
||||
SCTP_STAT_INCR(sctps_recvsacks);
|
||||
@ -4756,8 +4748,6 @@ __attribute__((noinline))
|
||||
}
|
||||
nr_sack = (struct sctp_nr_sack_chunk *)ch;
|
||||
flags = ch->chunk_flags;
|
||||
nonce_sum_flag = flags & SCTP_SACK_NONCE_SUM;
|
||||
|
||||
cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack);
|
||||
num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks);
|
||||
num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks);
|
||||
@ -4789,7 +4779,7 @@ __attribute__((noinline))
|
||||
* missing segments to go this way
|
||||
* too.
|
||||
*/
|
||||
sctp_express_handle_sack(stcb, cum_ack, a_rwnd, nonce_sum_flag,
|
||||
sctp_express_handle_sack(stcb, cum_ack, a_rwnd,
|
||||
&abort_now);
|
||||
} else {
|
||||
if (netp && *netp)
|
||||
@ -5395,66 +5385,6 @@ __attribute__((noinline))
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process the ECN bits we have something set so we must look to see if it is
|
||||
* ECN(0) or ECN(1) or CE
|
||||
*/
|
||||
static void
|
||||
sctp_process_ecn_marked_a(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
uint8_t ecn_bits)
|
||||
{
|
||||
if ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS) {
|
||||
;
|
||||
} else if ((ecn_bits & SCTP_ECT1_BIT) == SCTP_ECT1_BIT) {
|
||||
/*
|
||||
* we only add to the nonce sum for ECT1, ECT0 does not
|
||||
* change the NS bit (that we have yet to find a way to send
|
||||
* it yet).
|
||||
*/
|
||||
|
||||
/* ECN Nonce stuff */
|
||||
stcb->asoc.receiver_nonce_sum++;
|
||||
stcb->asoc.receiver_nonce_sum &= SCTP_SACK_NONCE_SUM;
|
||||
|
||||
/*
|
||||
* Drag up the last_echo point if cumack is larger since we
|
||||
* don't want the point falling way behind by more than
|
||||
* 2^^31 and then having it be incorrect.
|
||||
*/
|
||||
if (SCTP_TSN_GT(stcb->asoc.cumulative_tsn, stcb->asoc.last_echo_tsn)) {
|
||||
stcb->asoc.last_echo_tsn = stcb->asoc.cumulative_tsn;
|
||||
}
|
||||
} else if ((ecn_bits & SCTP_ECT0_BIT) == SCTP_ECT0_BIT) {
|
||||
/*
|
||||
* Drag up the last_echo point if cumack is larger since we
|
||||
* don't want the point falling way behind by more than
|
||||
* 2^^31 and then having it be incorrect.
|
||||
*/
|
||||
if (SCTP_TSN_GT(stcb->asoc.cumulative_tsn, stcb->asoc.last_echo_tsn)) {
|
||||
stcb->asoc.last_echo_tsn = stcb->asoc.cumulative_tsn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sctp_process_ecn_marked_b(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
uint32_t high_tsn, uint8_t ecn_bits)
|
||||
{
|
||||
if ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS) {
|
||||
/*
|
||||
* we possibly must notify the sender that a congestion
|
||||
* window reduction is in order. We do this by adding a ECNE
|
||||
* chunk to the output chunk queue. The incoming CWR will
|
||||
* remove this chunk.
|
||||
*/
|
||||
if (SCTP_TSN_GT(high_tsn, stcb->asoc.last_echo_tsn)) {
|
||||
/* Yep, we need to add a ECNE */
|
||||
sctp_send_ecn_echo(stcb, net, high_tsn);
|
||||
stcb->asoc.last_echo_tsn = high_tsn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INVARIANTS
|
||||
#ifdef __GNUC__
|
||||
__attribute__((noinline))
|
||||
@ -5496,6 +5426,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
|
||||
struct mbuf *m = *mm;
|
||||
int abort_flag = 0;
|
||||
int un_sent;
|
||||
int cnt_ctrl_ready = 0;
|
||||
|
||||
SCTP_STAT_INCR(sctps_recvdatagrams);
|
||||
#ifdef SCTP_AUDITING_ENABLED
|
||||
@ -5653,11 +5584,6 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
|
||||
case SCTP_STATE_SHUTDOWN_SENT:
|
||||
break;
|
||||
}
|
||||
/* take care of ECN, part 1. */
|
||||
if (stcb->asoc.ecn_allowed &&
|
||||
(ecn_bits & (SCTP_ECT0_BIT | SCTP_ECT1_BIT))) {
|
||||
sctp_process_ecn_marked_a(stcb, net, ecn_bits);
|
||||
}
|
||||
/* plow through the data chunks while length > offset */
|
||||
retval = sctp_process_data(mm, iphlen, &offset, length, sh,
|
||||
inp, stcb, net, &high_tsn);
|
||||
@ -5669,19 +5595,16 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
|
||||
goto out_now;
|
||||
}
|
||||
data_processed = 1;
|
||||
if (retval == 0) {
|
||||
/* take care of ecn part 2. */
|
||||
if (stcb->asoc.ecn_allowed &&
|
||||
(ecn_bits & (SCTP_ECT0_BIT | SCTP_ECT1_BIT))) {
|
||||
sctp_process_ecn_marked_b(stcb, net, high_tsn,
|
||||
ecn_bits);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Anything important needs to have been m_copy'ed in
|
||||
* process_data
|
||||
*/
|
||||
}
|
||||
/* take care of ecn */
|
||||
if (stcb->asoc.ecn_allowed && ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) {
|
||||
/* Yep, we need to add a ECNE */
|
||||
sctp_send_ecn_echo(stcb, net, high_tsn);
|
||||
}
|
||||
if ((data_processed == 0) && (fwd_tsn_seen)) {
|
||||
int was_a_gap;
|
||||
uint32_t highest_tsn;
|
||||
@ -5713,8 +5636,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
|
||||
TAILQ_EMPTY(&stcb->asoc.control_send_queue),
|
||||
stcb->asoc.total_flight);
|
||||
un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight);
|
||||
|
||||
if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue) ||
|
||||
if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
|
||||
cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq;
|
||||
}
|
||||
if (cnt_ctrl_ready ||
|
||||
((un_sent) &&
|
||||
(stcb->asoc.peers_rwnd > 0 ||
|
||||
(stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) {
|
||||
|
@ -3389,55 +3389,10 @@ static uint8_t
|
||||
sctp_get_ect(struct sctp_tcb *stcb,
|
||||
struct sctp_tmit_chunk *chk)
|
||||
{
|
||||
uint8_t this_random;
|
||||
|
||||
/* Huh? */
|
||||
if (SCTP_BASE_SYSCTL(sctp_ecn_enable) == 0)
|
||||
return (0);
|
||||
|
||||
if (SCTP_BASE_SYSCTL(sctp_ecn_nonce) == 0)
|
||||
/* no nonce, always return ECT0 */
|
||||
return (SCTP_ECT0_BIT);
|
||||
|
||||
if (stcb->asoc.peer_supports_ecn_nonce == 0) {
|
||||
/* Peer does NOT support it, so we send a ECT0 only */
|
||||
return (SCTP_ECT0_BIT);
|
||||
}
|
||||
if (chk == NULL)
|
||||
return (SCTP_ECT0_BIT);
|
||||
|
||||
if ((stcb->asoc.hb_random_idx > 3) ||
|
||||
((stcb->asoc.hb_random_idx == 3) &&
|
||||
(stcb->asoc.hb_ect_randombit > 7))) {
|
||||
uint32_t rndval;
|
||||
|
||||
warp_drive_sa:
|
||||
rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep);
|
||||
memcpy(stcb->asoc.hb_random_values, &rndval,
|
||||
sizeof(stcb->asoc.hb_random_values));
|
||||
this_random = stcb->asoc.hb_random_values[0];
|
||||
stcb->asoc.hb_random_idx = 0;
|
||||
stcb->asoc.hb_ect_randombit = 0;
|
||||
} else {
|
||||
if (stcb->asoc.hb_ect_randombit > 7) {
|
||||
stcb->asoc.hb_ect_randombit = 0;
|
||||
stcb->asoc.hb_random_idx++;
|
||||
if (stcb->asoc.hb_random_idx > 3) {
|
||||
goto warp_drive_sa;
|
||||
}
|
||||
}
|
||||
this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
|
||||
}
|
||||
if ((this_random >> stcb->asoc.hb_ect_randombit) & 0x01) {
|
||||
if (chk != NULL)
|
||||
/* ECN Nonce stuff */
|
||||
chk->rec.data.ect_nonce = SCTP_ECT1_BIT;
|
||||
stcb->asoc.hb_ect_randombit++;
|
||||
return (SCTP_ECT1_BIT);
|
||||
} else {
|
||||
stcb->asoc.hb_ect_randombit++;
|
||||
return (SCTP_ECT0_BIT);
|
||||
}
|
||||
return (SCTP_ECT0_BIT);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -4167,7 +4122,6 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
struct sctp_adaptation_layer_indication *ali;
|
||||
struct sctp_ecn_supported_param *ecn;
|
||||
struct sctp_prsctp_supported_param *prsctp;
|
||||
struct sctp_ecn_nonce_supported_param *ecn_nonce;
|
||||
struct sctp_supported_chunk_types_param *pr_supported;
|
||||
int cnt_inits_to = 0;
|
||||
int padval, ret;
|
||||
@ -4326,14 +4280,6 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
|
||||
|
||||
|
||||
/* ECN nonce: And now tell the peer we support ECN nonce */
|
||||
if (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) {
|
||||
ecn_nonce = (struct sctp_ecn_nonce_supported_param *)
|
||||
((caddr_t)pr_supported + SCTP_SIZE32(p_len));
|
||||
ecn_nonce->ph.param_type = htons(SCTP_ECN_NONCE_SUPPORTED);
|
||||
ecn_nonce->ph.param_length = htons(sizeof(*ecn_nonce));
|
||||
SCTP_BUF_LEN(m) += sizeof(*ecn_nonce);
|
||||
}
|
||||
/* add authentication parameters */
|
||||
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
|
||||
struct sctp_auth_random *randp;
|
||||
@ -4555,11 +4501,10 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
|
||||
case SCTP_HAS_NAT_SUPPORT:
|
||||
*nat_friendly = 1;
|
||||
/* fall through */
|
||||
case SCTP_ECN_NONCE_SUPPORTED:
|
||||
case SCTP_PRSCTP_SUPPORTED:
|
||||
|
||||
if (padded_size != sizeof(struct sctp_paramhdr)) {
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error ecnnonce/prsctp/nat support %d\n", plen);
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error prsctp/nat support %d\n", plen);
|
||||
goto invalid_size;
|
||||
}
|
||||
at += padded_size;
|
||||
@ -4960,7 +4905,6 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
struct sctp_adaptation_layer_indication *ali;
|
||||
struct sctp_ecn_supported_param *ecn;
|
||||
struct sctp_prsctp_supported_param *prsctp;
|
||||
struct sctp_ecn_nonce_supported_param *ecn_nonce;
|
||||
struct sctp_supported_chunk_types_param *pr_supported;
|
||||
union sctp_sockstore store, store1, *over_addr;
|
||||
struct sockaddr_in *sin, *to_sin;
|
||||
@ -5444,14 +5388,6 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
bzero((caddr_t)pr_supported + p_len, SCTP_SIZE32(p_len) - p_len);
|
||||
SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
|
||||
|
||||
/* ECN nonce: And now tell the peer we support ECN nonce */
|
||||
if (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) {
|
||||
ecn_nonce = (struct sctp_ecn_nonce_supported_param *)
|
||||
((caddr_t)pr_supported + SCTP_SIZE32(p_len));
|
||||
ecn_nonce->ph.param_type = htons(SCTP_ECN_NONCE_SUPPORTED);
|
||||
ecn_nonce->ph.param_length = htons(sizeof(*ecn_nonce));
|
||||
SCTP_BUF_LEN(m) += sizeof(*ecn_nonce);
|
||||
}
|
||||
/* add authentication parameters */
|
||||
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
|
||||
struct sctp_auth_random *randp;
|
||||
@ -7009,7 +6945,6 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
chk->rec.data.payloadtype = sp->ppid;
|
||||
chk->rec.data.context = sp->context;
|
||||
chk->rec.data.doing_fast_retransmit = 0;
|
||||
chk->rec.data.ect_nonce = 0; /* ECN Nonce */
|
||||
|
||||
chk->rec.data.timetodrop = sp->ts;
|
||||
chk->flags = sp->act_flags;
|
||||
@ -10000,13 +9935,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
|
||||
limit = mtod(a_chk->data, caddr_t);
|
||||
limit += space;
|
||||
|
||||
/* 0x01 is used by nonce for ecn */
|
||||
if ((SCTP_BASE_SYSCTL(sctp_ecn_enable)) &&
|
||||
(SCTP_BASE_SYSCTL(sctp_ecn_nonce)) &&
|
||||
(asoc->peer_supports_ecn_nonce))
|
||||
flags = (asoc->receiver_nonce_sum & SCTP_SACK_NONCE_SUM);
|
||||
else
|
||||
flags = 0;
|
||||
flags = 0;
|
||||
|
||||
if ((asoc->sctp_cmt_on_off > 0) &&
|
||||
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
|
||||
@ -10809,11 +10738,11 @@ sctp_send_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
ctsn = ntohl(ecne->tsn);
|
||||
if (SCTP_TSN_GT(high_tsn, ctsn)) {
|
||||
ecne->tsn = htonl(high_tsn);
|
||||
cnt = ntohl(ecne->num_pkts_since_cwr);
|
||||
cnt++;
|
||||
ecne->num_pkts_since_cwr = htonl(cnt);
|
||||
SCTP_STAT_INCR(sctps_queue_upd_ecne);
|
||||
}
|
||||
cnt = ntohl(ecne->num_pkts_since_cwr);
|
||||
cnt++;
|
||||
ecne->num_pkts_since_cwr = htonl(cnt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -6139,10 +6139,6 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
|
||||
}
|
||||
}
|
||||
} else if (ptype == SCTP_ECN_NONCE_SUPPORTED) {
|
||||
/* Peer supports ECN-nonce */
|
||||
stcb->asoc.peer_supports_ecn_nonce = 1;
|
||||
stcb->asoc.ecn_nonce_allowed = 1;
|
||||
} else if (ptype == SCTP_RANDOM) {
|
||||
if (plen > sizeof(random_store))
|
||||
break;
|
||||
|
@ -330,8 +330,6 @@ struct sctp_data_chunkrec {
|
||||
uint32_t payloadtype;
|
||||
uint32_t context; /* from send */
|
||||
|
||||
/* ECN Nonce: Nonce Value for this chunk */
|
||||
uint8_t ect_nonce;
|
||||
uint8_t fwd_tsn_cnt;
|
||||
/*
|
||||
* part of the Highest sacked algorithm to be able to stroke counts
|
||||
@ -607,7 +605,7 @@ struct sctp_cc_functions {
|
||||
void (*sctp_cwnd_update_after_timeout) (struct sctp_tcb *stcb,
|
||||
struct sctp_nets *net);
|
||||
void (*sctp_cwnd_update_after_ecn_echo) (struct sctp_tcb *stcb,
|
||||
struct sctp_nets *net);
|
||||
struct sctp_nets *net, int in_window, int num_pkt_lost);
|
||||
void (*sctp_cwnd_update_after_packet_dropped) (struct sctp_tcb *stcb,
|
||||
struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
|
||||
uint32_t * bottle_bw, uint32_t * on_queue);
|
||||
@ -866,7 +864,6 @@ struct sctp_association {
|
||||
uint8_t *nr_mapping_array;
|
||||
uint32_t highest_tsn_inside_nr_map;
|
||||
|
||||
uint32_t last_echo_tsn;
|
||||
uint32_t fast_recovery_tsn;
|
||||
uint32_t sat_t3_recovery_tsn;
|
||||
uint32_t tsn_last_delivered;
|
||||
@ -921,12 +918,9 @@ struct sctp_association {
|
||||
uint32_t sb_send_resv; /* amount reserved on a send */
|
||||
uint32_t my_rwnd_control_len; /* shadow of sb_mbcnt used for rwnd
|
||||
* control */
|
||||
/* 32 bit nonce stuff */
|
||||
uint32_t nonce_resync_tsn;
|
||||
uint32_t nonce_wait_tsn;
|
||||
uint32_t default_flowlabel;
|
||||
uint32_t pr_sctp_cnt;
|
||||
int ctrl_queue_cnt; /* could be removed REM */
|
||||
int ctrl_queue_cnt; /* could be removed REM - NO IT CAN'T!! RRS */
|
||||
/*
|
||||
* All outbound datagrams queue into this list from the individual
|
||||
* stream queue. Here they get assigned a TSN and then await
|
||||
@ -1075,20 +1069,13 @@ struct sctp_association {
|
||||
uint8_t default_tos;
|
||||
uint8_t asconf_del_pending; /* asconf delete last addr pending */
|
||||
|
||||
/* ECN Nonce stuff */
|
||||
uint8_t receiver_nonce_sum; /* nonce I sum and put in my sack */
|
||||
uint8_t ecn_nonce_allowed; /* Tells us if ECN nonce is on */
|
||||
uint8_t nonce_sum_check;/* On off switch used during re-sync */
|
||||
uint8_t nonce_wait_for_ecne; /* flag when we expect a ECN */
|
||||
uint8_t peer_supports_ecn_nonce;
|
||||
|
||||
/*
|
||||
* This value, plus all other ack'd but above cum-ack is added
|
||||
* together to cross check against the bit that we have yet to
|
||||
* define (probably in the SACK). When the cum-ack is updated, this
|
||||
* sum is updated as well.
|
||||
*/
|
||||
uint8_t nonce_sum_expect_base;
|
||||
|
||||
/* Flag to tell if ECN is allowed */
|
||||
uint8_t ecn_allowed;
|
||||
|
||||
|
@ -52,7 +52,6 @@ sctp_init_sysctls()
|
||||
SCTP_BASE_SYSCTL(sctp_auto_asconf) = SCTPCTL_AUTOASCONF_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_multiple_asconfs) = SCTPCTL_MULTIPLEASCONFS_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_ecn_nonce) = SCTPCTL_ECN_NONCE_DEFAULT;
|
||||
SCTP_BASE_SYSCTL(sctp_strict_sacks) = SCTPCTL_STRICT_SACKS_DEFAULT;
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) = SCTPCTL_LOOPBACK_NOCSUM_DEFAULT;
|
||||
@ -570,7 +569,6 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_recvspace), SCTPCTL_RECVSPACE_MIN, SCTPCTL_RECVSPACE_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_enable), SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_nonce), SCTPCTL_ECN_NONCE_MIN, SCTPCTL_ECN_NONCE_MAX);
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_sacks), SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX);
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
RANGECHK(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), SCTPCTL_LOOPBACK_NOCSUM_MIN, SCTPCTL_LOOPBACK_NOCSUM_MAX);
|
||||
@ -829,10 +827,6 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, ecn_enable, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_ecn_enable), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_ECN_ENABLE_DESC);
|
||||
|
||||
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, ecn_nonce, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_ecn_nonce), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_ECN_NONCE_DESC);
|
||||
|
||||
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_UINT | CTLFLAG_RW,
|
||||
&SCTP_BASE_SYSCTL(sctp_strict_sacks), 0, sysctl_sctp_check, "IU",
|
||||
SCTPCTL_STRICT_SACKS_DESC);
|
||||
|
@ -43,7 +43,7 @@ struct sctp_sysctl {
|
||||
uint32_t sctp_auto_asconf;
|
||||
uint32_t sctp_multiple_asconfs;
|
||||
uint32_t sctp_ecn_enable;
|
||||
uint32_t sctp_ecn_nonce;
|
||||
uint32_t sctp_not_used;
|
||||
uint32_t sctp_strict_sacks;
|
||||
#if !defined(SCTP_WITH_NO_CSUM)
|
||||
uint32_t sctp_no_csum_on_loopback;
|
||||
@ -152,12 +152,6 @@ struct sctp_sysctl {
|
||||
#define SCTPCTL_ECN_ENABLE_MAX 1
|
||||
#define SCTPCTL_ECN_ENABLE_DEFAULT 1
|
||||
|
||||
/* ecn_nonce: Enable SCTP ECN Nonce */
|
||||
#define SCTPCTL_ECN_NONCE_DESC "Enable SCTP ECN Nonce"
|
||||
#define SCTPCTL_ECN_NONCE_MIN 0
|
||||
#define SCTPCTL_ECN_NONCE_MAX 1
|
||||
#define SCTPCTL_ECN_NONCE_DEFAULT 0
|
||||
|
||||
/* strict_sacks: Enable SCTP Strict SACK checking */
|
||||
#define SCTPCTL_STRICT_SACKS_DESC "Enable SCTP Strict SACK checking"
|
||||
#define SCTPCTL_STRICT_SACKS_MIN 0
|
||||
|
@ -934,19 +934,6 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Setup the ecn nonce re-sync point. We do this since
|
||||
* retranmissions are NOT setup for ECN. This means that do to
|
||||
* Karn's rule, we don't know the total of the peers ecn bits.
|
||||
*/
|
||||
chk = TAILQ_FIRST(&stcb->asoc.send_queue);
|
||||
if (chk == NULL) {
|
||||
stcb->asoc.nonce_resync_tsn = stcb->asoc.sending_seq;
|
||||
} else {
|
||||
stcb->asoc.nonce_resync_tsn = chk->rec.data.TSN_seq;
|
||||
}
|
||||
stcb->asoc.nonce_wait_for_ecne = 0;
|
||||
stcb->asoc.nonce_sum_check = 0;
|
||||
/* We return 1 if we only have a window probe outstanding */
|
||||
return (0);
|
||||
}
|
||||
@ -1144,11 +1131,6 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
|
||||
lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc);
|
||||
/* C3. See if we need to send a Fwd-TSN */
|
||||
if (SCTP_TSN_GT(stcb->asoc.advanced_peer_ack_point, stcb->asoc.last_acked_seq)) {
|
||||
/*
|
||||
* ISSUE with ECN, see FWD-TSN processing for notes
|
||||
* on issues that will occur when the ECN NONCE
|
||||
* stuff is put into SCTP for cross checking.
|
||||
*/
|
||||
send_forward_tsn(stcb, &stcb->asoc);
|
||||
if (lchk) {
|
||||
/* Assure a timer is up */
|
||||
|
@ -987,16 +987,9 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
|
||||
asoc->free_chunk_cnt = 0;
|
||||
|
||||
asoc->iam_blocking = 0;
|
||||
/* ECN Nonce initialization */
|
||||
|
||||
asoc->context = m->sctp_context;
|
||||
asoc->def_send = m->def_send;
|
||||
asoc->ecn_nonce_allowed = 0;
|
||||
asoc->receiver_nonce_sum = 1;
|
||||
asoc->nonce_sum_expect_base = 1;
|
||||
asoc->nonce_sum_check = 1;
|
||||
asoc->nonce_resync_tsn = 0;
|
||||
asoc->nonce_wait_for_ecne = 0;
|
||||
asoc->nonce_wait_tsn = 0;
|
||||
asoc->delayed_ack = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
|
||||
asoc->sack_freq = m->sctp_ep.sctp_sack_freq;
|
||||
asoc->pr_sctp_cnt = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user