diff options
author | rrs <rrs@FreeBSD.org> | 2010-07-29 11:37:04 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2010-07-29 11:37:04 +0000 |
commit | c9a735e2e795174cacdb32cf78185bc3c8fde78c (patch) | |
tree | 03cffd00fe5726c24c8cca36c9801d3dc3ff5732 /sys/netinet/sctp_indata.c | |
parent | a871a4e0159f3433c4ca560a62d1e6fbd89b4477 (diff) | |
download | FreeBSD-src-c9a735e2e795174cacdb32cf78185bc3c8fde78c.zip FreeBSD-src-c9a735e2e795174cacdb32cf78185bc3c8fde78c.tar.gz |
PR SCTP Bugs. Basically a full sized frame of
PR SCTP FWD-TSN's would not be sent and thus
cause a stalled connection. Also the rwnd
Calculation was also off on the receiver side for
PR-SCTP.
MFC after: 1 month
Diffstat (limited to 'sys/netinet/sctp_indata.c')
-rw-r--r-- | sys/netinet/sctp_indata.c | 31 |
1 files changed, 16 insertions, 15 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index e792648..e429da8 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -91,8 +91,10 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc) * take out what has NOT been put on socket queue and we yet hold * for putting up. */ - calc = sctp_sbspace_sub(calc, (uint32_t) asoc->size_on_reasm_queue); - calc = sctp_sbspace_sub(calc, (uint32_t) asoc->size_on_all_streams); + calc = sctp_sbspace_sub(calc, (uint32_t) (asoc->size_on_reasm_queue + + asoc->cnt_on_reasm_queue * MSIZE)); + calc = sctp_sbspace_sub(calc, (uint32_t) (asoc->size_on_all_streams + + asoc->cnt_on_all_streams * MSIZE)); if (calc == 0) { /* out of space */ @@ -3322,6 +3324,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, if (tp1->sent >= SCTP_DATAGRAM_RESEND) { /* either a RESEND, ACKED, or MARKED */ /* skip */ + if (tp1->sent == SCTP_FORWARD_TSN_SKIP) { + /* Continue strikin FWD-TSN chunks */ + tp1->rec.data.fwd_tsn_cnt++; + } tp1 = TAILQ_NEXT(tp1, sctp_next); continue; } @@ -3707,7 +3713,6 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb, tp1 = TAILQ_FIRST(&asoc->sent_queue); while (tp1) { if (tp1->sent != SCTP_FORWARD_TSN_SKIP && - tp1->sent != SCTP_DATAGRAM_ACKED && tp1->sent != SCTP_DATAGRAM_RESEND) { /* no chance to advance, out of here */ break; @@ -3763,8 +3768,7 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb, * the chunk, advance our peer ack point and we can check * the next chunk. */ - if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) || - (tp1->sent == SCTP_DATAGRAM_ACKED)) { + if (tp1->sent == SCTP_FORWARD_TSN_SKIP) { /* advance PeerAckPoint goes forward */ if (compare_with_wrap(tp1->rec.data.TSN_seq, asoc->advanced_peer_ack_point, @@ -3905,7 +3909,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, } else if (asoc->last_acked_seq == cumack) { /* Window update sack */ asoc->peers_rwnd = sctp_sbspace_sub(rwnd, - (uint32_t) (asoc->total_flight + (asoc->sent_queue_cnt * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)))); + (uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)))); if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { /* SWS sender side engages */ asoc->peers_rwnd = 0; @@ -4189,7 +4193,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, } /* RWND update */ asoc->peers_rwnd = sctp_sbspace_sub(rwnd, - (uint32_t) (asoc->total_flight + (asoc->sent_queue_cnt * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)))); + (uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)))); if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { /* SWS sender side engages */ asoc->peers_rwnd = 0; @@ -4404,10 +4408,8 @@ again: asoc->nonce_resync_tsn = asoc->advanced_peer_ack_point; } else if (lchk) { /* try to FR fwd-tsn's that get lost too */ - lchk->rec.data.fwd_tsn_cnt++; - if (lchk->rec.data.fwd_tsn_cnt > 3) { + if (lchk->rec.data.fwd_tsn_cnt >= 3) { send_forward_tsn(stcb, asoc); - lchk->rec.data.fwd_tsn_cnt = 0; } } } @@ -5188,10 +5190,10 @@ done_with_it: /* Adjust and set the new rwnd value */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) { sctp_log_rwnd_set(SCTP_SET_PEER_RWND_VIA_SACK, - asoc->peers_rwnd, asoc->total_flight, (asoc->sent_queue_cnt * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)), a_rwnd); + asoc->peers_rwnd, asoc->total_flight, (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)), a_rwnd); } asoc->peers_rwnd = sctp_sbspace_sub(a_rwnd, - (uint32_t) (asoc->total_flight + (asoc->sent_queue_cnt * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)))); + (uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)))); if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { /* SWS sender side engages */ asoc->peers_rwnd = 0; @@ -5314,6 +5316,7 @@ again: } if (compare_with_wrap(asoc->advanced_peer_ack_point, old_adv_peer_ack_point, MAX_TSN)) { + send_forward_tsn(stcb, asoc); /* * ECN Nonce: Disable Nonce Sum check when @@ -5323,10 +5326,8 @@ again: asoc->nonce_resync_tsn = asoc->advanced_peer_ack_point; } else if (lchk) { /* try to FR fwd-tsn's that get lost too */ - lchk->rec.data.fwd_tsn_cnt++; - if (lchk->rec.data.fwd_tsn_cnt > 3) { + if (lchk->rec.data.fwd_tsn_cnt >= 3) { send_forward_tsn(stcb, asoc); - lchk->rec.data.fwd_tsn_cnt = 0; } } } |