diff options
author | rrs <rrs@FreeBSD.org> | 2010-05-12 13:45:46 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2010-05-12 13:45:46 +0000 |
commit | 078a73da4612d564f4479fae47df46408e712db7 (patch) | |
tree | 51a24cda3a6b781469f9212cb9a7e62d5273c950 /sys/netinet | |
parent | 7c190c1c89d45ca83db4120a8a5fe107a8a52050 (diff) | |
download | FreeBSD-src-078a73da4612d564f4479fae47df46408e712db7.zip FreeBSD-src-078a73da4612d564f4479fae47df46408e712db7.tar.gz |
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
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/sctp_indata.c | 49 |
1 files changed, 13 insertions, 36 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 2ed6c16..e1194c8 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 */ |