summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2009-04-04 11:43:32 +0000
committerrrs <rrs@FreeBSD.org>2009-04-04 11:43:32 +0000
commitf72ef579b2bcf1c9f2abd735735fe92b2f8ada15 (patch)
treeaa1f0e7c08d66758879376d7bd3ed3ff5a7c7bb3
parent3503cf99e3ac0111488d2a57341ab1b1088e2436 (diff)
downloadFreeBSD-src-f72ef579b2bcf1c9f2abd735735fe92b2f8ada15.zip
FreeBSD-src-f72ef579b2bcf1c9f2abd735735fe92b2f8ada15.tar.gz
Many bug fixes (from the IETF hack-fest):
- PR-SCTP had major issues when skipping through a multi-part message. o Did not look at socket buffer. o Did not properly handle the reassmebly queue. o The MARKED segments could interfere and un-skip a chunk causing a problem with the proper FWD-TSN. o No FR of FWD-TSN's was being done. - NR-Sack code was basically disabled. It needed fixes that never got into the real code. - CMT code had issues when the two paths were NOT the same b/w. We found a few small bugs, but also the critcal one here was not dividing the rwnd amongst the paths. Obtained from: Michael Tuexen and myself at the IETF hack-fest ;-)
-rw-r--r--sys/netinet/sctp_indata.c332
-rw-r--r--sys/netinet/sctp_input.c9
-rw-r--r--sys/netinet/sctp_output.c2052
-rw-r--r--sys/netinet/sctp_pcb.c12
-rw-r--r--sys/netinet/sctp_structs.h3
-rw-r--r--sys/netinet/sctp_sysctl.c1
-rw-r--r--sys/netinet/sctp_sysctl.h2
-rw-r--r--sys/netinet/sctp_uio.h5
-rw-r--r--sys/netinet/sctp_usrreq.c6
-rw-r--r--sys/netinet/sctputil.c62
10 files changed, 365 insertions, 2119 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 0075007..a9f315c 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -423,12 +423,13 @@ abandon:
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) {
nr_tsn = chk->rec.data.TSN_seq;
- if (nr_tsn >= asoc->nr_mapping_array_base_tsn) {
+ if ((compare_with_wrap(nr_tsn, asoc->nr_mapping_array_base_tsn, MAX_TSN)) ||
+ (nr_tsn == asoc->nr_mapping_array_base_tsn)) {
nr_gap = nr_tsn - asoc->nr_mapping_array_base_tsn;
} else {
nr_gap = (MAX_TSN - asoc->nr_mapping_array_base_tsn) + nr_tsn + 1;
}
- if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) ||
+ if ((nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3)) ||
(nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) {
/*
* EY The 1st should never happen, as in
@@ -440,10 +441,11 @@ abandon:
* 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);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
}
@@ -550,7 +552,9 @@ abandon:
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn,
+ asoc->highest_tsn_inside_nr_map,
+ MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
}
@@ -699,7 +703,7 @@ protocol_error:
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
}
@@ -760,7 +764,8 @@ protocol_error:
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map,
+ MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
}
@@ -2390,6 +2395,15 @@ finish_express_del:
}
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap);
+
+ 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);
+ 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)) ||
@@ -2498,9 +2512,9 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
int slide_from, slide_end, lgap, distance;
/* EY nr_mapping array variables */
- int nr_at;
- int nr_last_all_ones = 0;
- int nr_slide_from, nr_slide_end, nr_lgap, nr_distance;
+ /* 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;
unsigned char aux_array[64];
@@ -2683,102 +2697,19 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
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) {
-
- nr_at = 0;
- for (nr_slide_from = 0; nr_slide_from < stcb->asoc.nr_mapping_array_size; nr_slide_from++) {
-
- if (asoc->nr_mapping_array[nr_slide_from] == 0xff) {
- nr_at += 8;
- nr_last_all_ones = 1;
- } else {
- /* there is a 0 bit */
- nr_at += sctp_map_lookup_tab[asoc->nr_mapping_array[nr_slide_from]];
- nr_last_all_ones = 0;
- break;
- }
- }
-
- nr_at++;
-
- if (compare_with_wrap(asoc->cumulative_tsn,
- asoc->highest_tsn_inside_nr_map, MAX_TSN) && (at >= 8)) {
- /* The complete array was completed by a single FR */
- /* higest becomes the cum-ack */
- int clr;
-
- clr = (nr_at >> 3) + 1;
-
- if (clr > asoc->nr_mapping_array_size)
- clr = asoc->nr_mapping_array_size;
-
- 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;
-
- } else if (nr_at >= 8) {
- /* we can slide the mapping array down */
- /* Calculate the new byte postion we can move down */
-
/*
- * now calculate the ceiling of the move using our
- * highest TSN value
+ * EY if doing nr_sacks then slide the
+ * nr_mapping_array accordingly please
*/
- if (asoc->highest_tsn_inside_nr_map >= asoc->nr_mapping_array_base_tsn) {
- nr_lgap = asoc->highest_tsn_inside_nr_map -
- asoc->nr_mapping_array_base_tsn;
- } else {
- nr_lgap = (MAX_TSN - asoc->nr_mapping_array_base_tsn) +
- asoc->highest_tsn_inside_nr_map + 1;
- }
- nr_slide_end = nr_lgap >> 3;
- if (nr_slide_end < nr_slide_from) {
-#ifdef INVARIANTS
- panic("impossible slide");
-#else
- printf("impossible slide?\n");
- return;
-#endif
- }
- if (nr_slide_end > asoc->nr_mapping_array_size) {
-#ifdef INVARIANTS
- panic("would overrun buffer");
-#else
- printf("Gak, would have overrun map end:%d nr_slide_end:%d\n",
- asoc->nr_mapping_array_size, nr_slide_end);
- nr_slide_end = asoc->nr_mapping_array_size;
-#endif
- }
- nr_distance = (nr_slide_end - nr_slide_from) + 1;
-
- if (nr_distance + nr_slide_from > asoc->nr_mapping_array_size ||
- nr_distance < 0) {
- /*
- * Here we do NOT slide forward the array so
- * that hopefully when more data comes in to
- * fill it up we will be able to slide it
- * forward. Really I don't think this should
- * happen :-0
- */
- ;
- } else {
- int ii;
-
- for (ii = 0; ii < nr_distance; ii++) {
+ 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[nr_slide_from + ii];
+ asoc->nr_mapping_array[slide_from + ii];
}
- for (ii = nr_distance; ii <= nr_slide_end; ii++) {
+ for (ii = distance; ii <= slide_end; ii++) {
asoc->nr_mapping_array[ii] = 0;
}
- asoc->nr_mapping_array_base_tsn += (nr_slide_from << 3);
+ asoc->nr_mapping_array_base_tsn += (slide_from << 3);
}
}
}
@@ -2802,7 +2733,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
* EY if nr_sacks used then send an nr-sack , a sack
* otherwise
*/
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack)
+ if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack)
sctp_send_nr_sack(stcb);
else
sctp_send_sack(stcb);
@@ -3496,9 +3427,13 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct
/*
* All chunks NOT UNSENT
* fall through here and are
- * marked
+ * marked (leave PR-SCTP
+ * ones that are to skip
+ * alone though)
*/
- tp1->sent = SCTP_DATAGRAM_MARKED;
+ if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+ tp1->sent = SCTP_DATAGRAM_MARKED;
+
if (tp1->rec.data.chunk_was_revoked) {
/* deflate the cwnd */
tp1->whoTo->cwnd -= tp1->book_size;
@@ -5798,7 +5733,9 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn,
+ asoc->highest_tsn_inside_nr_map,
+ MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
@@ -5901,7 +5838,8 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map,
+ MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
@@ -5963,6 +5901,91 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
}
}
+static void
+sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
+ struct sctp_association *asoc,
+ uint16_t stream, uint16_t seq)
+{
+ struct sctp_tmit_chunk *chk, *at;
+
+ if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
+ /* For each one on here see if we need to toss it */
+ /*
+ * For now large messages held on the reasmqueue that are
+ * complete will be tossed too. We could in theory do more
+ * work to spin through and stop after dumping one msg aka
+ * seeing the start of a new msg at the head, and call the
+ * delivery function... to see if it can be delivered... But
+ * for now we just dump everything on the queue.
+ */
+ chk = TAILQ_FIRST(&asoc->reasmqueue);
+ while (chk) {
+ at = TAILQ_NEXT(chk, sctp_next);
+ if (chk->rec.data.stream_number != stream) {
+ chk = at;
+ continue;
+ }
+ if (chk->rec.data.stream_seq == seq) {
+ /* It needs to be tossed */
+ TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
+ if (compare_with_wrap(chk->rec.data.TSN_seq,
+ asoc->tsn_last_delivered, MAX_TSN)) {
+ asoc->tsn_last_delivered =
+ chk->rec.data.TSN_seq;
+ asoc->str_of_pdapi =
+ chk->rec.data.stream_number;
+ asoc->ssn_of_pdapi =
+ chk->rec.data.stream_seq;
+ asoc->fragment_flags =
+ chk->rec.data.rcv_flags;
+ }
+ asoc->size_on_reasm_queue -= chk->send_size;
+ sctp_ucount_decr(asoc->cnt_on_reasm_queue);
+
+ /* Clear up any stream problem */
+ if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
+ SCTP_DATA_UNORDERED &&
+ (compare_with_wrap(chk->rec.data.stream_seq,
+ asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered,
+ MAX_SEQ))) {
+ /*
+ * We must dump forward this streams
+ * sequence number if the chunk is
+ * not unordered that is being
+ * skipped. There is a chance that
+ * if the peer does not include the
+ * last fragment in its FWD-TSN we
+ * WILL have a problem here since
+ * you would have a partial chunk in
+ * queue that may not be
+ * deliverable. Also if a Partial
+ * delivery API as started the user
+ * may get a partial chunk. The next
+ * read returning a new chunk...
+ * really ugly but I see no way
+ * around it! Maybe a notify??
+ */
+ asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered =
+ chk->rec.data.stream_seq;
+ }
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
+ }
+ sctp_free_a_chunk(stcb, chk);
+ } else if (compare_with_wrap(chk->rec.data.stream_seq, seq, MAX_SEQ)) {
+ /*
+ * If the stream_seq is > than the purging
+ * one, we are done
+ */
+ break;
+ }
+ chk = at;
+ }
+ }
+}
+
+
void
sctp_handle_forward_tsn(struct sctp_tcb *stcb,
struct sctp_forward_tsn_chunk *fwd, int *abort_flag, struct mbuf *m, int offset)
@@ -5992,13 +6015,14 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
*/
struct sctp_association *asoc;
uint32_t new_cum_tsn, gap;
- unsigned int i, cnt_gone, fwd_sz, cumack_set_flag, m_size;
+ 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;
+ struct sctp_queued_to_read *ctl, *sv;
cumack_set_flag = 0;
asoc = &stcb->asoc;
- cnt_gone = 0;
if ((fwd_sz = ntohs(fwd->ch.chunk_length)) < sizeof(struct sctp_forward_tsn_chunk)) {
SCTPDBG(SCTP_DEBUG_INDATA1,
"Bad size too small/big fwd-tsn\n");
@@ -6102,6 +6126,14 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
SCTP_TCB_LOCK_ASSERT(stcb);
for (i = 0; i <= gap; i++) {
SCTP_SET_TSN_PRESENT(asoc->mapping_array, i);
+ /*
+ * EY if drain is off then every gap-ack is an
+ * nr-gap-ack
+ */
+ 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, i);
+ }
}
/*
* Now after marking all, slide thing forward but no sack
@@ -6152,7 +6184,6 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
}
asoc->size_on_reasm_queue -= chk->send_size;
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
- cnt_gone++;
/* Clear up any stream problem */
if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
@@ -6188,45 +6219,17 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
} else {
/*
* Ok we have gone beyond the end of the
- * fwd-tsn's mark. Some checks...
+ * fwd-tsn's mark.
*/
- if ((asoc->fragmented_delivery_inprogress) &&
- (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) {
- uint32_t str_seq;
-
- /*
- * Special case PD-API is up and
- * what we fwd-tsn' over includes
- * one that had the LAST_FRAG. We no
- * longer need to do the PD-API.
- */
- asoc->fragmented_delivery_inprogress = 0;
-
- str_seq = (asoc->str_of_pdapi << 16) | asoc->ssn_of_pdapi;
- sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
- stcb, SCTP_PARTIAL_DELIVERY_ABORTED, (void *)&str_seq, SCTP_SO_NOT_LOCKED);
-
- }
break;
}
chk = at;
}
}
- if (asoc->fragmented_delivery_inprogress) {
- /*
- * Ok we removed cnt_gone chunks in the PD-API queue that
- * were being delivered. So now we must turn off the flag.
- */
- uint32_t str_seq;
-
- str_seq = (asoc->str_of_pdapi << 16) | asoc->ssn_of_pdapi;
- sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
- stcb, SCTP_PARTIAL_DELIVERY_ABORTED, (void *)&str_seq, SCTP_SO_NOT_LOCKED);
- asoc->fragmented_delivery_inprogress = 0;
- }
- /*************************************************************/
- /* 3. Update the PR-stream re-ordering queues */
- /*************************************************************/
+ /*******************************************************/
+ /* 3. Update the PR-stream re-ordering queues and fix */
+ /* delivery issues as needed. */
+ /*******************************************************/
fwd_sz -= sizeof(*fwd);
if (m && fwd_sz) {
/* New method. */
@@ -6235,6 +6238,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
offset += sizeof(*fwd);
+ SCTP_INP_READ_LOCK(stcb->sctp_ep);
num_str = fwd_sz / sizeof(struct sctp_strseq);
for (i = 0; i < num_str; i++) {
uint16_t st;
@@ -6251,11 +6255,49 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
stseq->stream = st;
st = ntohs(stseq->sequence);
stseq->sequence = st;
+
/* now process */
+
+ /*
+ * Ok we now look for the stream/seq on the read
+ * queue where its not all delivered. If we find it
+ * we transmute the read entry into a PDI_ABORTED.
+ */
if (stseq->stream >= asoc->streamincnt) {
/* screwed up streams, stop! */
break;
}
+ if ((asoc->str_of_pdapi == stseq->stream) &&
+ (asoc->ssn_of_pdapi == stseq->sequence)) {
+ /*
+ * If this is the one we were partially
+ * delivering now then we no longer are.
+ * Note this will change with the reassembly
+ * re-write.
+ */
+ asoc->fragmented_delivery_inprogress = 0;
+ }
+ sctp_flush_reassm_for_str_seq(stcb, asoc, stseq->stream, stseq->sequence);
+ TAILQ_FOREACH(ctl, &stcb->sctp_ep->read_queue, next) {
+ if ((ctl->sinfo_stream == stseq->stream) &&
+ (ctl->sinfo_ssn == stseq->sequence)) {
+ str_seq = (stseq->stream << 16) | stseq->sequence;
+ ctl->end_added = 1;
+ ctl->pdapi_aborted = 1;
+ sv = stcb->asoc.control_pdapi;
+ stcb->asoc.control_pdapi = ctl;
+ sctp_notify_partial_delivery_indication(stcb,
+ SCTP_PARTIAL_DELIVERY_ABORTED,
+ SCTP_HOLDS_LOCK,
+ str_seq);
+ stcb->asoc.control_pdapi = sv;
+ break;
+ } else if ((ctl->sinfo_stream == stseq->stream) &&
+ (compare_with_wrap(ctl->sinfo_ssn, stseq->sequence, MAX_SEQ))) {
+ /* We are past our victim SSN */
+ break;
+ }
+ }
strm = &asoc->strmin[stseq->stream];
if (compare_with_wrap(stseq->sequence,
strm->last_sequence_delivered, MAX_SEQ)) {
@@ -6267,6 +6309,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
/* sa_ignore NO_NULL_CHK */
sctp_kick_prsctp_reorder_queue(stcb, strm);
}
+ SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
}
if (TAILQ_FIRST(&asoc->reasmqueue)) {
/* now lets kick out and check for more fragmented delivery */
@@ -7067,7 +7110,8 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
* fall through here and are
* marked
*/
- tp1->sent = SCTP_DATAGRAM_MARKED;
+ if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+ tp1->sent = SCTP_DATAGRAM_NR_MARKED;
if (tp1->rec.data.chunk_was_revoked) {
/* deflate the cwnd */
tp1->whoTo->cwnd -= tp1->book_size;
@@ -7079,7 +7123,8 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
* nr_marked
*/
if (all_bit) {
- tp1->sent = SCTP_DATAGRAM_NR_MARKED;
+ if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+ tp1->sent = SCTP_DATAGRAM_NR_MARKED;
/*
* TAILQ_REMOVE(&asoc
* ->sent_queue,
@@ -7198,7 +7243,8 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
while (tp1) {
if (tp1->rec.data.TSN_seq == j) {
if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
- tp1->sent = SCTP_DATAGRAM_NR_MARKED;
+ if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+ tp1->sent = SCTP_DATAGRAM_NR_MARKED;
/*
* TAILQ_REMOVE(&asoc
* ->sent_queue,
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 494929b..c962e4d 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -3150,8 +3150,10 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
(uintptr_t) stcb,
tp1->rec.data.TSN_seq);
}
- sctp_flight_size_decrease(tp1);
- sctp_total_flight_decrease(stcb, tp1);
+ if (tp1->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_decrease(tp1);
+ sctp_total_flight_decrease(stcb, tp1);
+ }
} {
/* audit code */
unsigned int audit;
@@ -5606,11 +5608,14 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
/* there was a gap before this data was processed */
was_a_gap = 1;
}
+ stcb->asoc.send_sack = 1;
sctp_sack_check(stcb, 1, was_a_gap, &abort_flag);
if (abort_flag) {
/* Again, we aborted so NO UNLOCK needed */
goto out_now;
}
+ } else if (fwd_tsn_seen) {
+ stcb->asoc.send_sack = 1;
}
/* trigger send of any chunks in queue... */
trigger_send:
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 9c5603d..5885474 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -1859,1812 +1859,6 @@ struct sack_track sack_array[256] = {
}
};
-/* EY below are nr_sacks version of the preceeding two data structures, identical except their names */
-#define SCTP_MAX_NR_GAPS_INARRAY 4
-struct nr_sack_track {
- uint8_t right_edge; /* mergable on the right edge */
- uint8_t left_edge; /* mergable on the left edge */
- uint8_t num_entries;
- uint8_t spare;
- struct sctp_nr_gap_ack_block nr_gaps[SCTP_MAX_NR_GAPS_INARRAY];
-};
-
-struct nr_sack_track nr_sack_array[256] = {
- {0, 0, 0, 0, /* 0x00 */
- {{0, 0},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x01 */
- {{0, 0},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x02 */
- {{1, 1},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x03 */
- {{0, 1},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x04 */
- {{2, 2},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x05 */
- {{0, 0},
- {2, 2},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x06 */
- {{1, 2},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x07 */
- {{0, 2},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x08 */
- {{3, 3},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x09 */
- {{0, 0},
- {3, 3},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x0a */
- {{1, 1},
- {3, 3},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x0b */
- {{0, 1},
- {3, 3},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x0c */
- {{2, 3},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x0d */
- {{0, 0},
- {2, 3},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x0e */
- {{1, 3},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x0f */
- {{0, 3},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x10 */
- {{4, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x11 */
- {{0, 0},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x12 */
- {{1, 1},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x13 */
- {{0, 1},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x14 */
- {{2, 2},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x15 */
- {{0, 0},
- {2, 2},
- {4, 4},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x16 */
- {{1, 2},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x17 */
- {{0, 2},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x18 */
- {{3, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x19 */
- {{0, 0},
- {3, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x1a */
- {{1, 1},
- {3, 4},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x1b */
- {{0, 1},
- {3, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x1c */
- {{2, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x1d */
- {{0, 0},
- {2, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x1e */
- {{1, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x1f */
- {{0, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x20 */
- {{5, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x21 */
- {{0, 0},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x22 */
- {{1, 1},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x23 */
- {{0, 1},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x24 */
- {{2, 2},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x25 */
- {{0, 0},
- {2, 2},
- {5, 5},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x26 */
- {{1, 2},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x27 */
- {{0, 2},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x28 */
- {{3, 3},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x29 */
- {{0, 0},
- {3, 3},
- {5, 5},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x2a */
- {{1, 1},
- {3, 3},
- {5, 5},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x2b */
- {{0, 1},
- {3, 3},
- {5, 5},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x2c */
- {{2, 3},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x2d */
- {{0, 0},
- {2, 3},
- {5, 5},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x2e */
- {{1, 3},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x2f */
- {{0, 3},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x30 */
- {{4, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x31 */
- {{0, 0},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x32 */
- {{1, 1},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x33 */
- {{0, 1},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x34 */
- {{2, 2},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x35 */
- {{0, 0},
- {2, 2},
- {4, 5},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x36 */
- {{1, 2},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x37 */
- {{0, 2},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x38 */
- {{3, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x39 */
- {{0, 0},
- {3, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x3a */
- {{1, 1},
- {3, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x3b */
- {{0, 1},
- {3, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x3c */
- {{2, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x3d */
- {{0, 0},
- {2, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x3e */
- {{1, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x3f */
- {{0, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x40 */
- {{6, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x41 */
- {{0, 0},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x42 */
- {{1, 1},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x43 */
- {{0, 1},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x44 */
- {{2, 2},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x45 */
- {{0, 0},
- {2, 2},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x46 */
- {{1, 2},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x47 */
- {{0, 2},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x48 */
- {{3, 3},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x49 */
- {{0, 0},
- {3, 3},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x4a */
- {{1, 1},
- {3, 3},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x4b */
- {{0, 1},
- {3, 3},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x4c */
- {{2, 3},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x4d */
- {{0, 0},
- {2, 3},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x4e */
- {{1, 3},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x4f */
- {{0, 3},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x50 */
- {{4, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x51 */
- {{0, 0},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x52 */
- {{1, 1},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x53 */
- {{0, 1},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x54 */
- {{2, 2},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 4, 0, /* 0x55 */
- {{0, 0},
- {2, 2},
- {4, 4},
- {6, 6}
- }
- },
- {0, 0, 3, 0, /* 0x56 */
- {{1, 2},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x57 */
- {{0, 2},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x58 */
- {{3, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x59 */
- {{0, 0},
- {3, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x5a */
- {{1, 1},
- {3, 4},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x5b */
- {{0, 1},
- {3, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x5c */
- {{2, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x5d */
- {{0, 0},
- {2, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x5e */
- {{1, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x5f */
- {{0, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x60 */
- {{5, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x61 */
- {{0, 0},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x62 */
- {{1, 1},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x63 */
- {{0, 1},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x64 */
- {{2, 2},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x65 */
- {{0, 0},
- {2, 2},
- {5, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x66 */
- {{1, 2},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x67 */
- {{0, 2},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x68 */
- {{3, 3},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x69 */
- {{0, 0},
- {3, 3},
- {5, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x6a */
- {{1, 1},
- {3, 3},
- {5, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x6b */
- {{0, 1},
- {3, 3},
- {5, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x6c */
- {{2, 3},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x6d */
- {{0, 0},
- {2, 3},
- {5, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x6e */
- {{1, 3},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x6f */
- {{0, 3},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x70 */
- {{4, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x71 */
- {{0, 0},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x72 */
- {{1, 1},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x73 */
- {{0, 1},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x74 */
- {{2, 2},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x75 */
- {{0, 0},
- {2, 2},
- {4, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x76 */
- {{1, 2},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x77 */
- {{0, 2},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x78 */
- {{3, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x79 */
- {{0, 0},
- {3, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x7a */
- {{1, 1},
- {3, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x7b */
- {{0, 1},
- {3, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x7c */
- {{2, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x7d */
- {{0, 0},
- {2, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x7e */
- {{1, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x7f */
- {{0, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0x80 */
- {{7, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x81 */
- {{0, 0},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x82 */
- {{1, 1},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x83 */
- {{0, 1},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x84 */
- {{2, 2},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x85 */
- {{0, 0},
- {2, 2},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x86 */
- {{1, 2},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x87 */
- {{0, 2},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x88 */
- {{3, 3},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x89 */
- {{0, 0},
- {3, 3},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0x8a */
- {{1, 1},
- {3, 3},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x8b */
- {{0, 1},
- {3, 3},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x8c */
- {{2, 3},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x8d */
- {{0, 0},
- {2, 3},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x8e */
- {{1, 3},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x8f */
- {{0, 3},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x90 */
- {{4, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x91 */
- {{0, 0},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0x92 */
- {{1, 1},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x93 */
- {{0, 1},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0x94 */
- {{2, 2},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0x95 */
- {{0, 0},
- {2, 2},
- {4, 4},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0x96 */
- {{1, 2},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x97 */
- {{0, 2},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x98 */
- {{3, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x99 */
- {{0, 0},
- {3, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0x9a */
- {{1, 1},
- {3, 4},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x9b */
- {{0, 1},
- {3, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x9c */
- {{2, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x9d */
- {{0, 0},
- {2, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x9e */
- {{1, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x9f */
- {{0, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xa0 */
- {{5, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xa1 */
- {{0, 0},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xa2 */
- {{1, 1},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xa3 */
- {{0, 1},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xa4 */
- {{2, 2},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xa5 */
- {{0, 0},
- {2, 2},
- {5, 5},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0xa6 */
- {{1, 2},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xa7 */
- {{0, 2},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xa8 */
- {{3, 3},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xa9 */
- {{0, 0},
- {3, 3},
- {5, 5},
- {7, 7}
- }
- },
- {0, 1, 4, 0, /* 0xaa */
- {{1, 1},
- {3, 3},
- {5, 5},
- {7, 7}
- }
- },
- {1, 1, 4, 0, /* 0xab */
- {{0, 1},
- {3, 3},
- {5, 5},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0xac */
- {{2, 3},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xad */
- {{0, 0},
- {2, 3},
- {5, 5},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0xae */
- {{1, 3},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xaf */
- {{0, 3},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xb0 */
- {{4, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xb1 */
- {{0, 0},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xb2 */
- {{1, 1},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xb3 */
- {{0, 1},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xb4 */
- {{2, 2},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xb5 */
- {{0, 0},
- {2, 2},
- {4, 5},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0xb6 */
- {{1, 2},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xb7 */
- {{0, 2},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xb8 */
- {{3, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xb9 */
- {{0, 0},
- {3, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xba */
- {{1, 1},
- {3, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xbb */
- {{0, 1},
- {3, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xbc */
- {{2, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xbd */
- {{0, 0},
- {2, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xbe */
- {{1, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xbf */
- {{0, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xc0 */
- {{6, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xc1 */
- {{0, 0},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xc2 */
- {{1, 1},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xc3 */
- {{0, 1},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xc4 */
- {{2, 2},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xc5 */
- {{0, 0},
- {2, 2},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xc6 */
- {{1, 2},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xc7 */
- {{0, 2},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xc8 */
- {{3, 3},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xc9 */
- {{0, 0},
- {3, 3},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xca */
- {{1, 1},
- {3, 3},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xcb */
- {{0, 1},
- {3, 3},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xcc */
- {{2, 3},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xcd */
- {{0, 0},
- {2, 3},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xce */
- {{1, 3},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xcf */
- {{0, 3},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xd0 */
- {{4, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xd1 */
- {{0, 0},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xd2 */
- {{1, 1},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xd3 */
- {{0, 1},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xd4 */
- {{2, 2},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xd5 */
- {{0, 0},
- {2, 2},
- {4, 4},
- {6, 7}
- }
- },
- {0, 1, 3, 0, /* 0xd6 */
- {{1, 2},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xd7 */
- {{0, 2},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xd8 */
- {{3, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xd9 */
- {{0, 0},
- {3, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xda */
- {{1, 1},
- {3, 4},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xdb */
- {{0, 1},
- {3, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xdc */
- {{2, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xdd */
- {{0, 0},
- {2, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xde */
- {{1, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xdf */
- {{0, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xe0 */
- {{5, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xe1 */
- {{0, 0},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xe2 */
- {{1, 1},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xe3 */
- {{0, 1},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xe4 */
- {{2, 2},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xe5 */
- {{0, 0},
- {2, 2},
- {5, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xe6 */
- {{1, 2},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xe7 */
- {{0, 2},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xe8 */
- {{3, 3},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xe9 */
- {{0, 0},
- {3, 3},
- {5, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xea */
- {{1, 1},
- {3, 3},
- {5, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xeb */
- {{0, 1},
- {3, 3},
- {5, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xec */
- {{2, 3},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xed */
- {{0, 0},
- {2, 3},
- {5, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xee */
- {{1, 3},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xef */
- {{0, 3},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xf0 */
- {{4, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xf1 */
- {{0, 0},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xf2 */
- {{1, 1},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xf3 */
- {{0, 1},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xf4 */
- {{2, 2},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xf5 */
- {{0, 0},
- {2, 2},
- {4, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xf6 */
- {{1, 2},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xf7 */
- {{0, 2},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xf8 */
- {{3, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xf9 */
- {{0, 0},
- {3, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xfa */
- {{1, 1},
- {3, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xfb */
- {{0, 1},
- {3, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xfc */
- {{2, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xfd */
- {{0, 0},
- {2, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xfe */
- {{1, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 1, 0, /* 0xff */
- {{0, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- }
-};
-
-
int
sctp_is_address_in_scope(struct sctp_ifa *ifa,
@@ -7920,7 +6114,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
struct sctp_association *asoc,
int *num_out,
int *reason_code,
- int control_only, int *cwnd_full, int from_where,
+ int control_only, int from_where,
struct timeval *now, int *now_filled, int frag_point, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -8106,13 +6300,13 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
if (do_chunk_output)
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_NOT_LOCKED);
else if (added_control) {
- int num_out = 0, reason = 0, cwnd_full = 0, now_filled = 0;
+ int num_out = 0, reason = 0, now_filled = 0;
struct timeval now;
int frag_point;
frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
(void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out,
- &reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point, SCTP_SO_NOT_LOCKED);
+ &reason, 1, 1, &now, &now_filled, frag_point, SCTP_SO_NOT_LOCKED);
}
no_chunk_output:
if (ret) {
@@ -9195,7 +7389,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
struct sctp_association *asoc,
int *num_out,
int *reason_code,
- int control_only, int *cwnd_full, int from_where,
+ int control_only, int from_where,
struct timeval *now, int *now_filled, int frag_point, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -9211,18 +7405,18 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
* fomulate and send the low level chunks. Making sure to combine
* any control in the control chunk queue also.
*/
- struct sctp_nets *net;
+ struct sctp_nets *net, *start_at, *old_start_at = NULL;
struct mbuf *outchain, *endoutchain;
struct sctp_tmit_chunk *chk, *nchk;
/* temp arrays for unlinking */
struct sctp_tmit_chunk *data_list[SCTP_MAX_DATA_BUNDLING];
int no_fragmentflg, error;
+ unsigned int max_rwnd_per_dest;
int one_chunk, hbflag, skip_data_for_this_net;
int asconf, cookie, no_out_cnt;
- int bundle_at, ctl_cnt, no_data_chunks, cwnd_full_ind, eeor_mode;
+ int bundle_at, ctl_cnt, no_data_chunks, eeor_mode;
unsigned int mtu, r_mtu, omtu, mx_mtu, to_out;
- struct sctp_nets *start_at, *old_startat = NULL, *send_start_at;
int tsns_sent = 0;
uint32_t auth_offset = 0;
struct sctp_auth_chunk *auth = NULL;
@@ -9238,7 +7432,6 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
int quit_now = 0;
*num_out = 0;
- cwnd_full_ind = 0;
auth_keyid = stcb->asoc.authinfo.active_keyid;
if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
@@ -9274,112 +7467,61 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
}
if (asoc->peers_rwnd == 0) {
/* No room in peers rwnd */
- *cwnd_full = 1;
*reason_code = 1;
if (asoc->total_flight > 0) {
/* we are allowed one chunk in flight */
no_data_chunks = 1;
}
}
+ max_rwnd_per_dest = ((asoc->peers_rwnd + asoc->total_flight) / asoc->numnets);
if ((no_data_chunks == 0) && (!TAILQ_EMPTY(&asoc->out_wheel))) {
- if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
- /*
- * for CMT we start at the next one past the one we
- * last added data to.
- */
- if (TAILQ_FIRST(&asoc->send_queue) != NULL) {
- goto skip_the_fill_from_streams;
- }
- if (asoc->last_net_data_came_from) {
- net = TAILQ_NEXT(asoc->last_net_data_came_from, sctp_next);
- if (net == NULL) {
- net = TAILQ_FIRST(&asoc->nets);
- }
- } else {
- /* back to start */
- net = TAILQ_FIRST(&asoc->nets);
- }
-
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
/*
- * JRI-TODO: CMT-MPI. Simply set the first
- * destination (net) to be optimized for the next
- * message to be pulled out of the outwheel. 1. peek
- * at outwheel 2. If large message, set net =
- * highest_cwnd 3. If small message, set net =
- * lowest rtt
+ * This for loop we are in takes in each net, if
+ * its's got space in cwnd and has data sent to it
+ * (when CMT is off) then it calls
+ * sctp_fill_outqueue for the net. This gets data on
+ * the send queue for that network.
+ *
+ * In sctp_fill_outqueue TSN's are assigned and data is
+ * copied out of the stream buffers. Note mostly
+ * copy by reference (we hope).
*/
- } else {
- net = asoc->primary_destination;
- if (net == NULL) {
- /* TSNH */
- net = TAILQ_FIRST(&asoc->nets);
- }
- }
- start_at = net;
-
-one_more_time:
- for (; net != NULL; net = TAILQ_NEXT(net, sctp_next)) {
net->window_probe = 0;
- if (old_startat && (old_startat == net)) {
- break;
- }
- /*
- * JRI: if dest is unreachable or unconfirmed, do
- * not send data to it
- */
if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) || (net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
- continue;
- }
- /*
- * JRI: if dest is in PF state, do not send data to
- * it
- */
- if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
- SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
- (net->dest_state & SCTP_ADDR_PF)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
+ sctp_log_cwnd(stcb, net, 1,
+ SCTP_CWND_LOG_FILL_OUTQ_CALLED);
+ }
continue;
}
if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) && (net->ref_count < 2)) {
/* nothing can be in queue for this guy */
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
+ sctp_log_cwnd(stcb, net, 2,
+ SCTP_CWND_LOG_FILL_OUTQ_CALLED);
+ }
continue;
}
if (net->flight_size >= net->cwnd) {
- /* skip this network, no room */
- cwnd_full_ind++;
+ /* skip this network, no room - can't fill */
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
+ sctp_log_cwnd(stcb, net, 3,
+ SCTP_CWND_LOG_FILL_OUTQ_CALLED);
+ }
continue;
}
- /*
- * JRI : this for loop we are in takes in each net,
- * if its's got space in cwnd and has data sent to
- * it (when CMT is off) then it calls
- * sctp_fill_outqueue for the net. This gets data on
- * the send queue for that network.
- *
- * In sctp_fill_outqueue TSN's are assigned and data is
- * copied out of the stream buffers. Note mostly
- * copy by reference (we hope).
- */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
- sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FILL_OUTQ_CALLED);
+ sctp_log_cwnd(stcb, net, 4, SCTP_CWND_LOG_FILL_OUTQ_CALLED);
}
sctp_fill_outqueue(stcb, net, frag_point, eeor_mode, &quit_now);
if (quit_now) {
/* memory alloc failure */
no_data_chunks = 1;
- goto skip_the_fill_from_streams;
+ break;
}
}
- if (start_at != TAILQ_FIRST(&asoc->nets)) {
- /* got to pick up the beginning stuff. */
- old_startat = start_at;
- start_at = net = TAILQ_FIRST(&asoc->nets);
- if (old_startat)
- goto one_more_time;
- }
}
-skip_the_fill_from_streams:
- *cwnd_full = cwnd_full_ind;
-
/* now service each destination and send out what we can for it */
/* Nothing to send? */
if ((TAILQ_FIRST(&asoc->control_send_queue) == NULL) &&
@@ -9388,32 +7530,45 @@ skip_the_fill_from_streams:
*reason_code = 8;
return (0);
}
- if (no_data_chunks) {
- chk = TAILQ_FIRST(&asoc->asconf_send_queue);
- if (chk == NULL)
- chk = TAILQ_FIRST(&asoc->control_send_queue);
- } else {
- chk = TAILQ_FIRST(&asoc->send_queue);
- }
- if (chk) {
- send_start_at = chk->whoTo;
+ if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
+ /* get the last start point */
+ start_at = asoc->last_net_cmt_send_started;
+ if (start_at == NULL) {
+ /* null so to beginning */
+ start_at = TAILQ_FIRST(&asoc->nets);
+ } else {
+ start_at = TAILQ_NEXT(asoc->last_net_cmt_send_started, sctp_next);
+ if (start_at == NULL) {
+ start_at = TAILQ_FIRST(&asoc->nets);
+ }
+ }
+ asoc->last_net_cmt_send_started = start_at;
} else {
- send_start_at = TAILQ_FIRST(&asoc->nets);
+ start_at = TAILQ_FIRST(&asoc->nets);
}
- old_startat = NULL;
+ old_start_at = NULL;
again_one_more_time:
- for (net = send_start_at; net != NULL; net = TAILQ_NEXT(net, sctp_next)) {
+ for (net = start_at; net != NULL; net = TAILQ_NEXT(net, sctp_next)) {
/* how much can we send? */
/* SCTPDBG("Examine for sending net:%x\n", (uint32_t)net); */
- if (old_startat && (old_startat == net)) {
+ if (old_start_at && (old_start_at == net)) {
/* through list ocmpletely. */
break;
}
- tsns_sent = 0;
- if (net->ref_count < 2) {
+ tsns_sent = 0xa;
+ if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) && (net->ref_count < 2)) {
/*
* Ref-count of 1 so we cannot have data or control
- * queued to this address. Skip it.
+ * queued to this address. Skip it (non-CMT).
+ */
+ continue;
+ }
+ if ((TAILQ_FIRST(&asoc->control_send_queue) == NULL) &&
+ (TAILQ_FIRST(&asoc->asconf_send_queue) == NULL) &&
+ (net->flight_size >= net->cwnd)) {
+ /*
+ * Nothing on control or asconf and flight is full,
+ * we can skip even in the CMT case.
*/
continue;
}
@@ -9885,6 +8040,19 @@ again_one_more_time:
}
}
}
+ /* JRI: if dest is in PF state, do not send data to it */
+ if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
+ SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
+ (net->dest_state & SCTP_ADDR_PF)) {
+ goto no_data_fill;
+ }
+ if (net->flight_size >= net->cwnd) {
+ goto no_data_fill;
+ }
+ if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off)) &&
+ (net->flight_size > max_rwnd_per_dest)) {
+ goto no_data_fill;
+ }
/*********************/
/* Data transmission */
/*********************/
@@ -9920,7 +8088,8 @@ again_one_more_time:
omtu = 0;
break;
}
- if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) && (skip_data_for_this_net == 0)) ||
+ if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) &&
+ (skip_data_for_this_net == 0)) ||
(cookie)) {
for (chk = TAILQ_FIRST(&asoc->send_queue); chk; chk = nchk) {
if (no_data_chunks) {
@@ -9934,7 +8103,18 @@ again_one_more_time:
break;
}
nchk = TAILQ_NEXT(chk, sctp_next);
- if (chk->whoTo != net) {
+ if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
+ if (chk->whoTo != net) {
+ /*
+ * For CMT, steal the data
+ * to this network if its
+ * not set here.
+ */
+ sctp_free_remote_addr(chk->whoTo);
+ chk->whoTo = net;
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
+ } else if (chk->whoTo != net) {
/* No, not sent to this net */
continue;
}
@@ -10074,6 +8254,7 @@ again_one_more_time:
}
} /* for (chunk gather loop for this net) */
} /* if asoc.state OPEN */
+no_data_fill:
/* Is there something to send for this destination? */
if (outchain) {
/* We may need to start a control timer or two */
@@ -10222,10 +8403,10 @@ again_one_more_time:
sctp_log_cwnd(stcb, net, tsns_sent, SCTP_CWND_LOG_FROM_SEND);
}
}
- if (old_startat == NULL) {
- old_startat = send_start_at;
- send_start_at = TAILQ_FIRST(&asoc->nets);
- if (old_startat)
+ if (old_start_at == NULL) {
+ old_start_at = start_at;
+ start_at = TAILQ_FIRST(&asoc->nets);
+ if (old_start_at)
goto again_one_more_time;
}
/*
@@ -11270,7 +9451,6 @@ sctp_chunk_output(struct sctp_inpcb *inp,
burst_cnt = 0, burst_limit = 0;
struct timeval now;
int now_filled = 0;
- int cwnd_full = 0;
int nagle_on = 0;
int frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
int un_sent = 0;
@@ -11321,7 +9501,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
* and then the next call with get the retran's.
*/
(void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1,
- &cwnd_full, from_where,
+ from_where,
&now, &now_filled, frag_point, so_locked);
return;
} else if (from_where != SCTP_OUTPUT_FROM_HB_TMR) {
@@ -11346,7 +9526,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
* if queued too.
*/
(void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1,
- &cwnd_full, from_where,
+ from_where,
&now, &now_filled, frag_point, so_locked);
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(8, inp, stcb, NULL);
@@ -11373,7 +9553,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
sctp_auditing(10, inp, stcb, NULL);
#endif
/* Push out any control */
- (void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1, &cwnd_full, from_where,
+ (void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1, from_where,
&now, &now_filled, frag_point, so_locked);
return;
}
@@ -11444,10 +9624,9 @@ sctp_chunk_output(struct sctp_inpcb *inp,
}
burst_cnt = 0;
- cwnd_full = 0;
do {
error = sctp_med_chunk_output(inp, stcb, asoc, &num_out,
- &reason_code, 0, &cwnd_full, from_where,
+ &reason_code, 0, from_where,
&now, &now_filled, frag_point, so_locked);
if (error) {
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Error %d was returned from med-c-op\n", error);
@@ -11906,7 +10085,11 @@ sctp_send_sack(struct sctp_tcb *stcb)
gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)sack + sizeof(struct sctp_sack_chunk));
- siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
+ if (asoc->highest_tsn_inside_map > asoc->mapping_array_base_tsn)
+ siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
+ else
+ siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_map + 7) / 8;
+
if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
offset = 1;
/*-
@@ -12034,7 +10217,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
struct sctp_nr_gap_ack_block *nr_gap_descriptor;
struct sack_track *selector;
- struct nr_sack_track *nr_selector;
+ struct sack_track *nr_selector;
/* EY do we need nr_mergeable, NO */
int mergeable = 0;
@@ -12214,9 +10397,12 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
stcb->freed_by_sorcv_sincelast = 0;
gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)nr_sack + sizeof(struct sctp_nr_sack_chunk));
- nr_gap_descriptor = (struct sctp_nr_gap_ack_block *)((caddr_t)nr_sack + sizeof(struct sctp_nr_sack_chunk));
- siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
+ if (asoc->highest_tsn_inside_map > asoc->mapping_array_base_tsn)
+ siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
+ else
+ siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_map + 7) / 8;
+
if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
offset = 1;
/*-
@@ -12299,11 +10485,15 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
nr_gap_descriptor = (struct sctp_nr_gap_ack_block *)gap_descriptor;
/* EY - there will be gaps + nr_gaps if draining is possible */
- if (SCTP_BASE_SYSCTL(sctp_do_drain)) {
+ if ((SCTP_BASE_SYSCTL(sctp_do_drain)) && (limit_reached == 0)) {
mergeable = 0;
- siz = (((asoc->highest_tsn_inside_nr_map - asoc->nr_mapping_array_base_tsn) + 1) + 7) / 8;
+ if (asoc->highest_tsn_inside_nr_map > asoc->nr_mapping_array_base_tsn)
+ siz = (((asoc->highest_tsn_inside_nr_map - asoc->nr_mapping_array_base_tsn) + 1) + 7) / 8;
+ else
+ siz = (((MAX_TSN - asoc->nr_mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_nr_map + 7) / 8;
+
if (compare_with_wrap(asoc->nr_mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
offset = 1;
/*-
@@ -12322,7 +10512,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, asoc->cumulative_tsn, MAX_TSN)) {
/* we have a gap .. maybe */
for (i = 0; i < siz; i++) {
- nr_selector = &nr_sack_array[asoc->nr_mapping_array[i]];
+ nr_selector = &sack_array[asoc->nr_mapping_array[i]];
if (mergeable && nr_selector->right_edge) {
/*
* Backup, left and right edges were
@@ -12348,9 +10538,9 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
* left side
*/
mergeable = 0;
- nr_gap_descriptor->start = htons((nr_selector->nr_gaps[j].start + offset));
+ nr_gap_descriptor->start = htons((nr_selector->gaps[j].start + offset));
}
- nr_gap_descriptor->end = htons((nr_selector->nr_gaps[j].end + offset));
+ nr_gap_descriptor->end = htons((nr_selector->gaps[j].end + offset));
num_nr_gap_blocks++;
nr_gap_descriptor++;
if (((caddr_t)nr_gap_descriptor + sizeof(struct sctp_nr_gap_ack_block)) > limit) {
@@ -12372,7 +10562,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
}
}
}
- /*---------------------------------------------------End of---filling the nr_gap_ack blocks----------------------------------------------------*/
+ /*---------------------------------------------End of---filling the nr_gap_ack blocks----------------------------------------------------*/
/* now we must add any dups we are going to report. */
if ((limit_reached == 0) && (asoc->numduptsns)) {
@@ -15445,7 +13635,7 @@ skip_out_eof:
}
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED);
} else if (some_on_control) {
- int num_out, reason, cwnd_full, frag_point;
+ int num_out, reason, frag_point;
/* Here we do control only */
if (hold_tcblock == 0) {
@@ -15454,7 +13644,7 @@ skip_out_eof:
}
frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
(void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out,
- &reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point, SCTP_SO_LOCKED);
+ &reason, 1, 1, &now, &now_filled, frag_point, SCTP_SO_LOCKED);
}
SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d\n",
queue_only, stcb->asoc.peers_rwnd, un_sent,
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index d98e760..df519cc 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -3157,8 +3157,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_TCB_UNLOCK(asoc);
continue;
}
- if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ if (((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_ECHOED)) &&
+ (asoc->asoc.total_output_queue_size == 0)) {
/*
* If we have data in queue, we don't want
* to just free since the app may have done,
@@ -6029,6 +6030,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
stcb->asoc.peer_supports_prsctp = 0;
stcb->asoc.peer_supports_pktdrop = 0;
stcb->asoc.peer_supports_strreset = 0;
+ stcb->asoc.peer_supports_nr_sack = 0;
stcb->asoc.peer_supports_auth = 0;
pr_supported = (struct sctp_supported_chunk_types_param *)phdr;
num_ent = plen - sizeof(struct sctp_paramhdr);
@@ -6044,6 +6046,12 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
case SCTP_PACKET_DROPPED:
stcb->asoc.peer_supports_pktdrop = 1;
break;
+ case SCTP_NR_SELECTIVE_ACK:
+ if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off))
+ stcb->asoc.peer_supports_nr_sack = 1;
+ else
+ stcb->asoc.peer_supports_nr_sack = 0;
+ break;
case SCTP_STREAM_RESET:
stcb->asoc.peer_supports_strreset = 1;
break;
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index 0d9f67d..24ae10f 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -196,6 +196,7 @@ struct sctp_nets {
/* smoothed average things for RTT and RTO itself */
int lastsa;
int lastsv;
+ int rtt; /* last measured rtt value in ms */
unsigned int RTO;
/* This is used for SHUTDOWN/SHUTDOWN-ACK/SEND or INIT timers */
@@ -677,7 +678,7 @@ struct sctp_association {
/* primary destination to use */
struct sctp_nets *primary_destination;
/* For CMT */
- struct sctp_nets *last_net_data_came_from;
+ struct sctp_nets *last_net_cmt_send_started;
/* last place I got a data chunk from */
struct sctp_nets *last_data_chunk_from;
/* last place I got a control from */
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index a64aec4..7570446 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -463,6 +463,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.cwnd = net->cwnd;
xraddr.flight_size = net->flight_size;
xraddr.mtu = net->mtu;
+ /* xraddr.rtt = net->rtt; Not yet */
xraddr.start_time.tv_sec = (uint32_t) net->start_time.tv_sec;
xraddr.start_time.tv_usec = (uint32_t) net->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h
index dd42d41..7419568 100644
--- a/sys/netinet/sctp_sysctl.h
+++ b/sys/netinet/sctp_sysctl.h
@@ -74,7 +74,7 @@ struct sctp_sysctl {
uint32_t sctp_nr_outgoing_streams_default;
uint32_t sctp_cmt_on_off;
uint32_t sctp_cmt_use_dac;
-/* EY 5/5/08 - nr_sack flag variable */
+ /* EY 5/5/08 - nr_sack flag variable */
uint32_t sctp_nr_sack_on_off;
uint32_t sctp_cmt_pf;
uint32_t sctp_use_cwnd_based_maxburst;
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index b8d2ecd..dc79939 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -565,9 +565,9 @@ struct sctp_sack_info {
struct sctp_cwnd_args {
struct sctp_nets *net; /* network to *//* FIXME: LP64 issue */
uint32_t cwnd_new_value;/* cwnd in k */
- uint32_t inflight; /* flightsize in k */
uint32_t pseudo_cumack;
- uint32_t cwnd_augment; /* increment to it */
+ uint16_t inflight; /* flightsize in k */
+ uint16_t cwnd_augment; /* increment to it */
uint8_t meets_pseudo_cumack;
uint8_t need_new_pseudo_cumack;
uint8_t cnt_in_send;
@@ -1042,6 +1042,7 @@ struct xsctp_raddr {
uint8_t heartbeat_enabled; /* sctpAssocLocalRemEntry 4 */
struct sctp_timeval start_time; /* sctpAssocLocalRemEntry 8 */
uint32_t extra_padding[8]; /* future */
+
};
#define SCTP_MAX_LOGGING_SIZE 30000
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index b3bfea5..c80cca0 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -126,6 +126,10 @@ sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
* since we sent to big of chunk
*/
chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
+ if (chk->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_decrease(chk);
+ sctp_total_flight_decrease(stcb, chk);
+ }
if (chk->sent != SCTP_DATAGRAM_RESEND) {
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
}
@@ -140,8 +144,6 @@ sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
}
/* Clear any time so NO RTT is being done */
chk->do_rtt = 0;
- sctp_flight_size_decrease(chk);
- sctp_total_flight_decrease(stcb, chk);
}
}
}
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 42a47ac..aea7376 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -970,7 +970,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->sent_queue_retran_cnt = 0;
/* for CMT */
- asoc->last_net_data_came_from = NULL;
+ asoc->last_net_cmt_send_started = NULL;
/* This will need to be adjusted */
asoc->last_cwr_tsn = asoc->init_seq_number - 1;
@@ -1222,33 +1222,25 @@ sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed)
SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
asoc->mapping_array = new_array;
asoc->mapping_array_size = new_size;
- return (0);
-}
-
-/* EY - nr_sack version of the above method */
-int
-sctp_expand_nr_mapping_array(struct sctp_association *asoc, uint32_t needed)
-{
- /* nr mapping array needs to grow */
- uint8_t *new_array;
- uint32_t new_size;
-
- new_size = asoc->nr_mapping_array_size + ((needed + 7) / 8 + SCTP_NR_MAPPING_ARRAY_INCR);
- SCTP_MALLOC(new_array, uint8_t *, new_size, SCTP_M_MAP);
- if (new_array == NULL) {
- /* can't get more, forget it */
- SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n",
- new_size);
- return (-1);
+ if (asoc->peer_supports_nr_sack) {
+ new_size = asoc->nr_mapping_array_size + ((needed + 7) / 8 + SCTP_NR_MAPPING_ARRAY_INCR);
+ SCTP_MALLOC(new_array, uint8_t *, new_size, SCTP_M_MAP);
+ if (new_array == NULL) {
+ /* can't get more, forget it */
+ SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n",
+ new_size);
+ return (-1);
+ }
+ memset(new_array, 0, new_size);
+ memcpy(new_array, asoc->nr_mapping_array, asoc->nr_mapping_array_size);
+ SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP);
+ asoc->nr_mapping_array = new_array;
+ asoc->nr_mapping_array_size = new_size;
}
- memset(new_array, 0, new_size);
- memcpy(new_array, asoc->nr_mapping_array, asoc->nr_mapping_array_size);
- SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP);
- asoc->nr_mapping_array = new_array;
- asoc->nr_mapping_array_size = new_size;
return (0);
}
+
#if defined(SCTP_USE_THREAD_BASED_ITERATOR)
static void
sctp_iterator_work(struct sctp_iterator *it)
@@ -2589,7 +2581,7 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
/***************************/
/* 2. update RTTVAR & SRTT */
/***************************/
- o_calctime = calc_time;
+ net->rtt = o_calctime = calc_time;
/* this is Van Jacobson's integer version */
if (net->RTO_measured) {
calc_time -= (net->lastsa >> SCTP_RTT_SHIFT); /* take away 1/8th when
@@ -4650,18 +4642,12 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
seq = tp1->rec.data.stream_seq;
do {
ret_sz += tp1->book_size;
- tp1->sent = SCTP_FORWARD_TSN_SKIP;
if (tp1->data != NULL) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- struct socket *so;
-
-#endif
- printf("Release PR-SCTP chunk tsn:%u flags:%x\n",
- tp1->rec.data.TSN_seq,
- (unsigned int)tp1->rec.data.rcv_flags);
+ if (tp1->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_decrease(tp1);
+ sctp_total_flight_decrease(stcb, tp1);
+ }
sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
- sctp_flight_size_decrease(tp1);
- sctp_total_flight_decrease(stcb, tp1);
stcb->asoc.peers_rwnd += tp1->send_size;
stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, so_locked);
@@ -4672,6 +4658,7 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
stcb->asoc.sent_queue_cnt_removeable--;
}
}
+ tp1->sent = SCTP_FORWARD_TSN_SKIP;
if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
SCTP_DATA_NOT_FRAG) {
/* not frag'ed we ae done */
@@ -4715,6 +4702,8 @@ next_on_sent:
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, so_locked);
sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
sctp_m_freem(tp1->data);
+ /* No flight involved here book the size to 0 */
+ tp1->book_size = 0;
tp1->data = NULL;
if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
foundeom = 1;
@@ -4780,6 +4769,7 @@ next_on_sent:
chk->pr_sctp_on = 1;
TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
stcb->asoc.sent_queue_cnt++;
+ stcb->asoc.pr_sctp_cnt++;
} else {
chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
}
@@ -4810,6 +4800,8 @@ next_on_sent:
}
if (do_wakeup_routine) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ struct socket *so;
+
so = SCTP_INP_SO(stcb->sctp_ep);
if (!so_locked) {
atomic_add_int(&stcb->asoc.refcnt, 1);
OpenPOWER on IntegriCloud