From 7898f4085ce21a7ed72de2839a9f1d28a7fb0f24 Mon Sep 17 00:00:00 2001 From: Randall Stewart Date: Wed, 12 May 2010 13:45:46 +0000 Subject: [PATCH] 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 --- sys/netinet/sctp_indata.c | 49 +++++++++++---------------------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 2ed6c1660d7a..e1194c8e229a 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -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,34 +5620,14 @@ 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); - 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 (!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); + 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 */