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
This commit is contained in:
Michael Tuexen 2017-11-05 11:59:33 +00:00
parent a52058f013
commit 253a63b817
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=325434

View File

@ -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