diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 173 |
1 files changed, 84 insertions, 89 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index e31560daa0b9..a93a556ad03d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -402,112 +402,107 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
402 | if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || | 402 | if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || |
403 | DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK)) | 403 | DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK)) |
404 | return; | 404 | return; |
405 | /* ... and only in the established state */ | ||
406 | if (hctx->ccid3hctx_state != TFRC_SSTATE_FBACK && | ||
407 | hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK) | ||
408 | return; | ||
405 | 409 | ||
406 | opt_recv = &hctx->ccid3hctx_options_received; | 410 | opt_recv = &hctx->ccid3hctx_options_received; |
411 | now = ktime_get_real(); | ||
407 | 412 | ||
408 | switch (hctx->ccid3hctx_state) { | 413 | /* Estimate RTT from history if ACK number is valid */ |
409 | case TFRC_SSTATE_NO_FBACK: | 414 | r_sample = tfrc_tx_hist_rtt(hctx->ccid3hctx_hist, |
410 | case TFRC_SSTATE_FBACK: | 415 | DCCP_SKB_CB(skb)->dccpd_ack_seq, now); |
411 | now = ktime_get_real(); | 416 | if (r_sample == 0) { |
412 | 417 | DCCP_WARN("%s(%p): %s with bogus ACK-%llu\n", dccp_role(sk), sk, | |
413 | /* estimate RTT from history if ACK number is valid */ | 418 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type), |
414 | r_sample = tfrc_tx_hist_rtt(hctx->ccid3hctx_hist, | 419 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq); |
415 | DCCP_SKB_CB(skb)->dccpd_ack_seq, now); | 420 | return; |
416 | if (r_sample == 0) { | 421 | } |
417 | DCCP_WARN("%s(%p): %s with bogus ACK-%llu\n", dccp_role(sk), sk, | 422 | |
418 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type), | 423 | /* Update receive rate in units of 64 * bytes/second */ |
419 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq); | 424 | hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate; |
420 | return; | 425 | hctx->ccid3hctx_x_recv <<= 6; |
421 | } | ||
422 | 426 | ||
423 | /* Update receive rate in units of 64 * bytes/second */ | 427 | /* Update loss event rate (which is scaled by 1e6) */ |
424 | hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate; | 428 | pinv = opt_recv->ccid3or_loss_event_rate; |
425 | hctx->ccid3hctx_x_recv <<= 6; | 429 | if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */ |
430 | hctx->ccid3hctx_p = 0; | ||
431 | else /* can not exceed 100% */ | ||
432 | hctx->ccid3hctx_p = 1000000 / pinv; | ||
433 | /* | ||
434 | * Validate new RTT sample and update moving average | ||
435 | */ | ||
436 | r_sample = dccp_sample_rtt(sk, r_sample); | ||
437 | hctx->ccid3hctx_rtt = tfrc_ewma(hctx->ccid3hctx_rtt, r_sample, 9); | ||
426 | 438 | ||
427 | /* Update loss event rate */ | 439 | if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { |
428 | pinv = opt_recv->ccid3or_loss_event_rate; | ||
429 | if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */ | ||
430 | hctx->ccid3hctx_p = 0; | ||
431 | else /* can not exceed 100% */ | ||
432 | hctx->ccid3hctx_p = 1000000 / pinv; | ||
433 | /* | 440 | /* |
434 | * Validate new RTT sample and update moving average | 441 | * Larger Initial Windows [RFC 4342, sec. 5] |
435 | */ | 442 | */ |
436 | r_sample = dccp_sample_rtt(sk, r_sample); | 443 | hctx->ccid3hctx_x = rfc3390_initial_rate(sk); |
437 | hctx->ccid3hctx_rtt = tfrc_ewma(hctx->ccid3hctx_rtt, r_sample, 9); | 444 | hctx->ccid3hctx_t_ld = now; |
438 | 445 | ||
439 | if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { | 446 | ccid3_update_send_interval(hctx); |
440 | /* | ||
441 | * Larger Initial Windows [RFC 4342, sec. 5] | ||
442 | */ | ||
443 | hctx->ccid3hctx_x = rfc3390_initial_rate(sk); | ||
444 | hctx->ccid3hctx_t_ld = now; | ||
445 | 447 | ||
446 | ccid3_update_send_interval(hctx); | 448 | ccid3_pr_debug("%s(%p), s=%u, MSS=%u, " |
449 | "R_sample=%uus, X=%u\n", dccp_role(sk), | ||
450 | sk, hctx->ccid3hctx_s, | ||
451 | dccp_sk(sk)->dccps_mss_cache, r_sample, | ||
452 | (unsigned)(hctx->ccid3hctx_x >> 6)); | ||
447 | 453 | ||
448 | ccid3_pr_debug("%s(%p), s=%u, MSS=%u, " | 454 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); |
449 | "R_sample=%uus, X=%u\n", dccp_role(sk), | 455 | } else { |
450 | sk, hctx->ccid3hctx_s, | ||
451 | dccp_sk(sk)->dccps_mss_cache, r_sample, | ||
452 | (unsigned)(hctx->ccid3hctx_x >> 6)); | ||
453 | 456 | ||
454 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); | 457 | /* Update sending rate (step 4 of [RFC 3448, 4.3]) */ |
455 | } else { | 458 | if (hctx->ccid3hctx_p > 0) |
459 | hctx->ccid3hctx_x_calc = | ||
460 | tfrc_calc_x(hctx->ccid3hctx_s, | ||
461 | hctx->ccid3hctx_rtt, | ||
462 | hctx->ccid3hctx_p); | ||
463 | ccid3_hc_tx_update_x(sk, &now); | ||
456 | 464 | ||
457 | /* Update sending rate (step 4 of [RFC 3448, 4.3]) */ | 465 | ccid3_pr_debug("%s(%p), RTT=%uus (sample=%uus), s=%u, " |
458 | if (hctx->ccid3hctx_p > 0) | 466 | "p=%u, X_calc=%u, X_recv=%u, X=%u\n", |
459 | hctx->ccid3hctx_x_calc = | 467 | dccp_role(sk), |
460 | tfrc_calc_x(hctx->ccid3hctx_s, | 468 | sk, hctx->ccid3hctx_rtt, r_sample, |
461 | hctx->ccid3hctx_rtt, | 469 | hctx->ccid3hctx_s, hctx->ccid3hctx_p, |
462 | hctx->ccid3hctx_p); | 470 | hctx->ccid3hctx_x_calc, |
463 | ccid3_hc_tx_update_x(sk, &now); | 471 | (unsigned)(hctx->ccid3hctx_x_recv >> 6), |
464 | 472 | (unsigned)(hctx->ccid3hctx_x >> 6)); | |
465 | ccid3_pr_debug("%s(%p), RTT=%uus (sample=%uus), s=%u, " | 473 | } |
466 | "p=%u, X_calc=%u, X_recv=%u, X=%u\n", | ||
467 | dccp_role(sk), | ||
468 | sk, hctx->ccid3hctx_rtt, r_sample, | ||
469 | hctx->ccid3hctx_s, hctx->ccid3hctx_p, | ||
470 | hctx->ccid3hctx_x_calc, | ||
471 | (unsigned)(hctx->ccid3hctx_x_recv >> 6), | ||
472 | (unsigned)(hctx->ccid3hctx_x >> 6)); | ||
473 | } | ||
474 | 474 | ||
475 | /* unschedule no feedback timer */ | 475 | /* unschedule no feedback timer */ |
476 | sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); | 476 | sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); |
477 | 477 | ||
478 | /* | 478 | /* |
479 | * As we have calculated new ipi, delta, t_nom it is possible | 479 | * As we have calculated new ipi, delta, t_nom it is possible |
480 | * that we now can send a packet, so wake up dccp_wait_for_ccid | 480 | * that we now can send a packet, so wake up dccp_wait_for_ccid |
481 | */ | 481 | */ |
482 | sk->sk_write_space(sk); | 482 | sk->sk_write_space(sk); |
483 | 483 | ||
484 | /* | 484 | /* |
485 | * Update timeout interval for the nofeedback timer. | 485 | * Update timeout interval for the nofeedback timer. |
486 | * We use a configuration option to increase the lower bound. | 486 | * We use a configuration option to increase the lower bound. |
487 | * This can help avoid triggering the nofeedback timer too | 487 | * This can help avoid triggering the nofeedback timer too |
488 | * often ('spinning') on LANs with small RTTs. | 488 | * often ('spinning') on LANs with small RTTs. |
489 | */ | 489 | */ |
490 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, | 490 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, |
491 | CONFIG_IP_DCCP_CCID3_RTO * | 491 | (CONFIG_IP_DCCP_CCID3_RTO * |
492 | (USEC_PER_SEC/1000)); | 492 | (USEC_PER_SEC / 1000))); |
493 | /* | 493 | /* |
494 | * Schedule no feedback timer to expire in | 494 | * Schedule no feedback timer to expire in |
495 | * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) | 495 | * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) |
496 | */ | 496 | */ |
497 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); | 497 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); |
498 | 498 | ||
499 | ccid3_pr_debug("%s(%p), Scheduled no feedback timer to " | 499 | ccid3_pr_debug("%s(%p), Scheduled no feedback timer to " |
500 | "expire in %lu jiffies (%luus)\n", | 500 | "expire in %lu jiffies (%luus)\n", |
501 | dccp_role(sk), | 501 | dccp_role(sk), |
502 | sk, usecs_to_jiffies(t_nfb), t_nfb); | 502 | sk, usecs_to_jiffies(t_nfb), t_nfb); |
503 | 503 | ||
504 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, | 504 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, |
505 | jiffies + usecs_to_jiffies(t_nfb)); | 505 | jiffies + usecs_to_jiffies(t_nfb)); |
506 | break; | ||
507 | case TFRC_SSTATE_NO_SENT: /* fall through */ | ||
508 | case TFRC_SSTATE_TERM: /* ignore feedback when closing */ | ||
509 | break; | ||
510 | } | ||
511 | } | 506 | } |
512 | 507 | ||
513 | static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | 508 | static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, |