aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ccids
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2010-09-14 14:18:00 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2010-09-15 06:36:02 -0400
commitd2c726309d88df3c5568486e4b5b9e4c3150903f (patch)
treef4aab69a2cd3f76a1cf483a20eb11295a2ea1395 /net/dccp/ccids
parent20cbd3e120a0c20bebe420e1fed0e816730bb988 (diff)
dccp ccid-3: remove buggy RTT-sampling history lookup
This removes the RTT-sampling function tfrc_tx_hist_rtt(), since 1. it suffered from complex passing of return values (the return value both indicated successful lookup while the value doubled as RTT sample); 2. when for some odd reason the sample value equalled 0, this triggered a bug warning about "bogus Ack", due to the ambiguity of the return value; 3. on a passive host which has not sent anything the TX history is empty and thus will lead to unwanted "bogus Ack" warnings such as ccid3_hc_tx_packet_recv: server(e7b7d518): DATAACK with bogus ACK-28197148 ccid3_hc_tx_packet_recv: server(e7b7d518): DATAACK with bogus ACK-26641606. The fix is to replace the implicit encoding by performing the steps manually. Furthermore, the "bogus Ack" warning has been removed, since it can actually be triggered due to several reasons (network reordering, old packet, (3) above), hence it is not very useful. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net/dccp/ccids')
-rw-r--r--net/dccp/ccids/ccid3.c34
-rw-r--r--net/dccp/ccids/lib/packet_history.c39
-rw-r--r--net/dccp/ccids/lib/packet_history.h22
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 */
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)