From 41648a46b774b148c40ddb0cdb3c07375ebc19e7 Mon Sep 17 00:00:00 2001 From: tuexen Date: Sun, 5 Nov 2017 11:59:33 +0000 Subject: [PATCH] Fix an accounting bug where data was counted twice if on the read queue and on the ordered or unordered queue. While there, improve the checking in INVARIANTs when computing the a_rwnd. MFC after: 3 days --- sys/netinet/sctp_indata.c | 41 +++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 79fe5d9e65c3..8a12d3c6bbb0 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -88,12 +88,14 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc) if (stcb->sctp_socket == NULL) { return (calc); } + KASSERT(asoc->cnt_on_reasm_queue > 0 || asoc->size_on_reasm_queue == 0, + ("size_on_reasm_queue is %u", asoc->size_on_reasm_queue)); + KASSERT(asoc->cnt_on_all_streams > 0 || asoc->size_on_all_streams == 0, + ("size_on_all_streams is %u", asoc->size_on_all_streams)); if (stcb->asoc.sb_cc == 0 && - asoc->size_on_reasm_queue == 0 && - asoc->size_on_all_streams == 0) { + asoc->cnt_on_reasm_queue == 0 && + asoc->cnt_on_all_streams == 0) { /* Full rwnd granted */ - KASSERT(asoc->cnt_on_reasm_queue == 0, ("cnt_on_reasm_queue is %u", asoc->cnt_on_reasm_queue)); - KASSERT(asoc->cnt_on_all_streams == 0, ("cnt_on_all_streams is %u", asoc->cnt_on_all_streams)); calc = max(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), SCTP_MINIMAL_RWND); return (calc); } @@ -1245,6 +1247,19 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc, } done = (control->end_added) && (control->last_frag_seen); if (control->on_read_q == 0) { + if (!done) { + if (asoc->size_on_all_streams >= control->length) { + asoc->size_on_all_streams -= control->length; + } else { +#ifdef INVARIANTS + panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length); +#else + asoc->size_on_all_streams = 0; +#endif + } + strm->pd_api_started = 1; + control->pdapi_started = 1; + } sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, control->end_added, @@ -1254,10 +1269,6 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc, if (done) { control = nctl; goto deliver_more; - } else { - /* We are now doing PD API */ - strm->pd_api_started = 1; - control->pdapi_started = 1; } } } @@ -1316,15 +1327,11 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *control, } else if (control->on_strm_q == SCTP_ON_ORDERED) { /* Ordered */ TAILQ_REMOVE(&strm->inqueue, control, next_instrm); - if (asoc->size_on_all_streams >= control->length) { - asoc->size_on_all_streams -= control->length; - } else { -#ifdef INVARIANTS - panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length); -#else - asoc->size_on_all_streams = 0; -#endif - } + /* + * Don't need to decrement + * size_on_all_streams, since control is on + * the read queue. + */ sctp_ucount_decr(asoc->cnt_on_all_streams); control->on_strm_q = 0; #ifdef INVARIANTS