From owner-svn-src-stable-8@FreeBSD.ORG Sat Apr 17 03:38:26 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B6DBC1065673; Sat, 17 Apr 2010 03:38:26 +0000 (UTC) (envelope-from rrs@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A3CFE8FC0C; Sat, 17 Apr 2010 03:38:26 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o3H3cQTW035474; Sat, 17 Apr 2010 03:38:26 GMT (envelope-from rrs@svn.freebsd.org) Received: (from rrs@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o3H3cQ7w035472; Sat, 17 Apr 2010 03:38:26 GMT (envelope-from rrs@svn.freebsd.org) Message-Id: <201004170338.o3H3cQ7w035472@svn.freebsd.org> From: Randall Stewart Date: Sat, 17 Apr 2010 03:38:26 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r206723 - stable/8/sys/netinet X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 Apr 2010 03:38:26 -0000 Author: rrs Date: Sat Apr 17 03:38:26 2010 New Revision: 206723 URL: http://svn.freebsd.org/changeset/base/206723 Log: Merge of SVN 196507. This optimizes the sack handling a bit and restructures it so its much more readable ;-) Modified: stable/8/sys/netinet/sctp_indata.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/netinet/sctp_indata.c ============================================================================== --- stable/8/sys/netinet/sctp_indata.c Sat Apr 17 03:14:00 2010 (r206722) +++ stable/8/sys/netinet/sctp_indata.c Sat Apr 17 03:38:26 2010 (r206723) @@ -2525,6 +2525,7 @@ sctp_sack_check(struct sctp_tcb *stcb, i */ struct sctp_association *asoc; int at; + uint8_t comb_byte; int last_all_ones = 0; int slide_from, slide_end, lgap, distance; @@ -2555,7 +2556,6 @@ sctp_sack_check(struct sctp_tcb *stcb, i memcpy(aux_array, asoc->mapping_array, 64); /* EY do the same for nr_mapping_array */ if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - if (asoc->nr_mapping_array_size != asoc->mapping_array_size) { /* * printf("\nEY-IN sack_check method: \nEY-" "The @@ -2582,13 +2582,18 @@ sctp_sack_check(struct sctp_tcb *stcb, i */ at = 0; for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) { - - if (asoc->mapping_array[slide_from] == 0xff) { + /* + * We must combine the renegable and non-renegable arrays + * here to form a unified view of what is acked right now + * (since they are kept separate + */ + comb_byte = asoc->mapping_array[slide_from] | asoc->nr_mapping_array[slide_from]; + if (comb_byte == 0xff) { at += 8; last_all_ones = 1; } else { /* there is a 0 bit */ - at += sctp_map_lookup_tab[asoc->mapping_array[slide_from]]; + at += sctp_map_lookup_tab[comb_byte]; last_all_ones = 0; break; } @@ -3182,6 +3187,235 @@ sctp_process_data(struct mbuf **mm, int return (0); } +static int +sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1, uint32_t last_tsn, + uint16_t frag_strt, uint16_t frag_end, int nr_sacking, + int *num_frs, + uint32_t * biggest_newly_acked_tsn, + uint32_t * this_sack_lowest_newack, + int *ecn_seg_sums) +{ + struct sctp_tmit_chunk *tp1; + unsigned int theTSN; + int j, wake_him = 0; + + /* Recover the tp1 we last saw */ + tp1 = *p_tp1; + if (tp1 == NULL) { + tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); + } + for (j = frag_strt; j <= frag_end; j++) { + theTSN = j + last_tsn; + while (tp1) { + if (tp1->rec.data.doing_fast_retransmit) + (*num_frs) += 1; + + /*- + * CMT: CUCv2 algorithm. For each TSN being + * processed from the sent queue, track the + * next expected pseudo-cumack, or + * rtx_pseudo_cumack, if required. Separate + * cumack trackers for first transmissions, + * and retransmissions. + */ + if ((tp1->whoTo->find_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) && + (tp1->snd_count == 1)) { + tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq; + tp1->whoTo->find_pseudo_cumack = 0; + } + if ((tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) && + (tp1->snd_count > 1)) { + tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq; + tp1->whoTo->find_rtx_pseudo_cumack = 0; + } + if (tp1->rec.data.TSN_seq == theTSN) { + if (tp1->sent != SCTP_DATAGRAM_UNSENT) { + /*- + * 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 + * now no-longer in flight. + * Higher values may already be set + * via previous Gap Ack Blocks... + * i.e. ACKED or RESEND. + */ + if (compare_with_wrap(tp1->rec.data.TSN_seq, + *biggest_newly_acked_tsn, MAX_TSN)) { + *biggest_newly_acked_tsn = tp1->rec.data.TSN_seq; + } + /*- + * CMT: SFR algo (and HTNA) - set + * saw_newack to 1 for dest being + * newly acked. update + * this_sack_highest_newack if + * appropriate. + */ + if (tp1->rec.data.chunk_was_revoked == 0) + tp1->whoTo->saw_newack = 1; + + if (compare_with_wrap(tp1->rec.data.TSN_seq, + tp1->whoTo->this_sack_highest_newack, + MAX_TSN)) { + tp1->whoTo->this_sack_highest_newack = + tp1->rec.data.TSN_seq; + } + /*- + * CMT DAC algo: also update + * this_sack_lowest_newack + */ + if (*this_sack_lowest_newack == 0) { + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { + sctp_log_sack(*this_sack_lowest_newack, + last_tsn, + tp1->rec.data.TSN_seq, + 0, + 0, + SCTP_LOG_TSN_ACKED); + } + *this_sack_lowest_newack = tp1->rec.data.TSN_seq; + } + /*- + * CMT: CUCv2 algorithm. If (rtx-)pseudo-cumack for corresp + * dest is being acked, then we have a new (rtx-)pseudo-cumack. Set + * new_(rtx_)pseudo_cumack to TRUE so that the cwnd for this dest can be + * updated. Also trigger search for the next expected (rtx-)pseudo-cumack. + * Separate pseudo_cumack trackers for first transmissions and + * retransmissions. + */ + if (tp1->rec.data.TSN_seq == tp1->whoTo->pseudo_cumack) { + if (tp1->rec.data.chunk_was_revoked == 0) { + tp1->whoTo->new_pseudo_cumack = 1; + } + tp1->whoTo->find_pseudo_cumack = 1; + } + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { + sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); + } + if (tp1->rec.data.TSN_seq == tp1->whoTo->rtx_pseudo_cumack) { + if (tp1->rec.data.chunk_was_revoked == 0) { + tp1->whoTo->new_pseudo_cumack = 1; + } + tp1->whoTo->find_rtx_pseudo_cumack = 1; + } + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { + sctp_log_sack(*biggest_newly_acked_tsn, + last_tsn, + tp1->rec.data.TSN_seq, + frag_strt, + frag_end, + SCTP_LOG_TSN_ACKED); + } + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP, + tp1->whoTo->flight_size, + tp1->book_size, + (uintptr_t) tp1->whoTo, + tp1->rec.data.TSN_seq); + } + sctp_flight_size_decrease(tp1); + sctp_total_flight_decrease(stcb, tp1); + + tp1->whoTo->net_ack += tp1->send_size; + if (tp1->snd_count < 2) { + /*- + * True non-retransmited chunk + */ + tp1->whoTo->net_ack2 += tp1->send_size; + + /*- + * update RTO too ? + */ + if (tp1->do_rtt) { + tp1->whoTo->RTO = + sctp_calculate_rto(stcb, + &stcb->asoc, + tp1->whoTo, + &tp1->sent_rcv_time, + sctp_align_safe_nocopy); + tp1->do_rtt = 0; + } + } + } + if (tp1->sent <= SCTP_DATAGRAM_RESEND) { + (*ecn_seg_sums) += tp1->rec.data.ect_nonce; + (*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM; + if (compare_with_wrap(tp1->rec.data.TSN_seq, + stcb->asoc.this_sack_highest_gap, + MAX_TSN)) { + stcb->asoc.this_sack_highest_gap = + tp1->rec.data.TSN_seq; + } + if (tp1->sent == SCTP_DATAGRAM_RESEND) { + sctp_ucount_decr(stcb->asoc.sent_queue_retran_cnt); +#ifdef SCTP_AUDITING_ENABLED + sctp_audit_log(0xB2, + (stcb->asoc.sent_queue_retran_cnt & 0x000000ff)); +#endif + } + } + /*- + * All chunks NOT UNSENT fall through here and are marked + * (leave PR-SCTP ones that are to skip alone though) + */ + if (tp1->sent != SCTP_FORWARD_TSN_SKIP) + tp1->sent = SCTP_DATAGRAM_MARKED; + + if (tp1->rec.data.chunk_was_revoked) { + /* deflate the cwnd */ + tp1->whoTo->cwnd -= tp1->book_size; + tp1->rec.data.chunk_was_revoked = 0; + } + /* NR Sack code here */ + if (nr_sacking) { + if (tp1->sent != SCTP_FORWARD_TSN_SKIP) + tp1->sent = SCTP_DATAGRAM_NR_MARKED; + /* + * TAILQ_REMOVE(&asoc->sent_q + * ueue, tp1, sctp_next); + */ + if (tp1->data) { + /* + * sa_ignore + * NO_NULL_CHK + */ + sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); + sctp_m_freem(tp1->data); + } + tp1->data = NULL; + /* asoc->sent_queue_cnt--; */ + /* + * sctp_free_a_chunk(stcb, + * tp1); + */ + wake_him++; + } + } + break; + } /* if (tp1->TSN_seq == theTSN) */ + if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN, + MAX_TSN)) + break; + + tp1 = TAILQ_NEXT(tp1, sctp_next); + } /* end while (tp1) */ + /* In case the fragments were not in order we must reset */ + if (tp1 == NULL) { + tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); + } + } /* end for (j = fragStart */ + *p_tp1 = tp1; + return (wake_him); /* Return value only used for nr-sack */ +} + + static void sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_sack_chunk *ch, uint32_t last_tsn, uint32_t * biggest_tsn_acked, @@ -3194,8 +3428,7 @@ sctp_handle_segments(struct mbuf *m, int struct sctp_sack *sack; struct sctp_gap_ack_block *frag, block; struct sctp_tmit_chunk *tp1; - int i, j; - unsigned int theTSN; + int i; int num_frs = 0; uint16_t frag_strt, frag_end, primary_flag_set; @@ -3263,214 +3496,9 @@ sctp_handle_segments(struct mbuf *m, int } last_frag_high = frag_end + last_tsn; } - for (j = frag_strt; j <= frag_end; j++) { - theTSN = j + last_tsn; - while (tp1) { - if (tp1->rec.data.doing_fast_retransmit) - num_frs++; - - /* - * CMT: CUCv2 algorithm. For each TSN being - * processed from the sent queue, track the - * next expected pseudo-cumack, or - * rtx_pseudo_cumack, if required. Separate - * cumack trackers for first transmissions, - * and retransmissions. - */ - if ((tp1->whoTo->find_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) && - (tp1->snd_count == 1)) { - tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq; - tp1->whoTo->find_pseudo_cumack = 0; - } - if ((tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) && - (tp1->snd_count > 1)) { - tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq; - tp1->whoTo->find_rtx_pseudo_cumack = 0; - } - if (tp1->rec.data.TSN_seq == theTSN) { - if (tp1->sent != SCTP_DATAGRAM_UNSENT) { - /* - * 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 - * now no-longer in flight. - * Higher values may already be set - * via previous Gap Ack Blocks... - * i.e. ACKED or RESEND. - */ - if (compare_with_wrap(tp1->rec.data.TSN_seq, - *biggest_newly_acked_tsn, MAX_TSN)) { - *biggest_newly_acked_tsn = tp1->rec.data.TSN_seq; - } - /* - * CMT: SFR algo - * (and HTNA) - set - * saw_newack to 1 - * for dest being - * newly acked. - * update - * this_sack_highest_ - * newack if - * appropriate. - */ - if (tp1->rec.data.chunk_was_revoked == 0) - tp1->whoTo->saw_newack = 1; - - if (compare_with_wrap(tp1->rec.data.TSN_seq, - tp1->whoTo->this_sack_highest_newack, - MAX_TSN)) { - tp1->whoTo->this_sack_highest_newack = - tp1->rec.data.TSN_seq; - } - /* - * CMT DAC algo: - * also update - * this_sack_lowest_n - * ewack - */ - if (*this_sack_lowest_newack == 0) { - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { - sctp_log_sack(*this_sack_lowest_newack, - last_tsn, - tp1->rec.data.TSN_seq, - 0, - 0, - SCTP_LOG_TSN_ACKED); - } - *this_sack_lowest_newack = tp1->rec.data.TSN_seq; - } - /* - * CMT: CUCv2 - * algorithm. If - * (rtx-)pseudo-cumac - * k for corresp - * dest is being - * acked, then we - * have a new - * (rtx-)pseudo-cumac - * k. Set - * new_(rtx_)pseudo_c - * umack to TRUE so - * that the cwnd for - * this dest can be - * updated. Also - * trigger search - * for the next - * expected - * (rtx-)pseudo-cumac - * k. Separate - * pseudo_cumack - * trackers for - * first - * transmissions and - * retransmissions. - */ - if (tp1->rec.data.TSN_seq == tp1->whoTo->pseudo_cumack) { - if (tp1->rec.data.chunk_was_revoked == 0) { - tp1->whoTo->new_pseudo_cumack = 1; - } - tp1->whoTo->find_pseudo_cumack = 1; - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { - sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); - } - if (tp1->rec.data.TSN_seq == tp1->whoTo->rtx_pseudo_cumack) { - if (tp1->rec.data.chunk_was_revoked == 0) { - tp1->whoTo->new_pseudo_cumack = 1; - } - tp1->whoTo->find_rtx_pseudo_cumack = 1; - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { - sctp_log_sack(*biggest_newly_acked_tsn, - last_tsn, - tp1->rec.data.TSN_seq, - frag_strt, - frag_end, - SCTP_LOG_TSN_ACKED); - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { - sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP, - tp1->whoTo->flight_size, - tp1->book_size, - (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); - } - sctp_flight_size_decrease(tp1); - sctp_total_flight_decrease(stcb, tp1); - - tp1->whoTo->net_ack += tp1->send_size; - if (tp1->snd_count < 2) { - /* - * True - * non-retran - * smited - * chunk */ - tp1->whoTo->net_ack2 += tp1->send_size; - - /* - * update RTO - * too ? */ - if (tp1->do_rtt) { - tp1->whoTo->RTO = - sctp_calculate_rto(stcb, - asoc, - tp1->whoTo, - &tp1->sent_rcv_time, - sctp_align_safe_nocopy); - tp1->do_rtt = 0; - } - } - } - if (tp1->sent <= SCTP_DATAGRAM_RESEND) { - (*ecn_seg_sums) += tp1->rec.data.ect_nonce; - (*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM; - if (compare_with_wrap(tp1->rec.data.TSN_seq, - asoc->this_sack_highest_gap, - MAX_TSN)) { - asoc->this_sack_highest_gap = - tp1->rec.data.TSN_seq; - } - if (tp1->sent == SCTP_DATAGRAM_RESEND) { - sctp_ucount_decr(asoc->sent_queue_retran_cnt); -#ifdef SCTP_AUDITING_ENABLED - sctp_audit_log(0xB2, - (asoc->sent_queue_retran_cnt & 0x000000ff)); -#endif - } - } - /* - * All chunks NOT UNSENT - * fall through here and are - * marked (leave PR-SCTP - * ones that are to skip - * alone though) - */ - if (tp1->sent != SCTP_FORWARD_TSN_SKIP) - tp1->sent = SCTP_DATAGRAM_MARKED; - - if (tp1->rec.data.chunk_was_revoked) { - /* deflate the cwnd */ - tp1->whoTo->cwnd -= tp1->book_size; - tp1->rec.data.chunk_was_revoked = 0; - } - } - break; - } /* if (tp1->TSN_seq == theTSN) */ - if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN, - MAX_TSN)) - break; - - tp1 = TAILQ_NEXT(tp1, sctp_next); - } /* end while (tp1) */ - } /* end for (j = fragStart */ + sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end, + 0, &num_frs, biggest_newly_acked_tsn, + this_sack_lowest_newack, ecn_seg_sums); frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset, sizeof(struct sctp_gap_ack_block), (uint8_t *) & block); *offset += sizeof(block); @@ -6855,9 +6883,8 @@ sctp_handle_nr_sack_segments(struct mbuf struct sctp_gap_ack_block *frag, block; struct sctp_nr_gap_ack_block *nr_frag, nr_block; struct sctp_tmit_chunk *tp1; - uint32_t i, j; + uint32_t i; int wake_him = 0; - uint32_t theTSN; int num_frs = 0; uint16_t frag_strt, frag_end, primary_flag_set; @@ -6932,213 +6959,9 @@ sctp_handle_nr_sack_segments(struct mbuf } last_frag_high = frag_end + last_tsn; } - for (j = frag_strt; j <= frag_end; j++) { - theTSN = j + last_tsn; - while (tp1) { - if (tp1->rec.data.doing_fast_retransmit) - num_frs++; - - /* - * CMT: CUCv2 algorithm. For each TSN being - * processed from the sent queue, track the - * next expected pseudo-cumack, or - * rtx_pseudo_cumack, if required. Separate - * cumack trackers for first transmissions, - * and retransmissions. - */ - if ((tp1->whoTo->find_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) && - (tp1->snd_count == 1)) { - tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq; - tp1->whoTo->find_pseudo_cumack = 0; - } - if ((tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) && - (tp1->snd_count > 1)) { - tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq; - tp1->whoTo->find_rtx_pseudo_cumack = 0; - } - if (tp1->rec.data.TSN_seq == theTSN) { - if (tp1->sent != SCTP_DATAGRAM_UNSENT) { - /* - * 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 - * now no-longer in flight. - * Higher values may already be set - * via previous Gap Ack Blocks... - * i.e. ACKED or RESEND. - */ - if (compare_with_wrap(tp1->rec.data.TSN_seq, - *biggest_newly_acked_tsn, MAX_TSN)) { - *biggest_newly_acked_tsn = tp1->rec.data.TSN_seq; - } - /* - * CMT: SFR algo - * (and HTNA) - set - * saw_newack to 1 - * for dest being - * newly acked. - * update - * this_sack_highest_ - * newack if - * appropriate. - */ - if (tp1->rec.data.chunk_was_revoked == 0) - tp1->whoTo->saw_newack = 1; - - if (compare_with_wrap(tp1->rec.data.TSN_seq, - tp1->whoTo->this_sack_highest_newack, - MAX_TSN)) { - tp1->whoTo->this_sack_highest_newack = - tp1->rec.data.TSN_seq; - } - /* - * CMT DAC algo: - * also update - * this_sack_lowest_n - * ewack - */ - if (*this_sack_lowest_newack == 0) { - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { - sctp_log_sack(*this_sack_lowest_newack, - last_tsn, - tp1->rec.data.TSN_seq, - 0, - 0, - SCTP_LOG_TSN_ACKED); - } - *this_sack_lowest_newack = tp1->rec.data.TSN_seq; - } - /* - * CMT: CUCv2 - * algorithm. If - * (rtx-)pseudo-cumac - * k for corresp - * dest is being - * acked, then we - * have a new - * (rtx-)pseudo-cumac - * k. Set - * new_(rtx_)pseudo_c - * umack to TRUE so - * that the cwnd for - * this dest can be - * updated. Also - * trigger search - * for the next - * expected - * (rtx-)pseudo-cumac - * k. Separate - * pseudo_cumack - * trackers for - * first - * transmissions and - * retransmissions. - */ - if (tp1->rec.data.TSN_seq == tp1->whoTo->pseudo_cumack) { - if (tp1->rec.data.chunk_was_revoked == 0) { - tp1->whoTo->new_pseudo_cumack = 1; - } - tp1->whoTo->find_pseudo_cumack = 1; - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { - sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); - } - if (tp1->rec.data.TSN_seq == tp1->whoTo->rtx_pseudo_cumack) { - if (tp1->rec.data.chunk_was_revoked == 0) { - tp1->whoTo->new_pseudo_cumack = 1; - } - tp1->whoTo->find_rtx_pseudo_cumack = 1; - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { - sctp_log_sack(*biggest_newly_acked_tsn, - last_tsn, - tp1->rec.data.TSN_seq, - frag_strt, - frag_end, - SCTP_LOG_TSN_ACKED); - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { - sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP, - tp1->whoTo->flight_size, - tp1->book_size, - (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); - } - sctp_flight_size_decrease(tp1); - sctp_total_flight_decrease(stcb, tp1); - - tp1->whoTo->net_ack += tp1->send_size; - if (tp1->snd_count < 2) { - /* - * True - * non-retran - * smited - * chunk - */ - tp1->whoTo->net_ack2 += tp1->send_size; - - /* - * update - * RTO too ? - */ - if (tp1->do_rtt) { - tp1->whoTo->RTO = - sctp_calculate_rto(stcb, - asoc, - tp1->whoTo, - &tp1->sent_rcv_time, - sctp_align_safe_nocopy); - tp1->do_rtt = 0; - } - } - } - if (tp1->sent <= SCTP_DATAGRAM_RESEND) { - (*ecn_seg_sums) += tp1->rec.data.ect_nonce; - (*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM; - if (compare_with_wrap(tp1->rec.data.TSN_seq, - asoc->this_sack_highest_gap, - MAX_TSN)) { - asoc->this_sack_highest_gap = - tp1->rec.data.TSN_seq; - } - if (tp1->sent == SCTP_DATAGRAM_RESEND) { - sctp_ucount_decr(asoc->sent_queue_retran_cnt); -#ifdef SCTP_AUDITING_ENABLED - sctp_audit_log(0xB2, - (asoc->sent_queue_retran_cnt & 0x000000ff)); -#endif - } - } - /* - * All chunks NOT UNSENT - * fall through here and are - * marked - */ - if (tp1->sent != SCTP_FORWARD_TSN_SKIP) - tp1->sent = SCTP_DATAGRAM_NR_MARKED; - if (tp1->rec.data.chunk_was_revoked) { - /* deflate the cwnd */ - tp1->whoTo->cwnd -= tp1->book_size; - tp1->rec.data.chunk_was_revoked = 0; - } - } - break; - } /* if (tp1->TSN_seq == theTSN) */ - if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN, - MAX_TSN)) - break; - - tp1 = TAILQ_NEXT(tp1, sctp_next); - } /* end while (tp1) */ - } /* end for (j = fragStart */ + sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end, + 0, &num_frs, biggest_newly_acked_tsn, + this_sack_lowest_newack, ecn_seg_sums); frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset, sizeof(struct sctp_gap_ack_block), (uint8_t *) & block); *offset += sizeof(block); @@ -7164,6 +6987,8 @@ sctp_handle_nr_sack_segments(struct mbuf } tp1 = NULL; last_nr_frag_high = 0; + /* Reset to beginning for the nr_sack section */ + tp1 = TAILQ_FIRST(&asoc->sent_queue); for (i = 0; i < num_nr_seg; i++) { @@ -7207,45 +7032,15 @@ sctp_handle_nr_sack_segments(struct mbuf } last_nr_frag_high = nr_frag_end + last_tsn; } - - for (j = nr_frag_strt + last_tsn; (compare_with_wrap((nr_frag_end + last_tsn), j, MAX_TSN)); j++) { - while (tp1) { - if (tp1->rec.data.TSN_seq == j) { - if (tp1->sent != SCTP_DATAGRAM_UNSENT) { - if (tp1->sent != SCTP_FORWARD_TSN_SKIP) - tp1->sent = SCTP_DATAGRAM_NR_MARKED; - /* - * TAILQ_REMOVE(&asoc->sent_q - * ueue, tp1, sctp_next); - */ - if (tp1->data) { - /* - * sa_ignore - * NO_NULL_CHK - */ - sctp_free_bufspace(stcb, asoc, tp1, 1); - sctp_m_freem(tp1->data); - } - tp1->data = NULL; - /* asoc->sent_queue_cnt--; */ - /* - * sctp_free_a_chunk(stcb, - * tp1); - */ - wake_him++; - } - break; - } /* if (tp1->TSN_seq == j) */ - if (compare_with_wrap(tp1->rec.data.TSN_seq, j, - MAX_TSN)) - break; - tp1 = TAILQ_NEXT(tp1, sctp_next); - } /* end while (tp1) */ - - } /* end for (j = nrFragStart */ + num_frs = 0; + wake_him = sctp_process_segment_range(stcb, &tp1, last_tsn, + nr_frag_strt, nr_frag_end, 1, + &num_frs, biggest_newly_acked_tsn, + this_sack_lowest_newack, ecn_seg_sums); nr_frag = (struct sctp_nr_gap_ack_block *)sctp_m_getptr(m, *offset, - sizeof(struct sctp_nr_gap_ack_block), (uint8_t *) & nr_block); + sizeof(struct sctp_nr_gap_ack_block), + (uint8_t *) & nr_block); *offset += sizeof(nr_block); if (nr_frag == NULL) { break;