diff options
-rw-r--r-- | net/dccp/ccids/ccid2.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index f18235e8ce84..ef19fb834299 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c | |||
@@ -143,32 +143,30 @@ static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
143 | static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val) | 143 | static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val) |
144 | { | 144 | { |
145 | struct dccp_sock *dp = dccp_sk(sk); | 145 | struct dccp_sock *dp = dccp_sk(sk); |
146 | u32 max_ratio = DIV_ROUND_UP(ccid2_hc_tx_sk(sk)->ccid2hctx_cwnd, 2); | ||
147 | |||
146 | /* | 148 | /* |
147 | * XXX I don't really agree with val != 2. If cwnd is 1, ack ratio | 149 | * Ensure that Ack Ratio does not exceed ceil(cwnd/2), which is (2) from |
148 | * should be 1... it shouldn't be allowed to become 2. | 150 | * RFC 4341, 6.1.2. We ignore the statement that Ack Ratio 2 is always |
149 | * -sorbo. | 151 | * acceptable since this causes starvation/deadlock whenever cwnd < 2. |
152 | * The same problem arises when Ack Ratio is 0 (ie. Ack Ratio disabled). | ||
150 | */ | 153 | */ |
151 | if (val != 2) { | 154 | if (val == 0 || val > max_ratio) { |
152 | const struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); | 155 | DCCP_WARN("Limiting Ack Ratio (%u) to %u\n", val, max_ratio); |
153 | int max = hctx->ccid2hctx_cwnd / 2; | 156 | val = max_ratio; |
154 | |||
155 | /* round up */ | ||
156 | if (hctx->ccid2hctx_cwnd & 1) | ||
157 | max++; | ||
158 | |||
159 | if (val > max) | ||
160 | val = max; | ||
161 | } | 157 | } |
162 | if (val > 0xFFFF) /* RFC 4340, 11.3 */ | 158 | if (val > 0xFFFF) /* RFC 4340, 11.3 */ |
163 | val = 0xFFFF; | 159 | val = 0xFFFF; |
164 | 160 | ||
161 | if (val == dp->dccps_l_ack_ratio) | ||
162 | return; | ||
163 | |||
165 | ccid2_pr_debug("changing local ack ratio to %u\n", val); | 164 | ccid2_pr_debug("changing local ack ratio to %u\n", val); |
166 | dp->dccps_l_ack_ratio = val; | 165 | dp->dccps_l_ack_ratio = val; |
167 | } | 166 | } |
168 | 167 | ||
169 | static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, u32 val) | 168 | static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, u32 val) |
170 | { | 169 | { |
171 | /* XXX do we need to change ack ratio? */ | ||
172 | hctx->ccid2hctx_cwnd = val? : 1; | 170 | hctx->ccid2hctx_cwnd = val? : 1; |
173 | ccid2_pr_debug("changed cwnd to %u\n", hctx->ccid2hctx_cwnd); | 171 | ccid2_pr_debug("changed cwnd to %u\n", hctx->ccid2hctx_cwnd); |
174 | } | 172 | } |
@@ -519,9 +517,10 @@ static void ccid2_hc_tx_dec_pipe(struct sock *sk) | |||
519 | ccid2_hc_tx_kill_rto_timer(sk); | 517 | ccid2_hc_tx_kill_rto_timer(sk); |
520 | } | 518 | } |
521 | 519 | ||
522 | static void ccid2_congestion_event(struct ccid2_hc_tx_sock *hctx, | 520 | static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp) |
523 | struct ccid2_seq *seqp) | ||
524 | { | 521 | { |
522 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); | ||
523 | |||
525 | if (time_before(seqp->ccid2s_sent, hctx->ccid2hctx_last_cong)) { | 524 | if (time_before(seqp->ccid2s_sent, hctx->ccid2hctx_last_cong)) { |
526 | ccid2_pr_debug("Multiple losses in an RTT---treating as one\n"); | 525 | ccid2_pr_debug("Multiple losses in an RTT---treating as one\n"); |
527 | return; | 526 | return; |
@@ -533,6 +532,10 @@ static void ccid2_congestion_event(struct ccid2_hc_tx_sock *hctx, | |||
533 | hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd; | 532 | hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd; |
534 | if (hctx->ccid2hctx_ssthresh < 2) | 533 | if (hctx->ccid2hctx_ssthresh < 2) |
535 | hctx->ccid2hctx_ssthresh = 2; | 534 | hctx->ccid2hctx_ssthresh = 2; |
535 | |||
536 | /* Avoid spurious timeouts resulting from Ack Ratio > cwnd */ | ||
537 | if (dccp_sk(sk)->dccps_l_ack_ratio > hctx->ccid2hctx_cwnd) | ||
538 | ccid2_change_l_ack_ratio(sk, hctx->ccid2hctx_cwnd); | ||
536 | } | 539 | } |
537 | 540 | ||
538 | static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | 541 | static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) |
@@ -648,7 +651,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
648 | !seqp->ccid2s_acked) { | 651 | !seqp->ccid2s_acked) { |
649 | if (state == | 652 | if (state == |
650 | DCCP_ACKVEC_STATE_ECN_MARKED) { | 653 | DCCP_ACKVEC_STATE_ECN_MARKED) { |
651 | ccid2_congestion_event(hctx, | 654 | ccid2_congestion_event(sk, |
652 | seqp); | 655 | seqp); |
653 | } else | 656 | } else |
654 | ccid2_new_ack(sk, seqp, | 657 | ccid2_new_ack(sk, seqp, |
@@ -713,7 +716,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
713 | * order to detect multiple congestion events in | 716 | * order to detect multiple congestion events in |
714 | * one ack vector. | 717 | * one ack vector. |
715 | */ | 718 | */ |
716 | ccid2_congestion_event(hctx, seqp); | 719 | ccid2_congestion_event(sk, seqp); |
717 | ccid2_hc_tx_dec_pipe(sk); | 720 | ccid2_hc_tx_dec_pipe(sk); |
718 | } | 721 | } |
719 | if (seqp == hctx->ccid2hctx_seqt) | 722 | if (seqp == hctx->ccid2hctx_seqt) |