summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2010-05-16 16:45:49 +0000
committerrrs <rrs@FreeBSD.org>2010-05-16 16:45:49 +0000
commita225bd6befc5d2f1c76f014a1ff21e360ece89e8 (patch)
tree2782d5f7028d12401ce45791ecc19118396e0527
parent47043a6fc0c6cfc6acbbddec9b14d5ea0d8756f0 (diff)
downloadFreeBSD-src-a225bd6befc5d2f1c76f014a1ff21e360ece89e8.zip
FreeBSD-src-a225bd6befc5d2f1c76f014a1ff21e360ece89e8.tar.gz
MFC of 207963
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.
-rw-r--r--sys/netinet/sctp_indata.c49
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 */
OpenPOWER on IntegriCloud