aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ccids/lib
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:30:19 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:45:41 -0400
commit2b81143aa3505e2460b24b357996c2f21840ea58 (patch)
tree37f752fb85c563f965655cec834bb289fd831137 /net/dccp/ccids/lib
parent2f3e3bbad917c426d3aba03a535809e5699de156 (diff)
dccp ccid-3: Always perform receiver RTT sampling
This updates the CCID-3 receiver in part with regard to errata 610 and 611 (http://www.rfc-editor.org/errata_list.php), which change RFC 4342 to use the Receive Rate as specified in rfc3448bis, requiring to constantly sample the RTT (or use a sender RTT). Doing this requires reusing the RX history structure after dealing with a loss. The patch does not resolve how to compute X_recv if the interval is less than 1 RTT. A FIXME has been added (and is resolved in subsequent patch). Furthermore, since this is all TFRC-based functionality, the RTT estimation is now also performed by the dccp_tfrc_lib module. This further simplifies the CCID-3 code. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net/dccp/ccids/lib')
-rw-r--r--net/dccp/ccids/lib/packet_history.c60
-rw-r--r--net/dccp/ccids/lib/packet_history.h17
2 files changed, 59 insertions, 18 deletions
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index ee34b4564242..e2e250aa5c89 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -151,14 +151,31 @@ int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb)
151} 151}
152EXPORT_SYMBOL_GPL(tfrc_rx_hist_duplicate); 152EXPORT_SYMBOL_GPL(tfrc_rx_hist_duplicate);
153 153
154
155static void __tfrc_rx_hist_swap(struct tfrc_rx_hist *h, const u8 a, const u8 b)
156{
157 struct tfrc_rx_hist_entry *tmp = h->ring[a];
158
159 h->ring[a] = h->ring[b];
160 h->ring[b] = tmp;
161}
162
154static void tfrc_rx_hist_swap(struct tfrc_rx_hist *h, const u8 a, const u8 b) 163static void tfrc_rx_hist_swap(struct tfrc_rx_hist *h, const u8 a, const u8 b)
155{ 164{
156 const u8 idx_a = tfrc_rx_hist_index(h, a), 165 __tfrc_rx_hist_swap(h, tfrc_rx_hist_index(h, a),
157 idx_b = tfrc_rx_hist_index(h, b); 166 tfrc_rx_hist_index(h, b));
158 struct tfrc_rx_hist_entry *tmp = h->ring[idx_a]; 167}
159 168
160 h->ring[idx_a] = h->ring[idx_b]; 169/**
161 h->ring[idx_b] = tmp; 170 * tfrc_rx_hist_resume_rtt_sampling - Prepare RX history for RTT sampling
171 * This is called after loss detection has finished, when the history entry
172 * with the index of `loss_count' holds the highest-received sequence number.
173 * RTT sampling requires this information at ring[0] (tfrc_rx_hist_sample_rtt).
174 */
175static inline void tfrc_rx_hist_resume_rtt_sampling(struct tfrc_rx_hist *h)
176{
177 __tfrc_rx_hist_swap(h, 0, tfrc_rx_hist_index(h, h->loss_count));
178 h->loss_count = h->loss_start = 0;
162} 179}
163 180
164/* 181/*
@@ -200,8 +217,7 @@ static void __one_after_loss(struct tfrc_rx_hist *h, struct sk_buff *skb, u32 n2
200 217
201 if (dccp_loss_free(s2, s1, n1)) { 218 if (dccp_loss_free(s2, s1, n1)) {
202 /* hole is filled: S0, S2, and S1 are consecutive */ 219 /* hole is filled: S0, S2, and S1 are consecutive */
203 h->loss_count = 0; 220 tfrc_rx_hist_resume_rtt_sampling(h);
204 h->loss_start = tfrc_rx_hist_index(h, 1);
205 } else 221 } else
206 /* gap between S2 and S1: just update loss_prev */ 222 /* gap between S2 and S1: just update loss_prev */
207 tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_loss_prev(h), skb, n2); 223 tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_loss_prev(h), skb, n2);
@@ -254,8 +270,7 @@ static int __two_after_loss(struct tfrc_rx_hist *h, struct sk_buff *skb, u32 n3)
254 270
255 if (dccp_loss_free(s1, s2, n2)) { 271 if (dccp_loss_free(s1, s2, n2)) {
256 /* entire hole filled by S0, S3, S1, S2 */ 272 /* entire hole filled by S0, S3, S1, S2 */
257 h->loss_start = tfrc_rx_hist_index(h, 2); 273 tfrc_rx_hist_resume_rtt_sampling(h);
258 h->loss_count = 0;
259 } else { 274 } else {
260 /* gap remains between S1 and S2 */ 275 /* gap remains between S1 and S2 */
261 h->loss_start = tfrc_rx_hist_index(h, 1); 276 h->loss_start = tfrc_rx_hist_index(h, 1);
@@ -299,8 +314,7 @@ static void __three_after_loss(struct tfrc_rx_hist *h)
299 314
300 if (dccp_loss_free(s2, s3, n3)) { 315 if (dccp_loss_free(s2, s3, n3)) {
301 /* no gap between S2 and S3: entire hole is filled */ 316 /* no gap between S2 and S3: entire hole is filled */
302 h->loss_start = tfrc_rx_hist_index(h, 3); 317 tfrc_rx_hist_resume_rtt_sampling(h);
303 h->loss_count = 0;
304 } else { 318 } else {
305 /* gap between S2 and S3 */ 319 /* gap between S2 and S3 */
306 h->loss_start = tfrc_rx_hist_index(h, 2); 320 h->loss_start = tfrc_rx_hist_index(h, 2);
@@ -340,6 +354,7 @@ int tfrc_rx_handle_loss(struct tfrc_rx_hist *h,
340 354
341 if (h->loss_count == 0) { 355 if (h->loss_count == 0) {
342 __do_track_loss(h, skb, ndp); 356 __do_track_loss(h, skb, ndp);
357 tfrc_rx_hist_sample_rtt(h, skb);
343 } else if (h->loss_count == 1) { 358 } else if (h->loss_count == 1) {
344 __one_after_loss(h, skb, ndp); 359 __one_after_loss(h, skb, ndp);
345 } else if (h->loss_count != 2) { 360 } else if (h->loss_count != 2) {
@@ -435,11 +450,24 @@ static inline struct tfrc_rx_hist_entry *
435 * Based on ideas presented in RFC 4342, 8.1. Returns 0 if it was not able 450 * Based on ideas presented in RFC 4342, 8.1. Returns 0 if it was not able
436 * to compute a sample with given data - calling function should check this. 451 * to compute a sample with given data - calling function should check this.
437 */ 452 */
438u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h, const struct sk_buff *skb) 453void tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h, const struct sk_buff *skb)
439{ 454{
440 u32 sample = 0, 455 u32 sample = 0, delta_v;
441 delta_v = SUB16(dccp_hdr(skb)->dccph_ccval, 456
442 tfrc_rx_hist_rtt_last_s(h)->tfrchrx_ccval); 457 /*
458 * When not to sample:
459 * - on non-data packets
460 * (RFC 4342, 8.1: CCVal only fully defined for data packets);
461 * - when no data packets have been received yet
462 * (FIXME: using sampled packet size as indicator here);
463 * - as long as there are gaps in the sequence space (pending loss).
464 */
465 if (!dccp_data_packet(skb) || h->packet_size == 0 ||
466 tfrc_rx_hist_loss_pending(h))
467 return;
468
469 delta_v = SUB16(dccp_hdr(skb)->dccph_ccval,
470 tfrc_rx_hist_rtt_last_s(h)->tfrchrx_ccval);
443 471
444 if (delta_v < 1 || delta_v > 4) { /* unsuitable CCVal delta */ 472 if (delta_v < 1 || delta_v > 4) { /* unsuitable CCVal delta */
445 if (h->rtt_sample_prev == 2) { /* previous candidate stored */ 473 if (h->rtt_sample_prev == 2) { /* previous candidate stored */
@@ -479,6 +507,6 @@ u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h, const struct sk_buff *skb)
479 h->rtt_sample_prev = 0; /* use current entry as next reference */ 507 h->rtt_sample_prev = 0; /* use current entry as next reference */
480keep_ref_for_next_time: 508keep_ref_for_next_time:
481 509
482 return sample; 510 h->rtt_estimate = tfrc_ewma(h->rtt_estimate, sample, 9);
483} 511}
484EXPORT_SYMBOL_GPL(tfrc_rx_hist_sample_rtt); 512EXPORT_SYMBOL_GPL(tfrc_rx_hist_sample_rtt);
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index b7c87a1a2720..ba5832bbc348 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -91,6 +91,7 @@ struct tfrc_rx_hist_entry {
91 * @loss_count: Number of entries in circular history 91 * @loss_count: Number of entries in circular history
92 * @loss_start: Movable index (for loss detection) 92 * @loss_start: Movable index (for loss detection)
93 * @rtt_sample_prev: Used during RTT sampling, points to candidate entry 93 * @rtt_sample_prev: Used during RTT sampling, points to candidate entry
94 * @rtt_estimate: Receiver RTT estimate
94 * @packet_size: Packet size in bytes (as per RFC 3448, 3.1) 95 * @packet_size: Packet size in bytes (as per RFC 3448, 3.1)
95 * @bytes_recvd: Number of bytes received since last sending feedback 96 * @bytes_recvd: Number of bytes received since last sending feedback
96 */ 97 */
@@ -98,7 +99,10 @@ struct tfrc_rx_hist {
98 struct tfrc_rx_hist_entry *ring[TFRC_NDUPACK + 1]; 99 struct tfrc_rx_hist_entry *ring[TFRC_NDUPACK + 1];
99 u8 loss_count:2, 100 u8 loss_count:2,
100 loss_start:2; 101 loss_start:2;
102 /* Receiver RTT sampling */
101#define rtt_sample_prev loss_start 103#define rtt_sample_prev loss_start
104 u32 rtt_estimate;
105 /* Receiver sampling of application payload lengths */
102 u32 packet_size, 106 u32 packet_size,
103 bytes_recvd; 107 bytes_recvd;
104}; 108};
@@ -154,6 +158,15 @@ static inline u32 tfrc_rx_hist_packet_size(const struct tfrc_rx_hist *h)
154 return TCP_MIN_RCVMSS; 158 return TCP_MIN_RCVMSS;
155 } 159 }
156 return h->packet_size; 160 return h->packet_size;
161
162}
163static inline u32 tfrc_rx_hist_rtt(const struct tfrc_rx_hist *h)
164{
165 if (h->rtt_estimate == 0) {
166 DCCP_WARN("No RTT estimate available, using fallback RTT\n");
167 return DCCP_FALLBACK_RTT;
168 }
169 return h->rtt_estimate;
157} 170}
158 171
159extern void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h, 172extern void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
@@ -167,8 +180,8 @@ extern int tfrc_rx_handle_loss(struct tfrc_rx_hist *h,
167 struct sk_buff *skb, const u64 ndp, 180 struct sk_buff *skb, const u64 ndp,
168 u32 (*first_li)(struct sock *sk), 181 u32 (*first_li)(struct sock *sk),
169 struct sock *sk); 182 struct sock *sk);
170extern u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h, 183extern void tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h,
171 const struct sk_buff *skb); 184 const struct sk_buff *skb);
172extern int tfrc_rx_hist_init(struct tfrc_rx_hist *h, struct sock *sk); 185extern int tfrc_rx_hist_init(struct tfrc_rx_hist *h, struct sock *sk);
173extern void tfrc_rx_hist_purge(struct tfrc_rx_hist *h); 186extern void tfrc_rx_hist_purge(struct tfrc_rx_hist *h);
174 187