aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-09-15 23:21:48 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-15 23:21:48 -0400
commit7fedd7e5dfeb0f6bd69ee120b5c44a5e49892e47 (patch)
tree01be8759e2177d53c3766fa9e1593cd8b83b1026 /net
parent1a19eb753a591f8b39946b7fda91b25f07454835 (diff)
parent37efb03fbd0935f5f85a0538c46b53be5cf40504 (diff)
Merge branch 'dccp' of git://eden-feed.erg.abdn.ac.uk/net-next-2.6
Diffstat (limited to 'net')
-rw-r--r--net/dccp/ccids/ccid3.c110
-rw-r--r--net/dccp/ccids/ccid3.h21
-rw-r--r--net/dccp/ccids/lib/packet_history.c39
-rw-r--r--net/dccp/ccids/lib/packet_history.h22
4 files changed, 73 insertions, 119 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 278e17069322..ce8059130070 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -91,19 +91,16 @@ static inline u64 rfc3390_initial_rate(struct sock *sk)
91 return scaled_div(w_init << 6, hc->tx_rtt); 91 return scaled_div(w_init << 6, hc->tx_rtt);
92} 92}
93 93
94/* 94/**
95 * Recalculate t_ipi and delta (should be called whenever X changes) 95 * ccid3_update_send_interval - Calculate new t_ipi = s / X_inst
96 * This respects the granularity of X_inst (64 * bytes/second).
96 */ 97 */
97static void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hc) 98static void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hc)
98{ 99{
99 /* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
100 hc->tx_t_ipi = scaled_div32(((u64)hc->tx_s) << 6, hc->tx_x); 100 hc->tx_t_ipi = scaled_div32(((u64)hc->tx_s) << 6, hc->tx_x);
101 101
102 /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ 102 ccid3_pr_debug("t_ipi=%u, s=%u, X=%u\n", hc->tx_t_ipi,
103 hc->tx_delta = min_t(u32, hc->tx_t_ipi / 2, TFRC_OPSYS_HALF_TIME_GRAN); 103 hc->tx_s, (unsigned)(hc->tx_x >> 6));
104
105 ccid3_pr_debug("t_ipi=%u, delta=%u, s=%u, X=%u\n", hc->tx_t_ipi,
106 hc->tx_delta, hc->tx_s, (unsigned)(hc->tx_x >> 6));
107} 104}
108 105
109static u32 ccid3_hc_tx_idle_rtt(struct ccid3_hc_tx_sock *hc, ktime_t now) 106static u32 ccid3_hc_tx_idle_rtt(struct ccid3_hc_tx_sock *hc, ktime_t now)
@@ -332,15 +329,15 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
332 delay = ktime_us_delta(hc->tx_t_nom, now); 329 delay = ktime_us_delta(hc->tx_t_nom, now);
333 ccid3_pr_debug("delay=%ld\n", (long)delay); 330 ccid3_pr_debug("delay=%ld\n", (long)delay);
334 /* 331 /*
335 * Scheduling of packet transmissions [RFC 3448, 4.6] 332 * Scheduling of packet transmissions (RFC 5348, 8.3)
336 * 333 *
337 * if (t_now > t_nom - delta) 334 * if (t_now > t_nom - delta)
338 * // send the packet now 335 * // send the packet now
339 * else 336 * else
340 * // send the packet in (t_nom - t_now) milliseconds. 337 * // send the packet in (t_nom - t_now) milliseconds.
341 */ 338 */
342 if (delay - (s64)hc->tx_delta >= 1000) 339 if (delay >= TFRC_T_DELTA)
343 return (u32)delay / 1000L; 340 return (u32)delay / USEC_PER_MSEC;
344 341
345 ccid3_hc_tx_update_win_count(hc, now); 342 ccid3_hc_tx_update_win_count(hc, now);
346 break; 343 break;
@@ -373,6 +370,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
373{ 370{
374 struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); 371 struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
375 struct ccid3_options_received *opt_recv = &hc->tx_options_received; 372 struct ccid3_options_received *opt_recv = &hc->tx_options_received;
373 struct tfrc_tx_hist_entry *acked;
376 ktime_t now; 374 ktime_t now;
377 unsigned long t_nfb; 375 unsigned long t_nfb;
378 u32 pinv, r_sample; 376 u32 pinv, r_sample;
@@ -386,17 +384,24 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
386 hc->tx_state != TFRC_SSTATE_NO_FBACK) 384 hc->tx_state != TFRC_SSTATE_NO_FBACK)
387 return; 385 return;
388 386
389 now = ktime_get_real(); 387 /*
390 388 * Locate the acknowledged packet in the TX history.
391 /* Estimate RTT from history if ACK number is valid */ 389 *
392 r_sample = tfrc_tx_hist_rtt(hc->tx_hist, 390 * Returning "entry not found" here can for instance happen when
393 DCCP_SKB_CB(skb)->dccpd_ack_seq, now); 391 * - the host has not sent out anything (e.g. a passive server),
394 if (r_sample == 0) { 392 * - the Ack is outdated (packet with higher Ack number was received),
395 DCCP_WARN("%s(%p): %s with bogus ACK-%llu\n", dccp_role(sk), sk, 393 * - it is a bogus Ack (for a packet not sent on this connection).
396 dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type), 394 */
397 (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq); 395 acked = tfrc_tx_hist_find_entry(hc->tx_hist, dccp_hdr_ack_seq(skb));
396 if (acked == NULL)
398 return; 397 return;
399 } 398 /* For the sake of RTT sampling, ignore/remove all older entries */
399 tfrc_tx_hist_purge(&acked->next);
400
401 /* Update the moving average for the RTT estimate (RFC 3448, 4.3) */
402 now = ktime_get_real();
403 r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, acked->stamp));
404 hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9);
400 405
401 /* Update receive rate in units of 64 * bytes/second */ 406 /* Update receive rate in units of 64 * bytes/second */
402 hc->tx_x_recv = opt_recv->ccid3or_receive_rate; 407 hc->tx_x_recv = opt_recv->ccid3or_receive_rate;
@@ -408,11 +413,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
408 hc->tx_p = 0; 413 hc->tx_p = 0;
409 else /* can not exceed 100% */ 414 else /* can not exceed 100% */
410 hc->tx_p = scaled_div(1, pinv); 415 hc->tx_p = scaled_div(1, pinv);
411 /* 416
412 * Validate new RTT sample and update moving average
413 */
414 r_sample = dccp_sample_rtt(sk, r_sample);
415 hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9);
416 /* 417 /*
417 * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3 418 * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3
418 */ 419 */
@@ -484,60 +485,31 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
484 unsigned char len, u16 idx, 485 unsigned char len, u16 idx,
485 unsigned char *value) 486 unsigned char *value)
486{ 487{
487 int rc = 0;
488 const struct dccp_sock *dp = dccp_sk(sk);
489 struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); 488 struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
490 struct ccid3_options_received *opt_recv = &hc->tx_options_received; 489 struct ccid3_options_received *opt_recv = &hc->tx_options_received;
491 __be32 opt_val; 490 __be32 opt_val;
492 491
493 if (opt_recv->ccid3or_seqno != dp->dccps_gsr) {
494 opt_recv->ccid3or_seqno = dp->dccps_gsr;
495 opt_recv->ccid3or_loss_event_rate = ~0;
496 opt_recv->ccid3or_loss_intervals_idx = 0;
497 opt_recv->ccid3or_loss_intervals_len = 0;
498 opt_recv->ccid3or_receive_rate = 0;
499 }
500
501 switch (option) { 492 switch (option) {
493 case TFRC_OPT_RECEIVE_RATE:
502 case TFRC_OPT_LOSS_EVENT_RATE: 494 case TFRC_OPT_LOSS_EVENT_RATE:
503 if (unlikely(len != 4)) { 495 if (unlikely(len != 4)) {
504 DCCP_WARN("%s(%p), invalid len %d " 496 DCCP_WARN("%s(%p), invalid len %d for %u\n",
505 "for TFRC_OPT_LOSS_EVENT_RATE\n", 497 dccp_role(sk), sk, len, option);
506 dccp_role(sk), sk, len); 498 return -EINVAL;
507 rc = -EINVAL;
508 } else {
509 opt_val = get_unaligned((__be32 *)value);
510 opt_recv->ccid3or_loss_event_rate = ntohl(opt_val);
511 ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
512 dccp_role(sk), sk,
513 opt_recv->ccid3or_loss_event_rate);
514 } 499 }
515 break; 500 opt_val = ntohl(get_unaligned((__be32 *)value));
516 case TFRC_OPT_LOSS_INTERVALS: 501
517 opt_recv->ccid3or_loss_intervals_idx = idx; 502 if (option == TFRC_OPT_RECEIVE_RATE) {
518 opt_recv->ccid3or_loss_intervals_len = len; 503 opt_recv->ccid3or_receive_rate = opt_val;
519 ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",
520 dccp_role(sk), sk,
521 opt_recv->ccid3or_loss_intervals_idx,
522 opt_recv->ccid3or_loss_intervals_len);
523 break;
524 case TFRC_OPT_RECEIVE_RATE:
525 if (unlikely(len != 4)) {
526 DCCP_WARN("%s(%p), invalid len %d "
527 "for TFRC_OPT_RECEIVE_RATE\n",
528 dccp_role(sk), sk, len);
529 rc = -EINVAL;
530 } else {
531 opt_val = get_unaligned((__be32 *)value);
532 opt_recv->ccid3or_receive_rate = ntohl(opt_val);
533 ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", 504 ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
534 dccp_role(sk), sk, 505 dccp_role(sk), sk, opt_val);
535 opt_recv->ccid3or_receive_rate); 506 } else {
507 opt_recv->ccid3or_loss_event_rate = opt_val;
508 ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
509 dccp_role(sk), sk, opt_val);
536 } 510 }
537 break;
538 } 511 }
539 512 return 0;
540 return rc;
541} 513}
542 514
543static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) 515static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index b7e569c22f36..9eb90b863abd 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -45,12 +45,22 @@
45/* Two seconds as per RFC 5348, 4.2 */ 45/* Two seconds as per RFC 5348, 4.2 */
46#define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) 46#define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC)
47 47
48/* In usecs - half the scheduling granularity as per RFC3448 4.6 */
49#define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ))
50
51/* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */ 48/* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
52#define TFRC_T_MBI 64 49#define TFRC_T_MBI 64
53 50
51/*
52 * The t_delta parameter (RFC 5348, 8.3): delays of less than %USEC_PER_MSEC are
53 * rounded down to 0, since sk_reset_timer() here uses millisecond granularity.
54 * Hence we can use a constant t_delta = %USEC_PER_MSEC when HZ >= 500. A coarse
55 * resolution of HZ < 500 means that the error is below one timer tick (t_gran)
56 * when using the constant t_delta = t_gran / 2 = %USEC_PER_SEC / (2 * HZ).
57 */
58#if (HZ >= 500)
59# define TFRC_T_DELTA USEC_PER_MSEC
60#else
61# define TFRC_T_DELTA (USEC_PER_SEC / (2 * HZ))
62#endif
63
54enum ccid3_options { 64enum ccid3_options {
55 TFRC_OPT_LOSS_EVENT_RATE = 192, 65 TFRC_OPT_LOSS_EVENT_RATE = 192,
56 TFRC_OPT_LOSS_INTERVALS = 193, 66 TFRC_OPT_LOSS_INTERVALS = 193,
@@ -58,9 +68,6 @@ enum ccid3_options {
58}; 68};
59 69
60struct ccid3_options_received { 70struct ccid3_options_received {
61 u64 ccid3or_seqno:48,
62 ccid3or_loss_intervals_idx:16;
63 u16 ccid3or_loss_intervals_len;
64 u32 ccid3or_loss_event_rate; 71 u32 ccid3or_loss_event_rate;
65 u32 ccid3or_receive_rate; 72 u32 ccid3or_receive_rate;
66}; 73};
@@ -90,7 +97,6 @@ enum ccid3_hc_tx_states {
90 * @tx_no_feedback_timer: Handle to no feedback timer 97 * @tx_no_feedback_timer: Handle to no feedback timer
91 * @tx_t_ld: Time last doubled during slow start 98 * @tx_t_ld: Time last doubled during slow start
92 * @tx_t_nom: Nominal send time of next packet 99 * @tx_t_nom: Nominal send time of next packet
93 * @tx_delta: Send timer delta (RFC 3448, 4.6) in usecs
94 * @tx_hist: Packet history 100 * @tx_hist: Packet history
95 * @tx_options_received: Parsed set of retrieved options 101 * @tx_options_received: Parsed set of retrieved options
96 */ 102 */
@@ -109,7 +115,6 @@ struct ccid3_hc_tx_sock {
109 struct timer_list tx_no_feedback_timer; 115 struct timer_list tx_no_feedback_timer;
110 ktime_t tx_t_ld; 116 ktime_t tx_t_ld;
111 ktime_t tx_t_nom; 117 ktime_t tx_t_nom;
112 u32 tx_delta;
113 struct tfrc_tx_hist_entry *tx_hist; 118 struct tfrc_tx_hist_entry *tx_hist;
114 struct ccid3_options_received tx_options_received; 119 struct ccid3_options_received tx_options_received;
115}; 120};
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index 3a4f414e94a0..de8fe294bf0b 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -38,18 +38,6 @@
38#include "packet_history.h" 38#include "packet_history.h"
39#include "../../dccp.h" 39#include "../../dccp.h"
40 40
41/**
42 * tfrc_tx_hist_entry - Simple singly-linked TX history list
43 * @next: next oldest entry (LIFO order)
44 * @seqno: sequence number of this entry
45 * @stamp: send time of packet with sequence number @seqno
46 */
47struct tfrc_tx_hist_entry {
48 struct tfrc_tx_hist_entry *next;
49 u64 seqno;
50 ktime_t stamp;
51};
52
53/* 41/*
54 * Transmitter History Routines 42 * Transmitter History Routines
55 */ 43 */
@@ -71,15 +59,6 @@ void tfrc_tx_packet_history_exit(void)
71 } 59 }
72} 60}
73 61
74static struct tfrc_tx_hist_entry *
75 tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
76{
77 while (head != NULL && head->seqno != seqno)
78 head = head->next;
79
80 return head;
81}
82
83int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno) 62int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno)
84{ 63{
85 struct tfrc_tx_hist_entry *entry = kmem_cache_alloc(tfrc_tx_hist_slab, gfp_any()); 64 struct tfrc_tx_hist_entry *entry = kmem_cache_alloc(tfrc_tx_hist_slab, gfp_any());
@@ -107,24 +86,6 @@ void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp)
107 *headp = NULL; 86 *headp = NULL;
108} 87}
109 88
110u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head, const u64 seqno,
111 const ktime_t now)
112{
113 u32 rtt = 0;
114 struct tfrc_tx_hist_entry *packet = tfrc_tx_hist_find_entry(head, seqno);
115
116 if (packet != NULL) {
117 rtt = ktime_us_delta(now, packet->stamp);
118 /*
119 * Garbage-collect older (irrelevant) entries:
120 */
121 tfrc_tx_hist_purge(&packet->next);
122 }
123
124 return rtt;
125}
126
127
128/* 89/*
129 * Receiver History Routines 90 * Receiver History Routines
130 */ 91 */
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 7df6c5299999..7ee4a9d9d335 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -40,12 +40,28 @@
40#include <linux/slab.h> 40#include <linux/slab.h>
41#include "tfrc.h" 41#include "tfrc.h"
42 42
43struct tfrc_tx_hist_entry; 43/**
44 * tfrc_tx_hist_entry - Simple singly-linked TX history list
45 * @next: next oldest entry (LIFO order)
46 * @seqno: sequence number of this entry
47 * @stamp: send time of packet with sequence number @seqno
48 */
49struct tfrc_tx_hist_entry {
50 struct tfrc_tx_hist_entry *next;
51 u64 seqno;
52 ktime_t stamp;
53};
54
55static inline struct tfrc_tx_hist_entry *
56 tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
57{
58 while (head != NULL && head->seqno != seqno)
59 head = head->next;
60 return head;
61}
44 62
45extern int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno); 63extern int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno);
46extern void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp); 64extern void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp);
47extern u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head,
48 const u64 seqno, const ktime_t now);
49 65
50/* Subtraction a-b modulo-16, respects circular wrap-around */ 66/* Subtraction a-b modulo-16, respects circular wrap-around */
51#define SUB16(a, b) (((a) + 16 - (b)) & 0xF) 67#define SUB16(a, b) (((a) + 16 - (b)) & 0xF)