This fixes PR-SCTP issues:

- Slide the map at the proper place.
 - Mark the bits in the nr_array ONLY if there
   is no marking.
 - When generating a FWD-TSN we allow us to skip past
   ACKED chunks too.

MFC after:	1 weeks
This commit is contained in:
Randall Stewart 2010-05-12 13:45:46 +00:00
parent 6a440fc3e0
commit 7898f4085c

View File

@ -3694,6 +3694,7 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
tp1 = TAILQ_FIRST(&asoc->sent_queue);
while (tp1) {
if (tp1->sent != SCTP_FORWARD_TSN_SKIP &&
tp1->sent != SCTP_DATAGRAM_ACKED &&
tp1->sent != SCTP_DATAGRAM_RESEND) {
/* no chance to advance, out of here */
break;
@ -5540,8 +5541,8 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
* report where we are.
*/
struct sctp_association *asoc;
uint32_t new_cum_tsn, tsn, gap;
unsigned int i, fwd_sz, cumack_set_flag, m_size, fnd = 0;
uint32_t new_cum_tsn, gap;
unsigned int i, fwd_sz, cumack_set_flag, m_size;
uint32_t str_seq;
struct sctp_stream_in *strm;
struct sctp_tmit_chunk *chk, *at;
@ -5565,15 +5566,6 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
/* Already got there ... */
return;
}
if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_map,
MAX_TSN)) {
asoc->highest_tsn_inside_map = new_cum_tsn;
}
if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_nr_map,
MAX_TSN)) {
asoc->highest_tsn_inside_nr_map = new_cum_tsn;
}
/*
* now we know the new TSN is more advanced, let's find the actual
* gap
@ -5628,35 +5620,15 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
for (i = 0; i <= gap; i++) {
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, i);
if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, i) &&
!SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, i)) {
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i);
/* FIX ME add something to set up highest TSN in map */
}
if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
asoc->highest_tsn_inside_nr_map = new_cum_tsn;
}
if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_map, MAX_TSN) ||
new_cum_tsn == asoc->highest_tsn_inside_map) {
/* We must back down to see what the new highest is */
for (tsn = new_cum_tsn; (compare_with_wrap(tsn, asoc->mapping_array_base_tsn, MAX_TSN) ||
(tsn == asoc->mapping_array_base_tsn)); tsn--) {
SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn);
if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
asoc->highest_tsn_inside_map = tsn;
fnd = 1;
break;
if (compare_with_wrap(asoc->mapping_array_base_tsn + i, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
asoc->highest_tsn_inside_nr_map = asoc->mapping_array_base_tsn + i;
}
}
if (!fnd) {
asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1;
}
}
/*
* Now after marking all, slide thing forward but no sack
* please.
*/
sctp_slide_mapping_arrays(stcb);
}
/*************************************************************/
/* 2. Clear up re-assembly queue */
/*************************************************************/
@ -5826,6 +5798,11 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
}
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
}
/*
* Now slide thing forward.
*/
sctp_slide_mapping_arrays(stcb);
if (TAILQ_FIRST(&asoc->reasmqueue)) {
/* now lets kick out and check for more fragmented delivery */
/* sa_ignore NO_NULL_CHK */