aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ccids/ccid3.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 22:24:40 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 22:24:40 -0500
commit83ac58ba0a26228c0b16baa2c4b821de9c4ad5ca (patch)
tree6c8354a6314c39c5fa3f923e4095c16a5fed3d08 /net/dccp/ccids/ccid3.c
parentb4ad86bf52469b26148c677cb59d8bc81f129cc2 (diff)
parent2bbf29acd8f7adcf161de7e5d891b4095687a59f (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6
Diffstat (limited to 'net/dccp/ccids/ccid3.c')
-rw-r--r--net/dccp/ccids/ccid3.c119
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 */
131static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) 134static 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;