diff options
author | rrs <rrs@FreeBSD.org> | 2009-03-06 11:03:52 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2009-03-06 11:03:52 +0000 |
commit | 41426e5a37e0b82c42376621f11df8f9360a937f (patch) | |
tree | 6bc9cbca47c23b6c31885830b9c329da821da819 /sys/netinet | |
parent | 28029139153edbfa691205ff8c4cc4fbc62b119f (diff) | |
download | FreeBSD-src-41426e5a37e0b82c42376621f11df8f9360a937f.zip FreeBSD-src-41426e5a37e0b82c42376621f11df8f9360a937f.tar.gz |
Fixes for window probes:
1) WP should never be marked unless flight size is 0
2) When recovering from wp if the peer ack's it we don't mark for retran
3) When recovering, we must assure a timer is still running.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/sctp_indata.c | 118 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 2 |
2 files changed, 70 insertions, 50 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 655ce83..f9fd08f 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -4179,13 +4179,8 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb, struct sctp_nets *net, struct sctp_tmit_chunk *tp1) { - struct sctp_tmit_chunk *chk; - - /* First setup this one and get it moved back */ - sctp_flight_size_decrease(tp1); - sctp_total_flight_decrease(stcb, tp1); tp1->window_probe = 0; - if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) || (tp1->data == NULL)) { + if ((tp1->sent >= SCTP_DATAGRAM_ACKED) || (tp1->data == NULL)) { /* TSN's skipped we do NOT move back. */ sctp_misc_ints(SCTP_FLIGHT_LOG_DWN_WP_FWD, tp1->whoTo->flight_size, @@ -4194,7 +4189,12 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb, tp1->rec.data.TSN_seq); return; } - tp1->sent = SCTP_DATAGRAM_UNSENT; + /* First setup this by shrinking flight */ + sctp_flight_size_decrease(tp1); + sctp_total_flight_decrease(stcb, tp1); + /* Now mark for resend */ + tp1->sent = SCTP_DATAGRAM_RESEND; + asoc->sent_queue_retran_cnt++; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_WP, tp1->whoTo->flight_size, @@ -4202,26 +4202,6 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb, (uintptr_t) tp1->whoTo, tp1->rec.data.TSN_seq); } - TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); - TAILQ_INSERT_HEAD(&asoc->send_queue, tp1, sctp_next); - asoc->sent_queue_cnt--; - asoc->send_queue_cnt++; - /* - * Now all guys marked for RESEND on the sent_queue must be moved - * back too. - */ - TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { - if (chk->sent == SCTP_DATAGRAM_RESEND) { - /* Another chunk to move */ - chk->sent = SCTP_DATAGRAM_UNSENT; - /* It should not be in flight */ - TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); - TAILQ_INSERT_AFTER(&asoc->send_queue, tp1, chk, sctp_next); - asoc->sent_queue_cnt--; - asoc->send_queue_cnt++; - sctp_ucount_decr(asoc->sent_queue_retran_cnt); - } - } } void @@ -4552,8 +4532,9 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, again: j = 0; TAILQ_FOREACH(net, &asoc->nets, sctp_next) { + int to_ticks; + if (win_probe_recovery && (net->window_probe)) { - net->window_probe = 0; win_probe_recovered = 1; /* * Find first chunk that was used with window probe @@ -4562,25 +4543,35 @@ again: /* sa_ignore FREED_MEMORY */ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { if (tp1->window_probe) { - /* move back to data send queue */ sctp_window_probe_recovery(stcb, asoc, net, tp1); break; } } } + if (net->RTO == 0) { + to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); + } else { + to_ticks = MSEC_TO_TICKS(net->RTO); + } if (net->flight_size) { - int to_ticks; - - if (net->RTO == 0) { - to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); - } else { - to_ticks = MSEC_TO_TICKS(net->RTO); - } j++; (void)SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, sctp_timeout_handler, &net->rxt_timer); + if (net->window_probe) { + net->window_probe = 0; + } } else { - if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { + if (net->window_probe) { + /* + * In window probes we must assure a timer + * is still running there + */ + net->window_probe = 0; + if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { + SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, + sctp_timeout_handler, &net->rxt_timer); + } + } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); @@ -5563,7 +5554,6 @@ again: j = 0; TAILQ_FOREACH(net, &asoc->nets, sctp_next) { if (win_probe_recovery && (net->window_probe)) { - net->window_probe = 0; win_probe_recovered = 1; /*- * Find first chunk that was used with @@ -5582,8 +5572,21 @@ again: j++; sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); + if (net->window_probe) { + } } else { - if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { + if (net->window_probe) { + /* + * In window probes we must assure a timer + * is still running there + */ + + if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { + sctp_timer_start(SCTP_TIMER_TYPE_SEND, + stcb->sctp_ep, stcb, net); + + } + } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); @@ -6553,8 +6556,9 @@ sctp_express_handle_nr_sack(struct sctp_tcb *stcb, uint32_t cumack, again: j = 0; TAILQ_FOREACH(net, &asoc->nets, sctp_next) { + int to_ticks; + if (win_probe_recovery && (net->window_probe)) { - net->window_probe = 0; win_probe_recovered = 1; /* * Find first chunk that was used with window probe @@ -6569,19 +6573,29 @@ again: } } } + if (net->RTO == 0) { + to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); + } else { + to_ticks = MSEC_TO_TICKS(net->RTO); + } if (net->flight_size) { - int to_ticks; - if (net->RTO == 0) { - to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); - } else { - to_ticks = MSEC_TO_TICKS(net->RTO); - } j++; (void)SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, sctp_timeout_handler, &net->rxt_timer); + if (net->window_probe) { + net->window_probe = 0; + } } else { - if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { + if (net->window_probe) { + /* + * In window probes we must assure a timer + * is still running there + */ + net->window_probe = 0; + (void)SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, + sctp_timeout_handler, &net->rxt_timer); + } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); @@ -8111,7 +8125,6 @@ again: j = 0; TAILQ_FOREACH(net, &asoc->nets, sctp_next) { if (win_probe_recovery && (net->window_probe)) { - net->window_probe = 0; win_probe_recovered = 1; /*- * Find first chunk that was used with @@ -8130,8 +8143,15 @@ again: j++; sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); + if (net->window_probe) { + net->window_probe = 0; + } } else { - if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { + if (net->window_probe) { + net->window_probe = 0; + sctp_timer_start(SCTP_TIMER_TYPE_SEND, + stcb->sctp_ep, stcb, net); + } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 00e178b..3729616 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -10036,7 +10036,7 @@ again_one_more_time: SCTP_STAT_INCR_COUNTER64(sctps_fragusrmsgs); } if ((mtu == 0) || (r_mtu == 0) || (one_chunk)) { - if (one_chunk) { + if ((one_chunk) && (stcb->asoc.total_flight == 0)) { data_list[0]->window_probe = 1; net->window_probe = 1; } |