Fix a bug where also the number of non-renegable gap reports

was considered to be potentially renegable.

MFC after: 1 day.
This commit is contained in:
Michael Tuexen 2010-12-04 19:29:49 +00:00
parent f028d7f4c7
commit d9c5cfea61
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216188
3 changed files with 25 additions and 47 deletions

View File

@ -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 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
* 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 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
}
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);

View File

@ -4644,6 +4644,7 @@ __attribute__((noinline))
((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 @@ __attribute__((noinline))
((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

View File

@ -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;