diff options
-rw-r--r-- | net/dccp/ccids/ccid3.c | 34 | ||||
-rw-r--r-- | net/dccp/ccids/lib/packet_history.c | 39 | ||||
-rw-r--r-- | net/dccp/ccids/lib/packet_history.h | 22 |
3 files changed, 38 insertions, 57 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index e9ca0983ac58..b2ddd205d438 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -370,6 +370,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
370 | { | 370 | { |
371 | struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); | 371 | struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); |
372 | 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; | ||
373 | ktime_t now; | 374 | ktime_t now; |
374 | unsigned long t_nfb; | 375 | unsigned long t_nfb; |
375 | u32 pinv, r_sample; | 376 | u32 pinv, r_sample; |
@@ -383,17 +384,24 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
383 | hc->tx_state != TFRC_SSTATE_NO_FBACK) | 384 | hc->tx_state != TFRC_SSTATE_NO_FBACK) |
384 | return; | 385 | return; |
385 | 386 | ||
386 | now = ktime_get_real(); | 387 | /* |
387 | 388 | * Locate the acknowledged packet in the TX history. | |
388 | /* Estimate RTT from history if ACK number is valid */ | 389 | * |
389 | r_sample = tfrc_tx_hist_rtt(hc->tx_hist, | 390 | * Returning "entry not found" here can for instance happen when |
390 | DCCP_SKB_CB(skb)->dccpd_ack_seq, now); | 391 | * - the host has not sent out anything (e.g. a passive server), |
391 | if (r_sample == 0) { | 392 | * - the Ack is outdated (packet with higher Ack number was received), |
392 | 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). |
393 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type), | 394 | */ |
394 | (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) | ||
395 | return; | 397 | return; |
396 | } | 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); | ||
397 | 405 | ||
398 | /* Update receive rate in units of 64 * bytes/second */ | 406 | /* Update receive rate in units of 64 * bytes/second */ |
399 | hc->tx_x_recv = opt_recv->ccid3or_receive_rate; | 407 | hc->tx_x_recv = opt_recv->ccid3or_receive_rate; |
@@ -405,11 +413,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
405 | hc->tx_p = 0; | 413 | hc->tx_p = 0; |
406 | else /* can not exceed 100% */ | 414 | else /* can not exceed 100% */ |
407 | hc->tx_p = scaled_div(1, pinv); | 415 | hc->tx_p = scaled_div(1, pinv); |
408 | /* | 416 | |
409 | * Validate new RTT sample and update moving average | ||
410 | */ | ||
411 | r_sample = dccp_sample_rtt(sk, r_sample); | ||
412 | hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9); | ||
413 | /* | 417 | /* |
414 | * 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 |
415 | */ | 419 | */ |
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 | */ | ||
47 | struct 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 | ||
74 | static 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 | |||
83 | int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno) | 62 | int 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 | ||
110 | u32 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 | ||
43 | struct 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 | */ | ||
49 | struct tfrc_tx_hist_entry { | ||
50 | struct tfrc_tx_hist_entry *next; | ||
51 | u64 seqno; | ||
52 | ktime_t stamp; | ||
53 | }; | ||
54 | |||
55 | static 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 | ||
45 | extern int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno); | 63 | extern int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno); |
46 | extern void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp); | 64 | extern void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp); |
47 | extern 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) |