diff options
author | dim <dim@FreeBSD.org> | 2010-12-09 22:01:15 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2010-12-09 22:01:15 +0000 |
commit | a3786f65f1e2fa3a4e925fdb4b2b5544b9021bf9 (patch) | |
tree | 5f0a24f71baa3176c75a20a51a9e20a22c75426c /sys/netinet/sctp_indata.c | |
parent | ad01c620333d05c430d583ee40647e396be1ab91 (diff) | |
parent | 12dd9eb8e940c48f9fc30dbc137071b4fe5caead (diff) | |
download | FreeBSD-src-a3786f65f1e2fa3a4e925fdb4b2b5544b9021bf9.zip FreeBSD-src-a3786f65f1e2fa3a4e925fdb4b2b5544b9021bf9.tar.gz |
Sync: merge r216133 through r216338 from ^/head.
Diffstat (limited to 'sys/netinet/sctp_indata.c')
-rw-r--r-- | sys/netinet/sctp_indata.c | 69 |
1 files changed, 22 insertions, 47 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 05b40f7..bd484a7 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -3081,14 +3081,17 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct 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 *offset, struct sctp_tcb *stcb, struct } 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 offset_seg, int offset_dup, } } /********************************************/ - /* 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); |