aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ccids/ccid3.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2007-03-20 13:56:11 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:26:52 -0400
commit1266adee12d25385a25e1c57b1e3ff05a90bb4d7 (patch)
treeeb42be8ede3ca9d5ac00076ebee20be5771c30ee /net/dccp/ccids/ccid3.c
parent8699be7d240e37c91a84bdf32e79941d72bc7bd5 (diff)
[CCID3]: Remove race condition and update t_ipi when `s' changes
This: 1. removes a race condition in the access to the scheduled send time t_nom which results from allowing asynchronous r/w access to t_nom without locks; 2. updates the inter-packet interval t_ipi = s/X when `s' changes, following a suggestion by Ian McDonald. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Acked-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/ccids/ccid3.c')
-rw-r--r--net/dccp/ccids/ccid3.c35
1 files changed, 12 insertions, 23 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 26ab73db2868..95eca99e4dd9 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -82,20 +82,14 @@ static void ccid3_hc_tx_set_state(struct sock *sk,
82} 82}
83 83
84/* 84/*
85 * Recalculate scheduled nominal send time t_nom, inter-packet interval 85 * Recalculate t_ipi and delta (should be called whenever X changes)
86 * t_ipi, and delta value. Should be called after each change to X.
87 */ 86 */
88static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) 87static inline void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hctx)
89{ 88{
90 timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
91
92 /* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */ 89 /* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
93 hctx->ccid3hctx_t_ipi = scaled_div(hctx->ccid3hctx_s, 90 hctx->ccid3hctx_t_ipi = scaled_div(hctx->ccid3hctx_s,
94 hctx->ccid3hctx_x >> 6); 91 hctx->ccid3hctx_x >> 6);
95 92
96 /* Update nominal send time with regard to the new t_ipi */
97 timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
98
99 /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ 93 /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
100 hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2, 94 hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
101 TFRC_OPSYS_HALF_TIME_GRAN); 95 TFRC_OPSYS_HALF_TIME_GRAN);
@@ -119,8 +113,6 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
119 * fine-grained resolution of sending rates. This requires scaling by 2^6 113 * fine-grained resolution of sending rates. This requires scaling by 2^6
120 * throughout the code. Only X_calc is unscaled (in bytes/second). 114 * throughout the code. Only X_calc is unscaled (in bytes/second).
121 * 115 *
122 * If X has changed, we also update the scheduled send time t_now,
123 * the inter-packet interval t_ipi, and the delta value.
124 */ 116 */
125static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) 117static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
126 118
@@ -151,7 +143,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
151 "X_recv=%llu\n", old_x >> 6, hctx->ccid3hctx_x >> 6, 143 "X_recv=%llu\n", old_x >> 6, hctx->ccid3hctx_x >> 6,
152 hctx->ccid3hctx_x_calc, hctx->ccid3hctx_x_recv >> 6); 144 hctx->ccid3hctx_x_calc, hctx->ccid3hctx_x_recv >> 6);
153 145
154 ccid3_update_send_time(hctx); 146 ccid3_update_send_interval(hctx);
155 } 147 }
156} 148}
157 149
@@ -161,14 +153,12 @@ static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
161 */ 153 */
162static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len) 154static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
163{ 155{
164 hctx->ccid3hctx_s = hctx->ccid3hctx_s == 0 ? len : 156 const u16 old_s = hctx->ccid3hctx_s;
165 (9 * hctx->ccid3hctx_s + len) / 10; 157
166 /* 158 hctx->ccid3hctx_s = old_s == 0 ? len : (9 * old_s + len) / 10;
167 * Note: We could do a potential optimisation here - when `s' changes, 159
168 * recalculate sending rate and consequently t_ipi, t_delta, and 160 if (hctx->ccid3hctx_s != old_s)
169 * t_now. This is however non-standard, and the benefits are not 161 ccid3_update_send_interval(hctx);
170 * clear, so it is currently left out.
171 */
172} 162}
173 163
174/* 164/*
@@ -228,7 +218,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
228 /* The value of R is still undefined and so we can not recompute 218 /* The value of R is still undefined and so we can not recompute
229 * the timout value. Keep initial value as per [RFC 4342, 5]. */ 219 * the timout value. Keep initial value as per [RFC 4342, 5]. */
230 t_nfb = TFRC_INITIAL_TIMEOUT; 220 t_nfb = TFRC_INITIAL_TIMEOUT;
231 ccid3_update_send_time(hctx); 221 ccid3_update_send_interval(hctx);
232 break; 222 break;
233 case TFRC_SSTATE_FBACK: 223 case TFRC_SSTATE_FBACK:
234 /* 224 /*
@@ -334,8 +324,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
334 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); 324 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
335 325
336 /* Set initial sending rate X/s to 1pps (X is scaled by 2^6) */ 326 /* Set initial sending rate X/s to 1pps (X is scaled by 2^6) */
337 ccid3_hc_tx_update_s(hctx, skb->len); 327 hctx->ccid3hctx_x = hctx->ccid3hctx_s = skb->len;
338 hctx->ccid3hctx_x = hctx->ccid3hctx_s;
339 hctx->ccid3hctx_x <<= 6; 328 hctx->ccid3hctx_x <<= 6;
340 329
341 /* First timeout, according to [RFC 3448, 4.2], is 1 second */ 330 /* First timeout, according to [RFC 3448, 4.2], is 1 second */
@@ -484,7 +473,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
484 hctx->ccid3hctx_x = scaled_div(w_init << 6, r_sample); 473 hctx->ccid3hctx_x = scaled_div(w_init << 6, r_sample);
485 hctx->ccid3hctx_t_ld = now; 474 hctx->ccid3hctx_t_ld = now;
486 475
487 ccid3_update_send_time(hctx); 476 ccid3_update_send_interval(hctx);
488 477
489 ccid3_pr_debug("%s(%p), s=%u, MSS=%u, w_init=%u, " 478 ccid3_pr_debug("%s(%p), s=%u, MSS=%u, w_init=%u, "
490 "R_sample=%dus, X=%u\n", dccp_role(sk), 479 "R_sample=%dus, X=%u\n", dccp_role(sk),