diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2010-12-09 12:17:25 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-12-09 12:17:25 -0500 |
commit | d834a9dcecae834cd6b2bc5e50e1907738d9cf6a (patch) | |
tree | 0589d753465d3fe359ba451ba6cb7798df03aaa2 /net/dccp/ccids/ccid2.c | |
parent | a38c5380ef9f088be9f49b6e4c5d80af8b1b5cd4 (diff) | |
parent | f658bcfb2607bf0808966a69cf74135ce98e5c2d (diff) |
Merge branch 'x86/amd-nb' into x86/apic-cleanups
Reason: apic cleanup series depends on x86/apic, x86/amd-nb x86/platform
Conflicts:
arch/x86/include/asm/io_apic.h
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'net/dccp/ccids/ccid2.c')
-rw-r--r-- | net/dccp/ccids/ccid2.c | 310 |
1 files changed, 122 insertions, 188 deletions
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 9b3ae9922be1..6576eae9e779 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c | |||
@@ -25,59 +25,14 @@ | |||
25 | */ | 25 | */ |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include "../feat.h" | 27 | #include "../feat.h" |
28 | #include "../ccid.h" | ||
29 | #include "../dccp.h" | ||
30 | #include "ccid2.h" | 28 | #include "ccid2.h" |
31 | 29 | ||
32 | 30 | ||
33 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG | 31 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG |
34 | static int ccid2_debug; | 32 | static int ccid2_debug; |
35 | #define ccid2_pr_debug(format, a...) DCCP_PR_DEBUG(ccid2_debug, format, ##a) | 33 | #define ccid2_pr_debug(format, a...) DCCP_PR_DEBUG(ccid2_debug, format, ##a) |
36 | |||
37 | static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hc) | ||
38 | { | ||
39 | int len = 0; | ||
40 | int pipe = 0; | ||
41 | struct ccid2_seq *seqp = hc->tx_seqh; | ||
42 | |||
43 | /* there is data in the chain */ | ||
44 | if (seqp != hc->tx_seqt) { | ||
45 | seqp = seqp->ccid2s_prev; | ||
46 | len++; | ||
47 | if (!seqp->ccid2s_acked) | ||
48 | pipe++; | ||
49 | |||
50 | while (seqp != hc->tx_seqt) { | ||
51 | struct ccid2_seq *prev = seqp->ccid2s_prev; | ||
52 | |||
53 | len++; | ||
54 | if (!prev->ccid2s_acked) | ||
55 | pipe++; | ||
56 | |||
57 | /* packets are sent sequentially */ | ||
58 | BUG_ON(dccp_delta_seqno(seqp->ccid2s_seq, | ||
59 | prev->ccid2s_seq ) >= 0); | ||
60 | BUG_ON(time_before(seqp->ccid2s_sent, | ||
61 | prev->ccid2s_sent)); | ||
62 | |||
63 | seqp = prev; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | BUG_ON(pipe != hc->tx_pipe); | ||
68 | ccid2_pr_debug("len of chain=%d\n", len); | ||
69 | |||
70 | do { | ||
71 | seqp = seqp->ccid2s_prev; | ||
72 | len++; | ||
73 | } while (seqp != hc->tx_seqh); | ||
74 | |||
75 | ccid2_pr_debug("total len=%d\n", len); | ||
76 | BUG_ON(len != hc->tx_seqbufc * CCID2_SEQBUF_LEN); | ||
77 | } | ||
78 | #else | 34 | #else |
79 | #define ccid2_pr_debug(format, a...) | 35 | #define ccid2_pr_debug(format, a...) |
80 | #define ccid2_hc_tx_check_sanity(hc) | ||
81 | #endif | 36 | #endif |
82 | 37 | ||
83 | static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hc) | 38 | static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hc) |
@@ -123,12 +78,9 @@ static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hc) | |||
123 | 78 | ||
124 | static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | 79 | static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) |
125 | { | 80 | { |
126 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | 81 | if (ccid2_cwnd_network_limited(ccid2_hc_tx_sk(sk))) |
127 | 82 | return CCID_PACKET_WILL_DEQUEUE_LATER; | |
128 | if (hc->tx_pipe < hc->tx_cwnd) | 83 | return CCID_PACKET_SEND_AT_ONCE; |
129 | return 0; | ||
130 | |||
131 | return 1; /* XXX CCID should dequeue when ready instead of polling */ | ||
132 | } | 84 | } |
133 | 85 | ||
134 | static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val) | 86 | static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val) |
@@ -156,19 +108,11 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val) | |||
156 | dp->dccps_l_ack_ratio = val; | 108 | dp->dccps_l_ack_ratio = val; |
157 | } | 109 | } |
158 | 110 | ||
159 | static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hc, long val) | ||
160 | { | ||
161 | ccid2_pr_debug("change SRTT to %ld\n", val); | ||
162 | hc->tx_srtt = val; | ||
163 | } | ||
164 | |||
165 | static void ccid2_start_rto_timer(struct sock *sk); | ||
166 | |||
167 | static void ccid2_hc_tx_rto_expire(unsigned long data) | 111 | static void ccid2_hc_tx_rto_expire(unsigned long data) |
168 | { | 112 | { |
169 | struct sock *sk = (struct sock *)data; | 113 | struct sock *sk = (struct sock *)data; |
170 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | 114 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); |
171 | long s; | 115 | const bool sender_was_blocked = ccid2_cwnd_network_limited(hc); |
172 | 116 | ||
173 | bh_lock_sock(sk); | 117 | bh_lock_sock(sk); |
174 | if (sock_owned_by_user(sk)) { | 118 | if (sock_owned_by_user(sk)) { |
@@ -178,23 +122,17 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) | |||
178 | 122 | ||
179 | ccid2_pr_debug("RTO_EXPIRE\n"); | 123 | ccid2_pr_debug("RTO_EXPIRE\n"); |
180 | 124 | ||
181 | ccid2_hc_tx_check_sanity(hc); | ||
182 | |||
183 | /* back-off timer */ | 125 | /* back-off timer */ |
184 | hc->tx_rto <<= 1; | 126 | hc->tx_rto <<= 1; |
185 | 127 | if (hc->tx_rto > DCCP_RTO_MAX) | |
186 | s = hc->tx_rto / HZ; | 128 | hc->tx_rto = DCCP_RTO_MAX; |
187 | if (s > 60) | ||
188 | hc->tx_rto = 60 * HZ; | ||
189 | |||
190 | ccid2_start_rto_timer(sk); | ||
191 | 129 | ||
192 | /* adjust pipe, cwnd etc */ | 130 | /* adjust pipe, cwnd etc */ |
193 | hc->tx_ssthresh = hc->tx_cwnd / 2; | 131 | hc->tx_ssthresh = hc->tx_cwnd / 2; |
194 | if (hc->tx_ssthresh < 2) | 132 | if (hc->tx_ssthresh < 2) |
195 | hc->tx_ssthresh = 2; | 133 | hc->tx_ssthresh = 2; |
196 | hc->tx_cwnd = 1; | 134 | hc->tx_cwnd = 1; |
197 | hc->tx_pipe = 0; | 135 | hc->tx_pipe = 0; |
198 | 136 | ||
199 | /* clear state about stuff we sent */ | 137 | /* clear state about stuff we sent */ |
200 | hc->tx_seqt = hc->tx_seqh; | 138 | hc->tx_seqt = hc->tx_seqh; |
@@ -204,23 +142,18 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) | |||
204 | hc->tx_rpseq = 0; | 142 | hc->tx_rpseq = 0; |
205 | hc->tx_rpdupack = -1; | 143 | hc->tx_rpdupack = -1; |
206 | ccid2_change_l_ack_ratio(sk, 1); | 144 | ccid2_change_l_ack_ratio(sk, 1); |
207 | ccid2_hc_tx_check_sanity(hc); | 145 | |
146 | /* if we were blocked before, we may now send cwnd=1 packet */ | ||
147 | if (sender_was_blocked) | ||
148 | tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); | ||
149 | /* restart backed-off timer */ | ||
150 | sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); | ||
208 | out: | 151 | out: |
209 | bh_unlock_sock(sk); | 152 | bh_unlock_sock(sk); |
210 | sock_put(sk); | 153 | sock_put(sk); |
211 | } | 154 | } |
212 | 155 | ||
213 | static void ccid2_start_rto_timer(struct sock *sk) | 156 | static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len) |
214 | { | ||
215 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | ||
216 | |||
217 | ccid2_pr_debug("setting RTO timeout=%ld\n", hc->tx_rto); | ||
218 | |||
219 | BUG_ON(timer_pending(&hc->tx_rtotimer)); | ||
220 | sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); | ||
221 | } | ||
222 | |||
223 | static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) | ||
224 | { | 157 | { |
225 | struct dccp_sock *dp = dccp_sk(sk); | 158 | struct dccp_sock *dp = dccp_sk(sk); |
226 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | 159 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); |
@@ -230,7 +163,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) | |||
230 | 163 | ||
231 | hc->tx_seqh->ccid2s_seq = dp->dccps_gss; | 164 | hc->tx_seqh->ccid2s_seq = dp->dccps_gss; |
232 | hc->tx_seqh->ccid2s_acked = 0; | 165 | hc->tx_seqh->ccid2s_acked = 0; |
233 | hc->tx_seqh->ccid2s_sent = jiffies; | 166 | hc->tx_seqh->ccid2s_sent = ccid2_time_stamp; |
234 | 167 | ||
235 | next = hc->tx_seqh->ccid2s_next; | 168 | next = hc->tx_seqh->ccid2s_next; |
236 | /* check if we need to alloc more space */ | 169 | /* check if we need to alloc more space */ |
@@ -296,23 +229,20 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) | |||
296 | } | 229 | } |
297 | #endif | 230 | #endif |
298 | 231 | ||
299 | /* setup RTO timer */ | 232 | sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); |
300 | if (!timer_pending(&hc->tx_rtotimer)) | ||
301 | ccid2_start_rto_timer(sk); | ||
302 | 233 | ||
303 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG | 234 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG |
304 | do { | 235 | do { |
305 | struct ccid2_seq *seqp = hc->tx_seqt; | 236 | struct ccid2_seq *seqp = hc->tx_seqt; |
306 | 237 | ||
307 | while (seqp != hc->tx_seqh) { | 238 | while (seqp != hc->tx_seqh) { |
308 | ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n", | 239 | ccid2_pr_debug("out seq=%llu acked=%d time=%u\n", |
309 | (unsigned long long)seqp->ccid2s_seq, | 240 | (unsigned long long)seqp->ccid2s_seq, |
310 | seqp->ccid2s_acked, seqp->ccid2s_sent); | 241 | seqp->ccid2s_acked, seqp->ccid2s_sent); |
311 | seqp = seqp->ccid2s_next; | 242 | seqp = seqp->ccid2s_next; |
312 | } | 243 | } |
313 | } while (0); | 244 | } while (0); |
314 | ccid2_pr_debug("=========\n"); | 245 | ccid2_pr_debug("=========\n"); |
315 | ccid2_hc_tx_check_sanity(hc); | ||
316 | #endif | 246 | #endif |
317 | } | 247 | } |
318 | 248 | ||
@@ -378,17 +308,87 @@ out_invalid_option: | |||
378 | return -1; | 308 | return -1; |
379 | } | 309 | } |
380 | 310 | ||
381 | static void ccid2_hc_tx_kill_rto_timer(struct sock *sk) | 311 | /** |
312 | * ccid2_rtt_estimator - Sample RTT and compute RTO using RFC2988 algorithm | ||
313 | * This code is almost identical with TCP's tcp_rtt_estimator(), since | ||
314 | * - it has a higher sampling frequency (recommended by RFC 1323), | ||
315 | * - the RTO does not collapse into RTT due to RTTVAR going towards zero, | ||
316 | * - it is simple (cf. more complex proposals such as Eifel timer or research | ||
317 | * which suggests that the gain should be set according to window size), | ||
318 | * - in tests it was found to work well with CCID2 [gerrit]. | ||
319 | */ | ||
320 | static void ccid2_rtt_estimator(struct sock *sk, const long mrtt) | ||
382 | { | 321 | { |
383 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | 322 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); |
323 | long m = mrtt ? : 1; | ||
384 | 324 | ||
385 | sk_stop_timer(sk, &hc->tx_rtotimer); | 325 | if (hc->tx_srtt == 0) { |
386 | ccid2_pr_debug("deleted RTO timer\n"); | 326 | /* First measurement m */ |
327 | hc->tx_srtt = m << 3; | ||
328 | hc->tx_mdev = m << 1; | ||
329 | |||
330 | hc->tx_mdev_max = max(hc->tx_mdev, tcp_rto_min(sk)); | ||
331 | hc->tx_rttvar = hc->tx_mdev_max; | ||
332 | |||
333 | hc->tx_rtt_seq = dccp_sk(sk)->dccps_gss; | ||
334 | } else { | ||
335 | /* Update scaled SRTT as SRTT += 1/8 * (m - SRTT) */ | ||
336 | m -= (hc->tx_srtt >> 3); | ||
337 | hc->tx_srtt += m; | ||
338 | |||
339 | /* Similarly, update scaled mdev with regard to |m| */ | ||
340 | if (m < 0) { | ||
341 | m = -m; | ||
342 | m -= (hc->tx_mdev >> 2); | ||
343 | /* | ||
344 | * This neutralises RTO increase when RTT < SRTT - mdev | ||
345 | * (see P. Sarolahti, A. Kuznetsov,"Congestion Control | ||
346 | * in Linux TCP", USENIX 2002, pp. 49-62). | ||
347 | */ | ||
348 | if (m > 0) | ||
349 | m >>= 3; | ||
350 | } else { | ||
351 | m -= (hc->tx_mdev >> 2); | ||
352 | } | ||
353 | hc->tx_mdev += m; | ||
354 | |||
355 | if (hc->tx_mdev > hc->tx_mdev_max) { | ||
356 | hc->tx_mdev_max = hc->tx_mdev; | ||
357 | if (hc->tx_mdev_max > hc->tx_rttvar) | ||
358 | hc->tx_rttvar = hc->tx_mdev_max; | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * Decay RTTVAR at most once per flight, exploiting that | ||
363 | * 1) pipe <= cwnd <= Sequence_Window = W (RFC 4340, 7.5.2) | ||
364 | * 2) AWL = GSS-W+1 <= GAR <= GSS (RFC 4340, 7.5.1) | ||
365 | * GAR is a useful bound for FlightSize = pipe. | ||
366 | * AWL is probably too low here, as it over-estimates pipe. | ||
367 | */ | ||
368 | if (after48(dccp_sk(sk)->dccps_gar, hc->tx_rtt_seq)) { | ||
369 | if (hc->tx_mdev_max < hc->tx_rttvar) | ||
370 | hc->tx_rttvar -= (hc->tx_rttvar - | ||
371 | hc->tx_mdev_max) >> 2; | ||
372 | hc->tx_rtt_seq = dccp_sk(sk)->dccps_gss; | ||
373 | hc->tx_mdev_max = tcp_rto_min(sk); | ||
374 | } | ||
375 | } | ||
376 | |||
377 | /* | ||
378 | * Set RTO from SRTT and RTTVAR | ||
379 | * As in TCP, 4 * RTTVAR >= TCP_RTO_MIN, giving a minimum RTO of 200 ms. | ||
380 | * This agrees with RFC 4341, 5: | ||
381 | * "Because DCCP does not retransmit data, DCCP does not require | ||
382 | * TCP's recommended minimum timeout of one second". | ||
383 | */ | ||
384 | hc->tx_rto = (hc->tx_srtt >> 3) + hc->tx_rttvar; | ||
385 | |||
386 | if (hc->tx_rto > DCCP_RTO_MAX) | ||
387 | hc->tx_rto = DCCP_RTO_MAX; | ||
387 | } | 388 | } |
388 | 389 | ||
389 | static inline void ccid2_new_ack(struct sock *sk, | 390 | static void ccid2_new_ack(struct sock *sk, struct ccid2_seq *seqp, |
390 | struct ccid2_seq *seqp, | 391 | unsigned int *maxincr) |
391 | unsigned int *maxincr) | ||
392 | { | 392 | { |
393 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | 393 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); |
394 | 394 | ||
@@ -402,93 +402,27 @@ static inline void ccid2_new_ack(struct sock *sk, | |||
402 | hc->tx_cwnd += 1; | 402 | hc->tx_cwnd += 1; |
403 | hc->tx_packets_acked = 0; | 403 | hc->tx_packets_acked = 0; |
404 | } | 404 | } |
405 | 405 | /* | |
406 | /* update RTO */ | 406 | * FIXME: RTT is sampled several times per acknowledgment (for each |
407 | if (hc->tx_srtt == -1 || | 407 | * entry in the Ack Vector), instead of once per Ack (as in TCP SACK). |
408 | time_after(jiffies, hc->tx_lastrtt + hc->tx_srtt)) { | 408 | * This causes the RTT to be over-estimated, since the older entries |
409 | unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent; | 409 | * in the Ack Vector have earlier sending times. |
410 | int s; | 410 | * The cleanest solution is to not use the ccid2s_sent field at all |
411 | 411 | * and instead use DCCP timestamps: requires changes in other places. | |
412 | /* first measurement */ | 412 | */ |
413 | if (hc->tx_srtt == -1) { | 413 | ccid2_rtt_estimator(sk, ccid2_time_stamp - seqp->ccid2s_sent); |
414 | ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", | ||
415 | r, jiffies, | ||
416 | (unsigned long long)seqp->ccid2s_seq); | ||
417 | ccid2_change_srtt(hc, r); | ||
418 | hc->tx_rttvar = r >> 1; | ||
419 | } else { | ||
420 | /* RTTVAR */ | ||
421 | long tmp = hc->tx_srtt - r; | ||
422 | long srtt; | ||
423 | |||
424 | if (tmp < 0) | ||
425 | tmp *= -1; | ||
426 | |||
427 | tmp >>= 2; | ||
428 | hc->tx_rttvar *= 3; | ||
429 | hc->tx_rttvar >>= 2; | ||
430 | hc->tx_rttvar += tmp; | ||
431 | |||
432 | /* SRTT */ | ||
433 | srtt = hc->tx_srtt; | ||
434 | srtt *= 7; | ||
435 | srtt >>= 3; | ||
436 | tmp = r >> 3; | ||
437 | srtt += tmp; | ||
438 | ccid2_change_srtt(hc, srtt); | ||
439 | } | ||
440 | s = hc->tx_rttvar << 2; | ||
441 | /* clock granularity is 1 when based on jiffies */ | ||
442 | if (!s) | ||
443 | s = 1; | ||
444 | hc->tx_rto = hc->tx_srtt + s; | ||
445 | |||
446 | /* must be at least a second */ | ||
447 | s = hc->tx_rto / HZ; | ||
448 | /* DCCP doesn't require this [but I like it cuz my code sux] */ | ||
449 | #if 1 | ||
450 | if (s < 1) | ||
451 | hc->tx_rto = HZ; | ||
452 | #endif | ||
453 | /* max 60 seconds */ | ||
454 | if (s > 60) | ||
455 | hc->tx_rto = HZ * 60; | ||
456 | |||
457 | hc->tx_lastrtt = jiffies; | ||
458 | |||
459 | ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n", | ||
460 | hc->tx_srtt, hc->tx_rttvar, | ||
461 | hc->tx_rto, HZ, r); | ||
462 | } | ||
463 | |||
464 | /* we got a new ack, so re-start RTO timer */ | ||
465 | ccid2_hc_tx_kill_rto_timer(sk); | ||
466 | ccid2_start_rto_timer(sk); | ||
467 | } | ||
468 | |||
469 | static void ccid2_hc_tx_dec_pipe(struct sock *sk) | ||
470 | { | ||
471 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | ||
472 | |||
473 | if (hc->tx_pipe == 0) | ||
474 | DCCP_BUG("pipe == 0"); | ||
475 | else | ||
476 | hc->tx_pipe--; | ||
477 | |||
478 | if (hc->tx_pipe == 0) | ||
479 | ccid2_hc_tx_kill_rto_timer(sk); | ||
480 | } | 414 | } |
481 | 415 | ||
482 | static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp) | 416 | static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp) |
483 | { | 417 | { |
484 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | 418 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); |
485 | 419 | ||
486 | if (time_before(seqp->ccid2s_sent, hc->tx_last_cong)) { | 420 | if ((s32)(seqp->ccid2s_sent - hc->tx_last_cong) < 0) { |
487 | ccid2_pr_debug("Multiple losses in an RTT---treating as one\n"); | 421 | ccid2_pr_debug("Multiple losses in an RTT---treating as one\n"); |
488 | return; | 422 | return; |
489 | } | 423 | } |
490 | 424 | ||
491 | hc->tx_last_cong = jiffies; | 425 | hc->tx_last_cong = ccid2_time_stamp; |
492 | 426 | ||
493 | hc->tx_cwnd = hc->tx_cwnd / 2 ? : 1U; | 427 | hc->tx_cwnd = hc->tx_cwnd / 2 ? : 1U; |
494 | hc->tx_ssthresh = max(hc->tx_cwnd, 2U); | 428 | hc->tx_ssthresh = max(hc->tx_cwnd, 2U); |
@@ -502,6 +436,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
502 | { | 436 | { |
503 | struct dccp_sock *dp = dccp_sk(sk); | 437 | struct dccp_sock *dp = dccp_sk(sk); |
504 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | 438 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); |
439 | const bool sender_was_blocked = ccid2_cwnd_network_limited(hc); | ||
505 | u64 ackno, seqno; | 440 | u64 ackno, seqno; |
506 | struct ccid2_seq *seqp; | 441 | struct ccid2_seq *seqp; |
507 | unsigned char *vector; | 442 | unsigned char *vector; |
@@ -510,7 +445,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
510 | int done = 0; | 445 | int done = 0; |
511 | unsigned int maxincr = 0; | 446 | unsigned int maxincr = 0; |
512 | 447 | ||
513 | ccid2_hc_tx_check_sanity(hc); | ||
514 | /* check reverse path congestion */ | 448 | /* check reverse path congestion */ |
515 | seqno = DCCP_SKB_CB(skb)->dccpd_seq; | 449 | seqno = DCCP_SKB_CB(skb)->dccpd_seq; |
516 | 450 | ||
@@ -620,7 +554,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
620 | seqp->ccid2s_acked = 1; | 554 | seqp->ccid2s_acked = 1; |
621 | ccid2_pr_debug("Got ack for %llu\n", | 555 | ccid2_pr_debug("Got ack for %llu\n", |
622 | (unsigned long long)seqp->ccid2s_seq); | 556 | (unsigned long long)seqp->ccid2s_seq); |
623 | ccid2_hc_tx_dec_pipe(sk); | 557 | hc->tx_pipe--; |
624 | } | 558 | } |
625 | if (seqp == hc->tx_seqt) { | 559 | if (seqp == hc->tx_seqt) { |
626 | done = 1; | 560 | done = 1; |
@@ -677,7 +611,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
677 | * one ack vector. | 611 | * one ack vector. |
678 | */ | 612 | */ |
679 | ccid2_congestion_event(sk, seqp); | 613 | ccid2_congestion_event(sk, seqp); |
680 | ccid2_hc_tx_dec_pipe(sk); | 614 | hc->tx_pipe--; |
681 | } | 615 | } |
682 | if (seqp == hc->tx_seqt) | 616 | if (seqp == hc->tx_seqt) |
683 | break; | 617 | break; |
@@ -695,7 +629,15 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
695 | hc->tx_seqt = hc->tx_seqt->ccid2s_next; | 629 | hc->tx_seqt = hc->tx_seqt->ccid2s_next; |
696 | } | 630 | } |
697 | 631 | ||
698 | ccid2_hc_tx_check_sanity(hc); | 632 | /* restart RTO timer if not all outstanding data has been acked */ |
633 | if (hc->tx_pipe == 0) | ||
634 | sk_stop_timer(sk, &hc->tx_rtotimer); | ||
635 | else | ||
636 | sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); | ||
637 | |||
638 | /* check if incoming Acks allow pending packets to be sent */ | ||
639 | if (sender_was_blocked && !ccid2_cwnd_network_limited(hc)) | ||
640 | tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); | ||
699 | } | 641 | } |
700 | 642 | ||
701 | static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | 643 | static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) |
@@ -707,12 +649,8 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | |||
707 | /* RFC 4341, 5: initialise ssthresh to arbitrarily high (max) value */ | 649 | /* RFC 4341, 5: initialise ssthresh to arbitrarily high (max) value */ |
708 | hc->tx_ssthresh = ~0U; | 650 | hc->tx_ssthresh = ~0U; |
709 | 651 | ||
710 | /* | 652 | /* Use larger initial windows (RFC 4341, section 5). */ |
711 | * RFC 4341, 5: "The cwnd parameter is initialized to at most four | 653 | hc->tx_cwnd = rfc3390_bytes_to_packets(dp->dccps_mss_cache); |
712 | * packets for new connections, following the rules from [RFC3390]". | ||
713 | * We need to convert the bytes of RFC3390 into the packets of RFC 4341. | ||
714 | */ | ||
715 | hc->tx_cwnd = clamp(4380U / dp->dccps_mss_cache, 2U, 4U); | ||
716 | 654 | ||
717 | /* Make sure that Ack Ratio is enabled and within bounds. */ | 655 | /* Make sure that Ack Ratio is enabled and within bounds. */ |
718 | max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2); | 656 | max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2); |
@@ -723,15 +661,11 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | |||
723 | if (ccid2_hc_tx_alloc_seq(hc)) | 661 | if (ccid2_hc_tx_alloc_seq(hc)) |
724 | return -ENOMEM; | 662 | return -ENOMEM; |
725 | 663 | ||
726 | hc->tx_rto = 3 * HZ; | 664 | hc->tx_rto = DCCP_TIMEOUT_INIT; |
727 | ccid2_change_srtt(hc, -1); | ||
728 | hc->tx_rttvar = -1; | ||
729 | hc->tx_rpdupack = -1; | 665 | hc->tx_rpdupack = -1; |
730 | hc->tx_last_cong = jiffies; | 666 | hc->tx_last_cong = ccid2_time_stamp; |
731 | setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, | 667 | setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, |
732 | (unsigned long)sk); | 668 | (unsigned long)sk); |
733 | |||
734 | ccid2_hc_tx_check_sanity(hc); | ||
735 | return 0; | 669 | return 0; |
736 | } | 670 | } |
737 | 671 | ||
@@ -740,7 +674,7 @@ static void ccid2_hc_tx_exit(struct sock *sk) | |||
740 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | 674 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); |
741 | int i; | 675 | int i; |
742 | 676 | ||
743 | ccid2_hc_tx_kill_rto_timer(sk); | 677 | sk_stop_timer(sk, &hc->tx_rtotimer); |
744 | 678 | ||
745 | for (i = 0; i < hc->tx_seqbufc; i++) | 679 | for (i = 0; i < hc->tx_seqbufc; i++) |
746 | kfree(hc->tx_seqbuf[i]); | 680 | kfree(hc->tx_seqbuf[i]); |