svn commit: r206739 - stable/8/sys/netinet
Randall Stewart
rrs at FreeBSD.org
Sat Apr 17 04:10:30 UTC 2010
Author: rrs
Date: Sat Apr 17 04:10:29 2010
New Revision: 206739
URL: http://svn.freebsd.org/changeset/base/206739
Log:
MFC of 205627
Part II (more to follow) of the great IETF hack-a-thon to
fix the NR-Sack code.
Modified:
stable/8/sys/netinet/sctp_indata.c
stable/8/sys/netinet/sctp_input.c
stable/8/sys/netinet/sctp_output.c
stable/8/sys/netinet/sctputil.c
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
Modified: stable/8/sys/netinet/sctp_indata.c
==============================================================================
--- stable/8/sys/netinet/sctp_indata.c Sat Apr 17 04:08:51 2010 (r206738)
+++ stable/8/sys/netinet/sctp_indata.c Sat Apr 17 04:10:29 2010 (r206739)
@@ -46,24 +46,13 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_timer.h>
#define SCTP_CALC_TSN_TO_GAP(gap, tsn, mapping_tsn) do { \
- if ((compare_with_wrap(tsn, mapping_tsn, MAX_TSN)) || \
- (tsn == mapping_tsn)) { \
+ if (tsn >= mapping_tsn) { \
gap = tsn - mapping_tsn; \
} else { \
gap = (MAX_TSN - mapping_tsn) + tsn + 1; \
} \
} while(0)
-#define SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc) do { \
- if (asoc->mapping_array_base_tsn == asoc->nr_mapping_array_base_tsn) { \
- SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, nr_gap); \
- } else {\
- int lgap; \
- SCTP_CALC_TSN_TO_GAP(lgap, tsn, asoc->mapping_array_base_tsn); \
- SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, lgap); \
- } \
- } while(0)
-
/*
* NOTES: On the outbound side of things I need to check the sack timer to
* see if I should generate a sack into the chunk queue (if I have data to
@@ -304,6 +293,44 @@ sctp_build_ctl_cchunk(struct sctp_inpcb
return (buf);
}
+static void
+sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
+{
+ uint32_t gap, i;
+ int fnd = 0;
+
+ if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) {
+ return;
+ }
+ SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn);
+#ifdef INVARIANTS
+ if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
+ printf("gap:%x tsn:%x\n", gap, tsn);
+ sctp_print_mapping_array(asoc);
+ panic("Things are really messed up now!!");
+ }
+#endif
+ SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
+ SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
+ if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ asoc->highest_tsn_inside_nr_map = tsn;
+ }
+ if (tsn == asoc->highest_tsn_inside_map) {
+ /* We must back down to see what the new highest is */
+ for (i = tsn - 1; compare_with_wrap(i, asoc->mapping_array_base_tsn, MAX_TSN); i--) {
+ SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn);
+ if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
+ asoc->highest_tsn_inside_map = i;
+ fnd = 1;
+ break;
+ }
+ }
+ if (!fnd) {
+ asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1;
+ }
+ }
+}
+
/*
* We are delivering currently from the reassembly queue. We must continue to
@@ -319,9 +346,6 @@ sctp_service_reassembly(struct sctp_tcb
int end = 0;
int cntDel;
- /* EY if any out-of-order delivered, then tag it nr on nr_map */
- uint32_t nr_tsn, nr_gap;
-
struct sctp_queued_to_read *control, *ctl, *ctlat;
if (stcb == NULL)
@@ -430,39 +454,7 @@ abandon:
}
/* pull it we did it */
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
- /*
- * EY this is the chunk that should be tagged nr gapped
- * calculate the gap and such then tag this TSN nr
- * chk->rec.data.TSN_seq
- */
- /*
- * EY!-TODO- this tsn should be tagged nr only if it is
- * out-of-order, the if statement should be modified
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack) {
- nr_tsn = chk->rec.data.TSN_seq;
- SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn);
- if ((nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) {
- /*
- * EY The 1st should never happen, as in
- * process_a_data_chunk method this check
- * should be done
- */
- /*
- * EY The 2nd should never happen, because
- * nr_mapping_array is always expanded when
- * mapping_array is expanded
- */
- printf("Impossible nr_gap ack range failed\n");
- } else {
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc);
- if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN))
- asoc->highest_tsn_inside_nr_map = nr_tsn;
- }
- }
+ sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq);
if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
asoc->fragmented_delivery_inprogress = 0;
if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) {
@@ -509,67 +501,11 @@ abandon:
asoc->size_on_all_streams -= ctl->length;
sctp_ucount_decr(asoc->cnt_on_all_streams);
strm->last_sequence_delivered++;
- /*
- * EY will be used to
- * calculate nr-gap
- */
- nr_tsn = ctl->sinfo_tsn;
sctp_add_to_readq(stcb->sctp_ep, stcb,
ctl,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
- /*
- * EY -now something is
- * delivered, calculate
- * nr_gap and tag this tsn
- * NR
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack) {
- SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn);
- if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) ||
- (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) {
- /*
- * EY The
- * 1st
- * should
- * never
- * happen,
- * as in
- * process_a_
- * data_chunk
- * method
- * this
- * check
- * should be
- * done
- */
- /*
- * EY The
- * 2nd
- * should
- * never
- * happen,
- * because
- * nr_mapping
- * _array is
- * always
- * expanded
- * when
- * mapping_ar
- * ray is
- * expanded
- */
- } else {
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc);
- if (compare_with_wrap(nr_tsn,
- asoc->highest_tsn_inside_nr_map,
- MAX_TSN))
- asoc->highest_tsn_inside_nr_map = nr_tsn;
- }
- }
+ sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
ctl = ctlat;
} else {
break;
@@ -618,9 +554,6 @@ sctp_queue_data_to_stream(struct sctp_tc
uint16_t nxt_todel;
struct mbuf *oper;
- /* EY- will be used to calculate nr-gap for a tsn */
- uint32_t nr_tsn, nr_gap;
-
queue_needed = 1;
asoc->size_on_all_streams += control->length;
sctp_ucount_incr(asoc->cnt_on_all_streams);
@@ -682,41 +615,12 @@ protocol_error:
asoc->size_on_all_streams -= control->length;
sctp_ucount_decr(asoc->cnt_on_all_streams);
strm->last_sequence_delivered++;
- /* EY will be used to calculate nr-gap */
- nr_tsn = control->sinfo_tsn;
+
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
- /*
- * EY this is the chunk that should be tagged nr gapped
- * calculate the gap and such then tag this TSN nr
- * chk->rec.data.TSN_seq
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack) {
- SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn);
- if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) ||
- (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) {
- printf("Impossible nr_tsn set 2?\n");
- /*
- * EY The 1st should never happen, as in
- * process_a_data_chunk method this check
- * should be done
- */
- /*
- * EY The 2nd should never happen, because
- * nr_mapping_array is always expanded when
- * mapping_array is expanded
- */
- } else {
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc);
- if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN))
- asoc->highest_tsn_inside_nr_map = nr_tsn;
- }
- }
+ sctp_mark_non_revokable(asoc, control->sinfo_tsn);
control = TAILQ_FIRST(&strm->inqueue);
while (control != NULL) {
/* all delivered */
@@ -738,47 +642,12 @@ protocol_error:
SCTP_STR_LOG_FROM_IMMED_DEL);
}
/* EY will be used to calculate nr-gap */
- nr_tsn = control->sinfo_tsn;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD,
SCTP_SO_NOT_LOCKED);
- /*
- * EY this is the chunk that should be
- * tagged nr gapped calculate the gap and
- * such then tag this TSN nr
- * chk->rec.data.TSN_seq
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack) {
- SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn);
- if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) ||
- (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) {
- /*
- * EY The 1st should never
- * happen, as in
- * process_a_data_chunk
- * method this check should
- * be done
- */
- /*
- * EY The 2nd should never
- * happen, because
- * nr_mapping_array is
- * always expanded when
- * mapping_array is expanded
- */
- } else {
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (compare_with_wrap(nr_tsn,
- asoc->highest_tsn_inside_nr_map,
- MAX_TSN))
- asoc->highest_tsn_inside_nr_map = nr_tsn;
- }
- }
+ sctp_mark_non_revokable(asoc, control->sinfo_tsn);
control = at;
continue;
}
@@ -1586,9 +1455,6 @@ sctp_process_a_data_chunk(struct sctp_tc
/* struct sctp_tmit_chunk *chk; */
struct sctp_tmit_chunk *chk;
uint32_t tsn, gap;
-
- /* EY - for nr_sack */
- uint32_t nr_gap;
struct mbuf *dmbuf;
int indx, the_len;
int need_reasm_check = 0;
@@ -1640,14 +1506,12 @@ sctp_process_a_data_chunk(struct sctp_tc
return (0);
}
}
- /* EY - for nr_sack */
- nr_gap = gap;
-
if (compare_with_wrap(tsn, *high_tsn, MAX_TSN)) {
*high_tsn = tsn;
}
/* See if we have received this one already */
- if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
+ if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap) ||
+ SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, gap)) {
SCTP_STAT_INCR(sctps_recvdupdata);
if (asoc->numduptsns < SCTP_MAX_DUP_TSNS) {
/* Record a dup for the next outbound sack */
@@ -1714,7 +1578,8 @@ sctp_process_a_data_chunk(struct sctp_tc
#endif
}
/* now is it in the mapping array of what we have accepted? */
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) {
+ if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN) &&
+ compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
/* Nope not in the valid range dump it */
sctp_set_rwnd(stcb, asoc);
if ((asoc->cnt_on_all_streams +
@@ -1758,23 +1623,10 @@ sctp_process_a_data_chunk(struct sctp_tc
}
SCTP_STAT_INCR(sctps_badsid);
SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap);
- /* EY set this tsn present in nr_sack's nr_mapping_array */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack) {
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
- SCTP_REVERSE_OUT_TSN_PRES(gap, tsn, asoc);
- }
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) {
- /* we have a new high score */
- asoc->highest_tsn_inside_map = tsn;
- /* EY nr_sack version of the above */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack)
- asoc->highest_tsn_inside_nr_map = tsn;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
- sctp_log_map(0, 2, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
- }
+
+ SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
+ if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ asoc->highest_tsn_inside_nr_map = tsn;
}
if (tsn == (asoc->cumulative_tsn + 1)) {
/* Update cum-ack */
@@ -1925,48 +1777,6 @@ sctp_process_a_data_chunk(struct sctp_tc
control, &stcb->sctp_socket->so_rcv,
1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
- /*
- * EY here I should check if this delivered tsn is
- * out_of_order, if yes then update the nr_map
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) {
- /*
- * EY check if the mapping_array and nr_mapping
- * array are consistent
- */
- if (asoc->mapping_array_base_tsn != asoc->nr_mapping_array_base_tsn)
- /*
- * printf("EY-IN
- * sctp_process_a_data_chunk(5): Something
- * is wrong the map base tsn" "\nEY-and
- * nr_map base tsn should be equal.");
- */
- /* EY debugging block */
- {
- /*
- * printf("\nEY-Calculating an
- * nr_gap!!\nmapping_array_size = %d
- * nr_mapping_array_size = %d"
- * "\nEY-mapping_array_base = %d
- * nr_mapping_array_base =
- * %d\nEY-highest_tsn_inside_map = %d"
- * "highest_tsn_inside_nr_map = %d\nEY-TSN =
- * %d nr_gap = %d",asoc->mapping_array_size,
- * asoc->nr_mapping_array_size,
- * asoc->mapping_array_base_tsn,
- * asoc->nr_mapping_array_base_tsn,
- * asoc->highest_tsn_inside_map,
- * asoc->highest_tsn_inside_nr_map,tsn,nr_gap
- * );
- */
- }
- /* EY - not %100 sure about the lock thing */
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN))
- asoc->highest_tsn_inside_nr_map = tsn;
- }
if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) {
/* for ordered, bump what we delivered */
asoc->strmin[strmno].last_sequence_delivered++;
@@ -1977,6 +1787,10 @@ sctp_process_a_data_chunk(struct sctp_tc
SCTP_STR_LOG_FROM_EXPRS_DEL);
}
control = NULL;
+ SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
+ if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ asoc->highest_tsn_inside_nr_map = tsn;
+ }
goto finish_express_del;
}
failed_express_del:
@@ -2012,39 +1826,9 @@ failed_express_del:
SCTP_PRINTF("Append fails end:%d\n", end);
goto failed_pdapi_express_del;
}
- /*
- * EY It is appended to the read queue in prev if
- * block here I should check if this delivered tsn
- * is out_of_order, if yes then update the nr_map
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack) {
- /* EY debugging block */
- {
- /*
- * printf("\nEY-Calculating an
- * nr_gap!!\nEY-mapping_array_size =
- * %d nr_mapping_array_size = %d"
- * "\nEY-mapping_array_base = %d
- * nr_mapping_array_base =
- * %d\nEY-highest_tsn_inside_map =
- * %d" "highest_tsn_inside_nr_map =
- * %d\nEY-TSN = %d nr_gap =
- * %d",asoc->mapping_array_size,
- * asoc->nr_mapping_array_size,
- * asoc->mapping_array_base_tsn,
- * asoc->nr_mapping_array_base_tsn,
- * asoc->highest_tsn_inside_map,
- * asoc->highest_tsn_inside_nr_map,ts
- * n,nr_gap);
- */
- }
- /* EY - not %100 sure about the lock thing */
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN))
- asoc->highest_tsn_inside_nr_map = tsn;
+ SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
+ if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ asoc->highest_tsn_inside_nr_map = tsn;
}
SCTP_STAT_INCR(sctps_recvexpressm);
control->sinfo_tsn = tsn;
@@ -2069,12 +1853,27 @@ failed_express_del:
need_reasm_check = 1;
}
}
+ SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
+ if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ asoc->highest_tsn_inside_nr_map = tsn;
+ }
control = NULL;
goto finish_express_del;
}
}
failed_pdapi_express_del:
control = NULL;
+ if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) {
+ SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
+ if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ asoc->highest_tsn_inside_nr_map = tsn;
+ }
+ } else {
+ SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap);
+ if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) {
+ asoc->highest_tsn_inside_map = tsn;
+ }
+ }
if ((chunk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) {
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
@@ -2263,56 +2062,7 @@ failed_pdapi_express_del:
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
- /*
- * EY It is added to the read queue in prev if block
- * here I should check if this delivered tsn is
- * out_of_order, if yes then update the nr_map
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack) {
- /*
- * EY check if the mapping_array and
- * nr_mapping array are consistent
- */
- if (asoc->mapping_array_base_tsn != asoc->nr_mapping_array_base_tsn)
- /*
- * printf("EY-IN
- * sctp_process_a_data_chunk(6):
- * Something is wrong the map base
- * tsn" "\nEY-and nr_map base tsn
- * should be equal.");
- */
- /*
- * EY - not %100 sure about the lock
- * thing, i think we don't need the
- * below,
- */
- /* SCTP_TCB_LOCK_ASSERT(stcb); */
- {
- /*
- * printf("\nEY-Calculating an
- * nr_gap!!\nEY-mapping_array_size =
- * %d nr_mapping_array_size = %d"
- * "\nEY-mapping_array_base = %d
- * nr_mapping_array_base =
- * %d\nEY-highest_tsn_inside_map =
- * %d" "highest_tsn_inside_nr_map =
- * %d\nEY-TSN = %d nr_gap =
- * %d",asoc->mapping_array_size,
- * asoc->nr_mapping_array_size,
- * asoc->mapping_array_base_tsn,
- * asoc->nr_mapping_array_base_tsn,
- * asoc->highest_tsn_inside_map,
- * asoc->highest_tsn_inside_nr_map,ts
- * n,nr_gap);
- */
- }
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN))
- asoc->highest_tsn_inside_nr_map = tsn;
- }
+
} else {
/*
* Special check for when streams are resetting. We
@@ -2384,13 +2134,6 @@ failed_pdapi_express_del:
}
}
finish_express_del:
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) {
- /* we have a new high score */
- asoc->highest_tsn_inside_map = tsn;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
- sctp_log_map(0, 2, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
- }
- }
if (tsn == (asoc->cumulative_tsn + 1)) {
/* Update cum-ack */
asoc->cumulative_tsn = tsn;
@@ -2412,22 +2155,6 @@ finish_express_del:
sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn,
asoc->highest_tsn_inside_map, SCTP_MAP_PREPARE_SLIDE);
}
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap);
-
- /*
- * EY - set tsn present in nr-map if doing nr-sacks and the tsn is
- * non-renegable
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack &&
- (SCTP_BASE_SYSCTL(sctp_do_drain) == 0)) {
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
- asoc->highest_tsn_inside_nr_map = tsn;
- }
- }
/* check the special flag for stream resets */
if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) &&
((compare_with_wrap(asoc->cumulative_tsn, liste->tsn, MAX_TSN)) ||
@@ -2532,7 +2259,6 @@ sctp_sack_check(struct sctp_tcb *stcb, i
*/
struct sctp_association *asoc;
int at;
- uint8_t comb_byte;
int last_all_ones = 0;
int slide_from, slide_end, lgap, distance;
@@ -2540,7 +2266,7 @@ sctp_sack_check(struct sctp_tcb *stcb, i
/* int nr_at; */
/* int nr_last_all_ones = 0; */
/* int nr_slide_from, nr_slide_end, nr_lgap, nr_distance; */
- uint32_t old_cumack, old_base, old_highest;
+ uint32_t old_cumack, old_base, old_highest, highest_tsn;
asoc = &stcb->asoc;
at = 0;
@@ -2553,30 +2279,23 @@ sctp_sack_check(struct sctp_tcb *stcb, i
* offset of the current cum-ack as the starting point.
*/
at = 0;
- for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) {
- /*
- * We must combine the renegable and non-renegable arrays
- * here to form a unified view of what is acked right now
- * (since they are kept separate
- */
- comb_byte = asoc->mapping_array[slide_from] | asoc->nr_mapping_array[slide_from];
- if (comb_byte == 0xff) {
+ for (slide_from = 0; slide_from < stcb->asoc.nr_mapping_array_size; slide_from++) {
+ if (asoc->nr_mapping_array[slide_from] == 0xff) {
at += 8;
last_all_ones = 1;
} else {
/* there is a 0 bit */
- at += sctp_map_lookup_tab[comb_byte];
+ at += sctp_map_lookup_tab[asoc->nr_mapping_array[slide_from]];
last_all_ones = 0;
break;
}
}
- asoc->cumulative_tsn = asoc->mapping_array_base_tsn + (at - last_all_ones);
- /* at is one off, since in the table a embedded -1 is present */
+ asoc->cumulative_tsn = asoc->nr_mapping_array_base_tsn + (at - last_all_ones);
at++;
- if (compare_with_wrap(asoc->cumulative_tsn,
- asoc->highest_tsn_inside_map,
- MAX_TSN)) {
+ if (compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_map, MAX_TSN) &&
+ compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)
+ ) {
#ifdef INVARIANTS
panic("huh, cumack 0x%x greater than high-tsn 0x%x in map",
asoc->cumulative_tsn, asoc->highest_tsn_inside_map);
@@ -2591,37 +2310,29 @@ sctp_sack_check(struct sctp_tcb *stcb, i
asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn;
#endif
}
- if ((asoc->cumulative_tsn == asoc->highest_tsn_inside_map) && (at >= 8)) {
+ if (compare_with_wrap(asoc->highest_tsn_inside_nr_map,
+ asoc->highest_tsn_inside_map,
+ MAX_TSN)) {
+ highest_tsn = asoc->highest_tsn_inside_nr_map;
+ } else {
+ highest_tsn = asoc->highest_tsn_inside_map;
+ }
+ if ((asoc->cumulative_tsn == highest_tsn) && (at >= 8)) {
/* The complete array was completed by a single FR */
- /* higest becomes the cum-ack */
+ /* highest becomes the cum-ack */
int clr;
- asoc->cumulative_tsn = asoc->highest_tsn_inside_map;
/* clear the array */
clr = (at >> 3) + 1;
if (clr > asoc->mapping_array_size) {
clr = asoc->mapping_array_size;
}
memset(asoc->mapping_array, 0, clr);
- /* base becomes one ahead of the cum-ack */
- asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1;
-
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) {
-
- if (clr > asoc->nr_mapping_array_size)
- clr = asoc->nr_mapping_array_size;
+ memset(asoc->nr_mapping_array, 0, clr);
- memset(asoc->nr_mapping_array, 0, clr);
- /* base becomes one ahead of the cum-ack */
- asoc->nr_mapping_array_base_tsn = asoc->cumulative_tsn + 1;
- asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn;
- }
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
- sctp_log_map(old_base, old_cumack, old_highest,
- SCTP_MAP_PREPARE_SLIDE);
- sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn,
- asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_CLEARED);
- }
+ asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1;
+ asoc->nr_mapping_array_base_tsn = asoc->cumulative_tsn + 1;
+ asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map = asoc->cumulative_tsn;
} else if (at >= 8) {
/* we can slide the mapping array down */
/* slide_from holds where we hit the first NON 0xff byte */
@@ -2630,19 +2341,15 @@ sctp_sack_check(struct sctp_tcb *stcb, i
* now calculate the ceiling of the move using our highest
* TSN value
*/
- if (asoc->highest_tsn_inside_map >= asoc->mapping_array_base_tsn) {
- lgap = asoc->highest_tsn_inside_map -
- asoc->mapping_array_base_tsn;
- } else {
- lgap = (MAX_TSN - asoc->mapping_array_base_tsn) +
- asoc->highest_tsn_inside_map + 1;
- }
- slide_end = lgap >> 3;
+ SCTP_CALC_TSN_TO_GAP(lgap, highest_tsn, asoc->mapping_array_base_tsn);
+ slide_end = (lgap >> 3);
if (slide_end < slide_from) {
+ sctp_print_mapping_array(asoc);
#ifdef INVARIANTS
panic("impossible slide");
#else
- printf("impossible slide?\n");
+ printf("impossible slide lgap:%x slide_end:%x slide_from:%x? at:%d\n",
+ lgap, slide_end, slide_from, at);
return;
#endif
}
@@ -2682,30 +2389,21 @@ sctp_sack_check(struct sctp_tcb *stcb, i
for (ii = 0; ii < distance; ii++) {
asoc->mapping_array[ii] =
asoc->mapping_array[slide_from + ii];
+ asoc->nr_mapping_array[ii] =
+ asoc->nr_mapping_array[slide_from + ii];
+
}
for (ii = distance; ii <= slide_end; ii++) {
asoc->mapping_array[ii] = 0;
+ asoc->nr_mapping_array[ii] = 0;
}
asoc->mapping_array_base_tsn += (slide_from << 3);
+ asoc->nr_mapping_array_base_tsn += (slide_from << 3);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
sctp_log_map(asoc->mapping_array_base_tsn,
asoc->cumulative_tsn, asoc->highest_tsn_inside_map,
SCTP_MAP_SLIDE_RESULT);
}
- /*
- * EY if doing nr_sacks then slide the
- * nr_mapping_array accordingly please
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) {
- for (ii = 0; ii < distance; ii++) {
- asoc->nr_mapping_array[ii] =
- asoc->nr_mapping_array[slide_from + ii];
- }
- for (ii = distance; ii <= slide_end; ii++) {
- asoc->nr_mapping_array[ii] = 0;
- }
- asoc->nr_mapping_array_base_tsn += (slide_from << 3);
- }
}
}
/*
@@ -2736,8 +2434,7 @@ sctp_sack_check(struct sctp_tcb *stcb, i
int is_a_gap;
/* is there a gap now ? */
- is_a_gap = compare_with_wrap(stcb->asoc.highest_tsn_inside_map,
- stcb->asoc.cumulative_tsn, MAX_TSN);
+ is_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN);
/*
* CMT DAC algorithm: increase number of packets
@@ -5742,9 +5439,6 @@ sctp_kick_prsctp_reorder_queue(struct sc
struct sctp_association *asoc;
int tt;
- /* EY -used to calculate nr_gap information */
- uint32_t nr_tsn, nr_gap;
-
asoc = &stcb->asoc;
tt = strmin->last_sequence_delivered;
/*
@@ -5764,82 +5458,10 @@ sctp_kick_prsctp_reorder_queue(struct sc
/* deliver it to at least the delivery-q */
if (stcb->sctp_socket) {
/* EY need the tsn info for calculating nr */
- nr_tsn = ctl->sinfo_tsn;
sctp_add_to_readq(stcb->sctp_ep, stcb,
ctl,
&stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED);
- /*
- * EY this is the chunk that should be
- * tagged nr gapped calculate the gap and
- * such then tag this TSN nr
- * chk->rec.data.TSN_seq
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack) {
- SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn);
- if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) ||
- (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) {
- /*
- * EY These should never
- * happen- explained before
- */
- } else {
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc);
- if (compare_with_wrap(nr_tsn,
- asoc->highest_tsn_inside_nr_map,
- MAX_TSN))
- asoc->highest_tsn_inside_nr_map = nr_tsn;
- }
- if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, nr_gap))
- /*
- * printf("In
- * sctp_kick_prsctp_reorder_q
- * ueue(7): Something wrong,
- * the TSN to be tagged"
- * "\nas NR is not even in
- * the mapping_array, or map
- * and nr_map are
- * inconsistent");
- */
- /*
- * EY - not %100 sure about
- * the lock thing, don't
- * think its required
- */
- /*
- * SCTP_TCB_LOCK_ASSERT(stcb)
- * ;
- */
- {
- /*
- * printf("\nCalculating an
- * nr_gap!!\nmapping_array_si
- * ze = %d
- * nr_mapping_array_size =
- * %d" "\nmapping_array_base
- * = %d
- * nr_mapping_array_base =
- * %d\nhighest_tsn_inside_map
- * = %d"
- * "highest_tsn_inside_nr_map
- * = %d\nTSN = %d nr_gap =
- * %d",asoc->mapping_array_si
- * ze,
- * asoc->nr_mapping_array_siz
- * e,
- * asoc->mapping_array_base_t
- * sn,
- * asoc->nr_mapping_array_bas
- * e_tsn,
- * asoc->highest_tsn_inside_m
- * ap,
- * asoc->highest_tsn_inside_n
- * r_map,tsn,nr_gap);
- */
- }
- }
+ sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
}
} else {
/* no more delivery now. */
@@ -5864,82 +5486,11 @@ sctp_kick_prsctp_reorder_queue(struct sc
/* deliver it to at least the delivery-q */
strmin->last_sequence_delivered = ctl->sinfo_ssn;
if (stcb->sctp_socket) {
- /* EY */
- nr_tsn = ctl->sinfo_tsn;
sctp_add_to_readq(stcb->sctp_ep, stcb,
ctl,
&stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED);
- /*
- * EY this is the chunk that should be
- * tagged nr gapped calculate the gap and
- * such then tag this TSN nr
- * chk->rec.data.TSN_seq
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- asoc->peer_supports_nr_sack) {
- SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn);
- if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) ||
- (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) {
- /*
- * EY These should never
- * happen, explained before
- */
- } else {
- SCTP_TCB_LOCK_ASSERT(stcb);
- SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc);
- if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map,
- MAX_TSN))
- asoc->highest_tsn_inside_nr_map = nr_tsn;
- }
- if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, nr_gap))
- /*
- * printf("In
- * sctp_kick_prsctp_reorder_q
- * ueue(8): Something wrong,
- * the TSN to be tagged"
- * "\nas NR is not even in
- * the mapping_array, or map
- * and nr_map are
- * inconsistent");
- */
- /*
- * EY - not %100 sure about
- * the lock thing, don't
- * think its required
- */
- /*
- * SCTP_TCB_LOCK_ASSERT(stcb)
- * ;
- */
- {
- /*
- * printf("\nCalculating an
- * nr_gap!!\nmapping_array_si
- * ze = %d
- * nr_mapping_array_size =
- * %d" "\nmapping_array_base
- * = %d
- * nr_mapping_array_base =
- * %d\nhighest_tsn_inside_map
- * = %d"
- * "highest_tsn_inside_nr_map
- * = %d\nTSN = %d nr_gap =
- * %d",asoc->mapping_array_si
- * ze,
- * asoc->nr_mapping_array_siz
- * e,
- * asoc->mapping_array_base_t
- * sn,
- * asoc->nr_mapping_array_bas
- * e_tsn,
- * asoc->highest_tsn_inside_m
- * ap,
- * asoc->highest_tsn_inside_n
- * r_map,tsn,nr_gap);
- */
- }
- }
+ sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
+
}
tt = strmin->last_sequence_delivered + 1;
} else {
@@ -6096,25 +5647,19 @@ sctp_handle_forward_tsn(struct sctp_tcb
if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_map,
MAX_TSN)) {
asoc->highest_tsn_inside_map = new_cum_tsn;
- /* EY nr_mapping_array version of the above */
- /*
- * if(SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
- * asoc->peer_supports_nr_sack)
- */
+
+ }
+ 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 (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
- sctp_log_map(0, 0, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
- }
}
/*
* now we know the new TSN is more advanced, let's find the actual
* gap
*/
- SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->mapping_array_base_tsn);
+ SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->nr_mapping_array_base_tsn);
+ asoc->cumulative_tsn = new_cum_tsn;
if (gap >= m_size) {
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
- sctp_log_map(0, 0, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
- }
if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) {
struct mbuf *oper;
@@ -6147,23 +5692,15 @@ sctp_handle_forward_tsn(struct sctp_tcb
return;
}
SCTP_STAT_INCR(sctps_fwdtsn_map_over);
+
memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
- cumack_set_flag = 1;
asoc->mapping_array_base_tsn = new_cum_tsn + 1;
- asoc->cumulative_tsn = asoc->highest_tsn_inside_map = new_cum_tsn;
- /* EY - nr_sack: nr_mapping_array version of the above */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) {
- memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size);
- asoc->nr_mapping_array_base_tsn = new_cum_tsn + 1;
- asoc->highest_tsn_inside_nr_map = new_cum_tsn;
- if (asoc->nr_mapping_array_size != asoc->mapping_array_size) {
- /*
- * printf("IN sctp_handle_forward_tsn:
- * Something is wrong the size of" "map and
- * nr_map should be equal!")
- */ ;
- }
- }
+ asoc->highest_tsn_inside_map = new_cum_tsn;
+
+ memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable
mailing list