diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2007-12-17 09:57:43 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:58:23 -0500 |
commit | 52515e77a7a69867c479db4c9efb6be832b82179 (patch) | |
tree | d4246af065a53f7e2ae92070ec07d59ba892baf6 /net/dccp | |
parent | d8d1252f744cb7cebd6ba3a4b7feec31ff23ccde (diff) |
[CCID3]: Nofeedback timer according to rfc3448bis
This implements the changes to the nofeedback timer handling suggested
in draft rfc3448bis00, section 4.4. In particular, these changes mean:
* better handling of the lossless case (p == 0)
* the timestamp for computing t_ld becomes obsolete
* much more recent document (RFC 3448 is almost 5 years old)
* concepts in rfc3448bis arose from a real, working implementation
(cf. sec. 12)
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 63 |
1 files changed, 29 insertions, 34 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 1156fef17471..d292f23c002e 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -131,12 +131,11 @@ static u32 ccid3_hc_tx_idle_rtt(struct ccid3_hc_tx_sock *hctx, ktime_t now) | |||
131 | * | 131 | * |
132 | */ | 132 | */ |
133 | static void ccid3_hc_tx_update_x(struct sock *sk, ktime_t *stamp) | 133 | static void ccid3_hc_tx_update_x(struct sock *sk, ktime_t *stamp) |
134 | |||
135 | { | 134 | { |
136 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 135 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
137 | __u64 min_rate = 2 * hctx->ccid3hctx_x_recv; | 136 | __u64 min_rate = 2 * hctx->ccid3hctx_x_recv; |
138 | const __u64 old_x = hctx->ccid3hctx_x; | 137 | const __u64 old_x = hctx->ccid3hctx_x; |
139 | ktime_t now = stamp? *stamp : ktime_get_real(); | 138 | ktime_t now = stamp ? *stamp : ktime_get_real(); |
140 | 139 | ||
141 | /* | 140 | /* |
142 | * Handle IDLE periods: do not reduce below RFC3390 initial sending rate | 141 | * Handle IDLE periods: do not reduce below RFC3390 initial sending rate |
@@ -230,27 +229,27 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
230 | ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk, | 229 | ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk, |
231 | ccid3_tx_state_name(hctx->ccid3hctx_state)); | 230 | ccid3_tx_state_name(hctx->ccid3hctx_state)); |
232 | 231 | ||
233 | switch (hctx->ccid3hctx_state) { | 232 | if (hctx->ccid3hctx_state == TFRC_SSTATE_FBACK) |
234 | case TFRC_SSTATE_NO_FBACK: | 233 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); |
235 | /* RFC 3448, 4.4: Halve send rate directly */ | 234 | else if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK) |
235 | goto out; | ||
236 | |||
237 | /* | ||
238 | * Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4 | ||
239 | */ | ||
240 | if (hctx->ccid3hctx_t_rto == 0 || /* no feedback received yet */ | ||
241 | hctx->ccid3hctx_p == 0) { | ||
242 | |||
243 | /* halve send rate directly */ | ||
236 | hctx->ccid3hctx_x = max(hctx->ccid3hctx_x / 2, | 244 | hctx->ccid3hctx_x = max(hctx->ccid3hctx_x / 2, |
237 | (((__u64)hctx->ccid3hctx_s) << 6) / | 245 | (((__u64)hctx->ccid3hctx_s) << 6) / |
238 | TFRC_T_MBI); | 246 | TFRC_T_MBI); |
239 | |||
240 | ccid3_pr_debug("%s(%p, state=%s), updated tx rate to %u " | ||
241 | "bytes/s\n", dccp_role(sk), sk, | ||
242 | ccid3_tx_state_name(hctx->ccid3hctx_state), | ||
243 | (unsigned)(hctx->ccid3hctx_x >> 6)); | ||
244 | /* The value of R is still undefined and so we can not recompute | ||
245 | * the timeout value. Keep initial value as per [RFC 4342, 5]. */ | ||
246 | t_nfb = TFRC_INITIAL_TIMEOUT; | ||
247 | ccid3_update_send_interval(hctx); | 247 | ccid3_update_send_interval(hctx); |
248 | break; | 248 | } else { |
249 | case TFRC_SSTATE_FBACK: | ||
250 | /* | 249 | /* |
251 | * Modify the cached value of X_recv [RFC 3448, 4.4] | 250 | * Modify the cached value of X_recv |
252 | * | 251 | * |
253 | * If (p == 0 || X_calc > 2 * X_recv) | 252 | * If (X_calc > 2 * X_recv) |
254 | * X_recv = max(X_recv / 2, s / (2 * t_mbi)); | 253 | * X_recv = max(X_recv / 2, s / (2 * t_mbi)); |
255 | * Else | 254 | * Else |
256 | * X_recv = X_calc / 4; | 255 | * X_recv = X_calc / 4; |
@@ -259,32 +258,28 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
259 | */ | 258 | */ |
260 | BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc); | 259 | BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc); |
261 | 260 | ||
262 | if (hctx->ccid3hctx_p == 0 || | 261 | if (hctx->ccid3hctx_x_calc > (hctx->ccid3hctx_x_recv >> 5)) |
263 | (hctx->ccid3hctx_x_calc > (hctx->ccid3hctx_x_recv >> 5))) { | ||
264 | |||
265 | hctx->ccid3hctx_x_recv = | 262 | hctx->ccid3hctx_x_recv = |
266 | max(hctx->ccid3hctx_x_recv / 2, | 263 | max(hctx->ccid3hctx_x_recv / 2, |
267 | (((__u64)hctx->ccid3hctx_s) << 6) / | 264 | (((__u64)hctx->ccid3hctx_s) << 6) / |
268 | (2 * TFRC_T_MBI)); | 265 | (2 * TFRC_T_MBI)); |
269 | } else { | 266 | else { |
270 | hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc; | 267 | hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc; |
271 | hctx->ccid3hctx_x_recv <<= 4; | 268 | hctx->ccid3hctx_x_recv <<= 4; |
272 | } | 269 | } |
273 | /* Now recalculate X [RFC 3448, 4.3, step (4)] */ | ||
274 | ccid3_hc_tx_update_x(sk, NULL); | 270 | ccid3_hc_tx_update_x(sk, NULL); |
275 | /* | ||
276 | * Schedule no feedback timer to expire in | ||
277 | * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) | ||
278 | * See comments in packet_recv() regarding the value of t_RTO. | ||
279 | */ | ||
280 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); | ||
281 | break; | ||
282 | case TFRC_SSTATE_NO_SENT: | ||
283 | DCCP_BUG("%s(%p) - Illegal state NO_SENT", dccp_role(sk), sk); | ||
284 | /* fall through */ | ||
285 | case TFRC_SSTATE_TERM: | ||
286 | goto out; | ||
287 | } | 271 | } |
272 | ccid3_pr_debug("Reduced X to %llu/64 bytes/sec\n", | ||
273 | (unsigned long long)hctx->ccid3hctx_x); | ||
274 | |||
275 | /* | ||
276 | * Set new timeout for the nofeedback timer. | ||
277 | * See comments in packet_recv() regarding the value of t_RTO. | ||
278 | */ | ||
279 | if (unlikely(hctx->ccid3hctx_t_rto == 0)) /* no feedback yet */ | ||
280 | t_nfb = TFRC_INITIAL_TIMEOUT; | ||
281 | else | ||
282 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); | ||
288 | 283 | ||
289 | restart_timer: | 284 | restart_timer: |
290 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, | 285 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, |