diff options
Diffstat (limited to 'net/dccp/ccids/ccid3.c')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 119 |
1 files changed, 65 insertions, 54 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 70ebe705eb75..cf8c07b2704f 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -121,12 +121,15 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) | |||
121 | /* | 121 | /* |
122 | * Update X by | 122 | * Update X by |
123 | * If (p > 0) | 123 | * If (p > 0) |
124 | * x_calc = calcX(s, R, p); | 124 | * X_calc = calcX(s, R, p); |
125 | * X = max(min(X_calc, 2 * X_recv), s / t_mbi); | 125 | * X = max(min(X_calc, 2 * X_recv), s / t_mbi); |
126 | * Else | 126 | * Else |
127 | * If (now - tld >= R) | 127 | * If (now - tld >= R) |
128 | * X = max(min(2 * X, 2 * X_recv), s / R); | 128 | * X = max(min(2 * X, 2 * X_recv), s / R); |
129 | * tld = now; | 129 | * tld = now; |
130 | * | ||
131 | * If X has changed, we also update the scheduled send time t_now, | ||
132 | * the inter-packet interval t_ipi, and the delta value. | ||
130 | */ | 133 | */ |
131 | static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) | 134 | static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) |
132 | 135 | ||
@@ -134,8 +137,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) | |||
134 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 137 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
135 | const __u32 old_x = hctx->ccid3hctx_x; | 138 | const __u32 old_x = hctx->ccid3hctx_x; |
136 | 139 | ||
137 | /* To avoid large error in calcX */ | 140 | if (hctx->ccid3hctx_p > 0) { |
138 | if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) { | ||
139 | hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, | 141 | hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, |
140 | hctx->ccid3hctx_rtt, | 142 | hctx->ccid3hctx_rtt, |
141 | hctx->ccid3hctx_p); | 143 | hctx->ccid3hctx_p); |
@@ -223,16 +225,14 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
223 | ccid3_tx_state_name(hctx->ccid3hctx_state)); | 225 | ccid3_tx_state_name(hctx->ccid3hctx_state)); |
224 | /* Halve sending rate */ | 226 | /* Halve sending rate */ |
225 | 227 | ||
226 | /* If (X_calc > 2 * X_recv) | 228 | /* If (p == 0 || X_calc > 2 * X_recv) |
227 | * X_recv = max(X_recv / 2, s / (2 * t_mbi)); | 229 | * X_recv = max(X_recv / 2, s / (2 * t_mbi)); |
228 | * Else | 230 | * Else |
229 | * X_recv = X_calc / 4; | 231 | * X_recv = X_calc / 4; |
230 | */ | 232 | */ |
231 | BUG_ON(hctx->ccid3hctx_p >= TFRC_SMALLEST_P && | 233 | BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc); |
232 | hctx->ccid3hctx_x_calc == 0); | ||
233 | 234 | ||
234 | /* check also if p is zero -> x_calc is infinity? */ | 235 | if (hctx->ccid3hctx_p == 0 || |
235 | if (hctx->ccid3hctx_p < TFRC_SMALLEST_P || | ||
236 | hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) | 236 | hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) |
237 | hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2, | 237 | hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2, |
238 | hctx->ccid3hctx_s / (2 * TFRC_T_MBI)); | 238 | hctx->ccid3hctx_s / (2 * TFRC_T_MBI)); |
@@ -245,9 +245,10 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
245 | } | 245 | } |
246 | /* | 246 | /* |
247 | * Schedule no feedback timer to expire in | 247 | * Schedule no feedback timer to expire in |
248 | * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) | 248 | * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) |
249 | * See comments in packet_recv() regarding the value of t_RTO. | ||
249 | */ | 250 | */ |
250 | t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); | 251 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); |
251 | break; | 252 | break; |
252 | case TFRC_SSTATE_NO_SENT: | 253 | case TFRC_SSTATE_NO_SENT: |
253 | DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); | 254 | DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); |
@@ -338,7 +339,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
338 | * else | 339 | * else |
339 | * // send the packet in (t_nom - t_now) milliseconds. | 340 | * // send the packet in (t_nom - t_now) milliseconds. |
340 | */ | 341 | */ |
341 | if (delay >= hctx->ccid3hctx_delta) | 342 | if (delay - (long)hctx->ccid3hctx_delta >= 0) |
342 | return delay / 1000L; | 343 | return delay / 1000L; |
343 | break; | 344 | break; |
344 | case TFRC_SSTATE_TERM: | 345 | case TFRC_SSTATE_TERM: |
@@ -412,10 +413,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
412 | struct dccp_tx_hist_entry *packet; | 413 | struct dccp_tx_hist_entry *packet; |
413 | struct timeval now; | 414 | struct timeval now; |
414 | unsigned long t_nfb; | 415 | unsigned long t_nfb; |
415 | u32 t_elapsed; | ||
416 | u32 pinv; | 416 | u32 pinv; |
417 | u32 x_recv; | 417 | long r_sample, t_elapsed; |
418 | u32 r_sample; | ||
419 | 418 | ||
420 | BUG_ON(hctx == NULL); | 419 | BUG_ON(hctx == NULL); |
421 | 420 | ||
@@ -426,31 +425,44 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
426 | 425 | ||
427 | opt_recv = &hctx->ccid3hctx_options_received; | 426 | opt_recv = &hctx->ccid3hctx_options_received; |
428 | 427 | ||
429 | t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10; | ||
430 | x_recv = opt_recv->ccid3or_receive_rate; | ||
431 | pinv = opt_recv->ccid3or_loss_event_rate; | ||
432 | |||
433 | switch (hctx->ccid3hctx_state) { | 428 | switch (hctx->ccid3hctx_state) { |
434 | case TFRC_SSTATE_NO_FBACK: | 429 | case TFRC_SSTATE_NO_FBACK: |
435 | case TFRC_SSTATE_FBACK: | 430 | case TFRC_SSTATE_FBACK: |
436 | /* Calculate new round trip sample by | 431 | /* get packet from history to look up t_recvdata */ |
437 | * R_sample = (now - t_recvdata) - t_delay */ | ||
438 | /* get t_recvdata from history */ | ||
439 | packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, | 432 | packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, |
440 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 433 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
441 | if (unlikely(packet == NULL)) { | 434 | if (unlikely(packet == NULL)) { |
442 | DCCP_WARN("%s, sk=%p, seqno %llu(%s) does't exist " | 435 | DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist " |
443 | "in history!\n", dccp_role(sk), sk, | 436 | "in history!\n", dccp_role(sk), sk, |
444 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, | 437 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, |
445 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); | 438 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); |
446 | return; | 439 | return; |
447 | } | 440 | } |
448 | 441 | ||
449 | /* Update RTT */ | 442 | /* Update receive rate */ |
443 | hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate; | ||
444 | |||
445 | /* Update loss event rate */ | ||
446 | pinv = opt_recv->ccid3or_loss_event_rate; | ||
447 | if (pinv == ~0U || pinv == 0) | ||
448 | hctx->ccid3hctx_p = 0; | ||
449 | else | ||
450 | hctx->ccid3hctx_p = 1000000 / pinv; | ||
451 | |||
450 | dccp_timestamp(sk, &now); | 452 | dccp_timestamp(sk, &now); |
451 | r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); | 453 | |
452 | if (unlikely(r_sample <= t_elapsed)) | 454 | /* |
453 | DCCP_WARN("r_sample=%uus,t_elapsed=%uus\n", | 455 | * Calculate new round trip sample as per [RFC 3448, 4.3] by |
456 | * R_sample = (now - t_recvdata) - t_elapsed | ||
457 | */ | ||
458 | r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); | ||
459 | t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10; | ||
460 | |||
461 | if (unlikely(r_sample <= 0)) { | ||
462 | DCCP_WARN("WARNING: R_sample (%ld) <= 0!\n", r_sample); | ||
463 | r_sample = 0; | ||
464 | } else if (unlikely(r_sample <= t_elapsed)) | ||
465 | DCCP_WARN("WARNING: r_sample=%ldus <= t_elapsed=%ldus\n", | ||
454 | r_sample, t_elapsed); | 466 | r_sample, t_elapsed); |
455 | else | 467 | else |
456 | r_sample -= t_elapsed; | 468 | r_sample -= t_elapsed; |
@@ -473,31 +485,25 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
473 | hctx->ccid3hctx_t_ld = now; | 485 | hctx->ccid3hctx_t_ld = now; |
474 | 486 | ||
475 | ccid3_update_send_time(hctx); | 487 | ccid3_update_send_time(hctx); |
476 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); | ||
477 | } else { | ||
478 | hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + | ||
479 | r_sample / 10; | ||
480 | ccid3_hc_tx_update_x(sk, &now); | ||
481 | } | ||
482 | 488 | ||
483 | ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " | 489 | ccid3_pr_debug("%s(%p), s=%u, w_init=%u, " |
484 | "r_sample=%us\n", dccp_role(sk), sk, | 490 | "R_sample=%ldus, X=%u\n", dccp_role(sk), |
485 | hctx->ccid3hctx_rtt, r_sample); | 491 | sk, hctx->ccid3hctx_s, w_init, r_sample, |
492 | hctx->ccid3hctx_x); | ||
486 | 493 | ||
487 | /* Update receive rate */ | 494 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); |
488 | hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */ | 495 | } else { |
496 | hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt + | ||
497 | (u32)r_sample ) / 10; | ||
489 | 498 | ||
490 | /* Update loss event rate */ | 499 | ccid3_hc_tx_update_x(sk, &now); |
491 | if (pinv == ~0 || pinv == 0) | ||
492 | hctx->ccid3hctx_p = 0; | ||
493 | else { | ||
494 | hctx->ccid3hctx_p = 1000000 / pinv; | ||
495 | 500 | ||
496 | if (hctx->ccid3hctx_p < TFRC_SMALLEST_P) { | 501 | ccid3_pr_debug("%s(%p), RTT=%uus (sample=%ldus), s=%u, " |
497 | hctx->ccid3hctx_p = TFRC_SMALLEST_P; | 502 | "p=%u, X_calc=%u, X=%u\n", dccp_role(sk), |
498 | ccid3_pr_debug("%s, sk=%p, Smallest p used!\n", | 503 | sk, hctx->ccid3hctx_rtt, r_sample, |
499 | dccp_role(sk), sk); | 504 | hctx->ccid3hctx_s, hctx->ccid3hctx_p, |
500 | } | 505 | hctx->ccid3hctx_x_calc, |
506 | hctx->ccid3hctx_x); | ||
501 | } | 507 | } |
502 | 508 | ||
503 | /* unschedule no feedback timer */ | 509 | /* unschedule no feedback timer */ |
@@ -512,16 +518,20 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
512 | */ | 518 | */ |
513 | sk->sk_write_space(sk); | 519 | sk->sk_write_space(sk); |
514 | 520 | ||
515 | /* Update timeout interval. We use the alternative variant of | 521 | /* |
516 | * [RFC 3448, 3.1] which sets the upper bound of t_rto to one | 522 | * Update timeout interval for the nofeedback timer. |
517 | * second, as it is suggested for TCP (see RFC 2988, 2.4). */ | 523 | * We use a configuration option to increase the lower bound. |
524 | * This can help avoid triggering the nofeedback timer too often | ||
525 | * ('spinning') on LANs with small RTTs. | ||
526 | */ | ||
518 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, | 527 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, |
519 | USEC_PER_SEC ); | 528 | CONFIG_IP_DCCP_CCID3_RTO * |
529 | (USEC_PER_SEC/1000) ); | ||
520 | /* | 530 | /* |
521 | * Schedule no feedback timer to expire in | 531 | * Schedule no feedback timer to expire in |
522 | * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) | 532 | * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) |
523 | */ | 533 | */ |
524 | t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); | 534 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); |
525 | 535 | ||
526 | ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " | 536 | ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " |
527 | "expire in %lu jiffies (%luus)\n", | 537 | "expire in %lu jiffies (%luus)\n", |
@@ -535,7 +545,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
535 | hctx->ccid3hctx_idle = 1; | 545 | hctx->ccid3hctx_idle = 1; |
536 | break; | 546 | break; |
537 | case TFRC_SSTATE_NO_SENT: | 547 | case TFRC_SSTATE_NO_SENT: |
538 | DCCP_WARN("Illegal ACK received - no packet has been sent\n"); | 548 | if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT) |
549 | DCCP_WARN("Illegal ACK received - no packet sent\n"); | ||
539 | /* fall through */ | 550 | /* fall through */ |
540 | case TFRC_SSTATE_TERM: /* ignore feedback when closing */ | 551 | case TFRC_SSTATE_TERM: /* ignore feedback when closing */ |
541 | break; | 552 | break; |