summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_indata.c
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2009-03-06 11:03:52 +0000
committerrrs <rrs@FreeBSD.org>2009-03-06 11:03:52 +0000
commit41426e5a37e0b82c42376621f11df8f9360a937f (patch)
tree6bc9cbca47c23b6c31885830b9c329da821da819 /sys/netinet/sctp_indata.c
parent28029139153edbfa691205ff8c4cc4fbc62b119f (diff)
downloadFreeBSD-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/sctp_indata.c')
-rw-r--r--sys/netinet/sctp_indata.c118
1 files changed, 69 insertions, 49 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);
OpenPOWER on IntegriCloud