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:
parent
f028d7f4c7
commit
d9c5cfea61
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user