From 17aa08aca946bad5c41e3efa6f9fc217d14e9aaf Mon Sep 17 00:00:00 2001 From: tuexen Date: Fri, 16 Nov 2012 19:39:10 +0000 Subject: Get the accounting working. We now have counters how many chunks for each SCTP outgoing stream are in the send and sent queue. While there, improve the naming of NR-SACK related constants recently introduced. MFC after: 1 week --- sys/netinet/sctp_constants.h | 2 +- sys/netinet/sctp_indata.c | 30 +++++++++++++++++++----------- sys/netinet/sctp_input.c | 1 + sys/netinet/sctp_output.c | 10 +++++++--- sys/netinet/sctp_pcb.c | 16 +++++++++++++++- sys/netinet/sctp_timer.c | 2 +- sys/netinet/sctputil.c | 3 ++- 7 files changed, 46 insertions(+), 18 deletions(-) (limited to 'sys/netinet') 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 -- cgit v1.1