summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/sctp_constants.h2
-rw-r--r--sys/netinet/sctp_indata.c30
-rw-r--r--sys/netinet/sctp_input.c1
-rw-r--r--sys/netinet/sctp_output.c10
-rw-r--r--sys/netinet/sctp_pcb.c16
-rw-r--r--sys/netinet/sctp_timer.c2
-rw-r--r--sys/netinet/sctputil.c3
7 files changed, 46 insertions, 18 deletions
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 07f9612..1805700 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -370,7 +370,7 @@ __FBSDID("$FreeBSD$");
#define SCTP_DATAGRAM_ACKED 10010
#define SCTP_DATAGRAM_MARKED 20010
#define SCTP_FORWARD_TSN_SKIP 30010
-#define SCTP_DATAGRAM_NR_MARKED 40010
+#define SCTP_DATAGRAM_NR_ACKED 40010
/* chunk output send from locations */
#define SCTP_OUTPUT_FROM_USR_SEND 0
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 7701780..a394de5 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -2976,7 +2976,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
* (leave PR-SCTP ones that are to skip alone though)
*/
if ((tp1->sent != SCTP_FORWARD_TSN_SKIP) &&
- (tp1->sent != SCTP_DATAGRAM_NR_MARKED)) {
+ (tp1->sent != SCTP_DATAGRAM_NR_ACKED)) {
tp1->sent = SCTP_DATAGRAM_MARKED;
}
if (tp1->rec.data.chunk_was_revoked) {
@@ -2985,8 +2985,16 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
tp1->rec.data.chunk_was_revoked = 0;
}
/* NR Sack code here */
- if (nr_sacking) {
- tp1->sent = SCTP_DATAGRAM_NR_MARKED;
+ if (nr_sacking &&
+ (tp1->sent != SCTP_DATAGRAM_NR_ACKED)) {
+ if (stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) {
+ stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number);
+#endif
+ }
+ tp1->sent = SCTP_DATAGRAM_NR_ACKED;
if (tp1->data) {
/*
* sa_ignore
@@ -3091,7 +3099,6 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
uint32_t biggest_tsn_acked)
{
struct sctp_tmit_chunk *tp1;
- int tot_revoked = 0;
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cumack)) {
@@ -3126,7 +3133,6 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
* artificial inflation of the flight_size.
*/
tp1->whoTo->cwnd += tp1->book_size;
- tot_revoked++;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
sctp_log_sack(asoc->last_acked_seq,
cumack,
@@ -3603,13 +3609,13 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
if (tp1->sent != SCTP_FORWARD_TSN_SKIP &&
tp1->sent != SCTP_DATAGRAM_RESEND &&
- tp1->sent != SCTP_DATAGRAM_NR_MARKED) {
+ tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
/* no chance to advance, out of here */
break;
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) ||
- (tp1->sent == SCTP_DATAGRAM_NR_MARKED)) {
+ (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) {
sctp_misc_ints(SCTP_FWD_TSN_CHECK,
asoc->advanced_peer_ack_point,
tp1->rec.data.TSN_seq, 0, 0);
@@ -3658,7 +3664,7 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
* the next chunk.
*/
if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) ||
- (tp1->sent == SCTP_DATAGRAM_NR_MARKED)) {
+ (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) {
/* advance PeerAckPoint goes forward */
if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, asoc->advanced_peer_ack_point)) {
asoc->advanced_peer_ack_point = tp1->rec.data.TSN_seq;
@@ -3963,7 +3969,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
tp1->whoTo->cwnd -= tp1->book_size;
tp1->rec.data.chunk_was_revoked = 0;
}
- if (tp1->sent != SCTP_DATAGRAM_NR_MARKED) {
+ if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) {
asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--;
#ifdef INVARIANTS
@@ -4630,7 +4636,9 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
tp1->whoTo->cwnd -= tp1->book_size;
tp1->rec.data.chunk_was_revoked = 0;
}
- tp1->sent = SCTP_DATAGRAM_ACKED;
+ if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
+ tp1->sent = SCTP_DATAGRAM_ACKED;
+ }
}
} else {
break;
@@ -4707,7 +4715,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cum_ack)) {
break;
}
- if (tp1->sent != SCTP_DATAGRAM_NR_MARKED) {
+ if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) {
asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--;
#ifdef INVARIANTS
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index d1a0ef6..eb4be56 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -1948,6 +1948,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_NOT_LOCKED);
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ stcb->asoc.strmout[i].chunks_on_queues = 0;
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].next_sequence_send = 0;
stcb->asoc.strmout[i].last_msg_incomplete = 0;
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 4a77b34..aecf035 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -3513,8 +3513,9 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
stcb->asoc.pre_open_streams = stcb->asoc.streamoutcnt;
}
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
- stcb->asoc.strmout[i].next_sequence_send = 0;
TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
+ stcb->asoc.strmout[i].chunks_on_queues = 0;
+ stcb->asoc.strmout[i].next_sequence_send = 0;
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].last_msg_incomplete = 0;
stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
@@ -7494,6 +7495,7 @@ dont_do_it:
*locked = 1;
}
asoc->chunks_on_out_queue++;
+ strq->chunks_on_queues++;
TAILQ_INSERT_TAIL(&asoc->send_queue, chk, sctp_next);
asoc->send_queue_cnt++;
out_of:
@@ -10153,7 +10155,7 @@ sctp_fill_in_rest:
TAILQ_FOREACH(at, &asoc->sent_queue, sctp_next) {
if ((at->sent != SCTP_FORWARD_TSN_SKIP) &&
- (at->sent != SCTP_DATAGRAM_NR_MARKED)) {
+ (at->sent != SCTP_DATAGRAM_NR_ACKED)) {
/* no more to look at */
break;
}
@@ -11793,6 +11795,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 0, 1);
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
+ stcb->asoc.strmout[i].chunks_on_queues = oldstream[i].chunks_on_queues;
stcb->asoc.strmout[i].next_sequence_send = oldstream[i].next_sequence_send;
stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete;
stcb->asoc.strmout[i].stream_no = i;
@@ -11813,8 +11816,9 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
/* now the new streams */
stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
for (i = stcb->asoc.streamoutcnt; i < (stcb->asoc.streamoutcnt + adding_o); i++) {
- stcb->asoc.strmout[i].next_sequence_send = 0x0;
TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
+ stcb->asoc.strmout[i].chunks_on_queues = 0;
+ stcb->asoc.strmout[i].next_sequence_send = 0x0;
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].last_msg_incomplete = 0;
stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 93115f8..fb32635 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -4925,6 +4925,13 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* pending send queue SHOULD be empty */
TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
+ if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
+ asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
+#endif
+ }
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
if (chk->data) {
if (so) {
@@ -4949,7 +4956,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* sent queue SHOULD be empty */
TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
- if (chk->sent != SCTP_DATAGRAM_NR_MARKED) {
+ if (chk->sent != SCTP_DATAGRAM_NR_ACKED) {
if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
#ifdef INVARIANTS
@@ -4977,6 +4984,13 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
}
+#ifdef INVARIANTS
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ if (stcb->asoc.strmout[i].chunks_on_queues > 0) {
+ panic("%u chunks left for stream %u.", stcb->asoc.strmout[i].chunks_on_queues, i);
+ }
+ }
+#endif
/* control queue MAY not be empty */
TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index fe7f754..3444923 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -440,7 +440,7 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
if (SCTP_TSN_GE(asoc->last_acked_seq, chk->rec.data.TSN_seq)) {
SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n",
(void *)chk, chk->rec.data.TSN_seq, asoc->last_acked_seq);
- if (chk->sent != SCTP_DATAGRAM_NR_MARKED) {
+ if (chk->sent != SCTP_DATAGRAM_NR_ACKED) {
if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
}
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 72dc34e..007b138 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1054,6 +1054,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
*/
asoc->strmout[i].next_sequence_send = 0x0;
TAILQ_INIT(&asoc->strmout[i].outqueue);
+ asoc->strmout[i].chunks_on_queues = 0;
asoc->strmout[i].stream_no = i;
asoc->strmout[i].last_msg_incomplete = 0;
asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
@@ -3727,7 +3728,7 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock,
TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
asoc->sent_queue_cnt--;
- if (chk->sent != SCTP_DATAGRAM_NR_MARKED) {
+ if (chk->sent != SCTP_DATAGRAM_NR_ACKED) {
if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
#ifdef INVARIANTS
OpenPOWER on IntegriCloud