summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_indata.c
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2010-07-29 11:37:04 +0000
committerrrs <rrs@FreeBSD.org>2010-07-29 11:37:04 +0000
commitc9a735e2e795174cacdb32cf78185bc3c8fde78c (patch)
tree03cffd00fe5726c24c8cca36c9801d3dc3ff5732 /sys/netinet/sctp_indata.c
parenta871a4e0159f3433c4ca560a62d1e6fbd89b4477 (diff)
downloadFreeBSD-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.c31
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;
}
}
}
OpenPOWER on IntegriCloud