From owner-svn-src-all@FreeBSD.ORG Sat Dec 4 19:29:50 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 18BE0106564A; Sat, 4 Dec 2010 19:29:50 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 067928FC08; Sat, 4 Dec 2010 19:29:50 +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 oB4JTnfL005792; Sat, 4 Dec 2010 19:29:49 GMT (envelope-from tuexen@svn.freebsd.org) Received: (from tuexen@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oB4JTn4p005788; Sat, 4 Dec 2010 19:29:49 GMT (envelope-from tuexen@svn.freebsd.org) Message-Id: <201012041929.oB4JTn4p005788@svn.freebsd.org> From: Michael Tuexen Date: Sat, 4 Dec 2010 19:29:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r216188 - head/sys/netinet X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Dec 2010 19:29:50 -0000 Author: tuexen Date: Sat Dec 4 19:29:49 2010 New Revision: 216188 URL: http://svn.freebsd.org/changeset/base/216188 Log: Fix a bug where also the number of non-renegable gap reports was considered to be potentially renegable. MFC after: 1 day. Modified: head/sys/netinet/sctp_indata.c head/sys/netinet/sctp_input.c head/sys/netinet/sctp_structs.h Modified: head/sys/netinet/sctp_indata.c ============================================================================== --- head/sys/netinet/sctp_indata.c Sat Dec 4 18:52:05 2010 (r216187) +++ head/sys/netinet/sctp_indata.c Sat Dec 4 19:29:49 2010 (r216188) @@ -3081,14 +3081,17 @@ sctp_handle_segments(struct mbuf *m, int int num_frs = 0; int chunk_freed; int non_revocable; - uint16_t frag_strt, frag_end; - uint32_t last_frag_high; + uint16_t frag_strt, frag_end, prev_frag_end; - tp1 = NULL; - last_frag_high = 0; + tp1 = TAILQ_FIRST(&asoc->sent_queue); + prev_frag_end = 0; chunk_freed = 0; for (i = 0; i < (num_seg + num_nr_seg); i++) { + if (i == num_seg) { + prev_frag_end = 0; + tp1 = TAILQ_FIRST(&asoc->sent_queue); + } frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset, sizeof(struct sctp_gap_ack_block), (uint8_t *) & block); *offset += sizeof(block); @@ -3097,58 +3100,29 @@ sctp_handle_segments(struct mbuf *m, int } frag_strt = ntohs(frag->start); frag_end = ntohs(frag->end); - /* some sanity checks on the fragment offsets */ + if (frag_strt > frag_end) { - /* this one is malformed, skip */ + /* This gap report is malformed, skip it. */ continue; } - if (compare_with_wrap((frag_end + last_tsn), *biggest_tsn_acked, - MAX_TSN)) - *biggest_tsn_acked = frag_end + last_tsn; - - /* mark acked dgs and find out the highestTSN being acked */ - if (tp1 == NULL) { + if (frag_strt <= prev_frag_end) { + /* This gap report is not in order, so restart. */ tp1 = TAILQ_FIRST(&asoc->sent_queue); - /* save the locations of the last frags */ - last_frag_high = frag_end + last_tsn; - } else { - /* - * now lets see if we need to reset the queue due to - * a out-of-order SACK fragment - */ - if (compare_with_wrap(frag_strt + last_tsn, - last_frag_high, MAX_TSN)) { - /* - * if the new frag starts after the last TSN - * frag covered, we are ok and this one is - * beyond the last one - */ - ; - } else { - /* - * ok, they have reset us, so we need to - * reset the queue this will cause extra - * hunting but hey, they chose the - * performance hit when they failed to order - * their gaps - */ - tp1 = TAILQ_FIRST(&asoc->sent_queue); - } - last_frag_high = frag_end + last_tsn; + } + if (compare_with_wrap((last_tsn + frag_end), *biggest_tsn_acked, MAX_TSN)) { + *biggest_tsn_acked = last_tsn + frag_end; } if (i < num_seg) { non_revocable = 0; } else { non_revocable = 1; } - if (i == num_seg) { - tp1 = NULL; - } if (sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end, non_revocable, &num_frs, biggest_newly_acked_tsn, this_sack_lowest_newack, ecn_seg_sums)) { chunk_freed = 1; } + prev_frag_end = frag_end; } if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { if (num_frs) @@ -4817,7 +4791,7 @@ sctp_handle_sack(struct mbuf *m, int off } } /********************************************/ - /* drop the acked chunks from the sendqueue */ + /* drop the acked chunks from the sentqueue */ /********************************************/ asoc->last_acked_seq = cum_ack; @@ -4925,9 +4899,10 @@ done_with_it: * we had some before and now we have NONE. */ - if (num_seg) + if (num_seg) { sctp_check_for_revoked(stcb, asoc, cum_ack, biggest_tsn_acked); - else if (asoc->saw_sack_with_frags) { + asoc->saw_sack_with_frags = 1; + } else if (asoc->saw_sack_with_frags) { int cnt_revoked = 0; tp1 = TAILQ_FIRST(&asoc->sent_queue); @@ -4963,10 +4938,10 @@ done_with_it: } asoc->saw_sack_with_frags = 0; } - if (num_seg || num_nr_seg) - asoc->saw_sack_with_frags = 1; + if (num_nr_seg > 0) + asoc->saw_sack_with_nr_frags = 1; else - asoc->saw_sack_with_frags = 0; + asoc->saw_sack_with_nr_frags = 0; /* JRS - Use the congestion control given in the CC module */ asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery); Modified: head/sys/netinet/sctp_input.c ============================================================================== --- head/sys/netinet/sctp_input.c Sat Dec 4 18:52:05 2010 (r216187) +++ head/sys/netinet/sctp_input.c Sat Dec 4 19:29:49 2010 (r216188) @@ -4644,6 +4644,7 @@ process_control_chunks: ((compare_with_wrap(cum_ack, stcb->asoc.last_acked_seq, MAX_TSN)) || (cum_ack == stcb->asoc.last_acked_seq)) && (stcb->asoc.saw_sack_with_frags == 0) && + (stcb->asoc.saw_sack_with_nr_frags == 0) && (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) ) { /* @@ -4737,6 +4738,7 @@ process_control_chunks: ((compare_with_wrap(cum_ack, stcb->asoc.last_acked_seq, MAX_TSN)) || (cum_ack == stcb->asoc.last_acked_seq)) && (stcb->asoc.saw_sack_with_frags == 0) && + (stcb->asoc.saw_sack_with_nr_frags == 0) && (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) { /* * We have a SIMPLE sack having no Modified: head/sys/netinet/sctp_structs.h ============================================================================== --- head/sys/netinet/sctp_structs.h Sat Dec 4 18:52:05 2010 (r216187) +++ head/sys/netinet/sctp_structs.h Sat Dec 4 19:29:49 2010 (r216188) @@ -1058,6 +1058,7 @@ struct sctp_association { uint8_t delayed_connection; uint8_t ifp_had_enobuf; uint8_t saw_sack_with_frags; + uint8_t saw_sack_with_nr_frags; uint8_t in_asocid_hash; uint8_t assoc_up_sent; uint8_t adaptation_needed;