aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/dccp/ccids/ccid3.c66
-rw-r--r--net/dccp/ccids/ccid3.h4
2 files changed, 37 insertions, 33 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 05513f3df652..aa5440ee20ae 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -128,7 +128,8 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
128 * X = max(min(2 * X, 2 * X_recv), s / R); 128 * X = max(min(2 * X, 2 * X_recv), s / R);
129 * tld = now; 129 * tld = now;
130 */ 130 */
131static void ccid3_hc_tx_update_x(struct sock *sk) 131static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
132
132{ 133{
133 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 134 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
134 const __u32 old_x = hctx->ccid3hctx_x; 135 const __u32 old_x = hctx->ccid3hctx_x;
@@ -138,23 +139,20 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
138 hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, 139 hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s,
139 hctx->ccid3hctx_rtt, 140 hctx->ccid3hctx_rtt,
140 hctx->ccid3hctx_p); 141 hctx->ccid3hctx_p);
141 hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_calc, 142 hctx->ccid3hctx_x = max_t(u32, min(hctx->ccid3hctx_x_calc,
142 2 * hctx->ccid3hctx_x_recv), 143 hctx->ccid3hctx_x_recv * 2),
143 (hctx->ccid3hctx_s / 144 hctx->ccid3hctx_s / TFRC_T_MBI);
144 TFRC_MAX_BACK_OFF_TIME)); 145
145 } else { 146 } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >=
146 struct timeval now; 147 hctx->ccid3hctx_rtt) {
148 hctx->ccid3hctx_x = max(min(hctx->ccid3hctx_x_recv,
149 hctx->ccid3hctx_x ) * 2,
150 usecs_div(hctx->ccid3hctx_s,
151 hctx->ccid3hctx_rtt) );
152 hctx->ccid3hctx_t_ld = *now;
153 } else
154 ccid3_pr_debug("Not changing X\n");
147 155
148 dccp_timestamp(sk, &now);
149 if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
150 hctx->ccid3hctx_rtt) {
151 hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
152 hctx->ccid3hctx_x) * 2,
153 usecs_div(hctx->ccid3hctx_s,
154 hctx->ccid3hctx_rtt));
155 hctx->ccid3hctx_t_ld = now;
156 }
157 }
158 if (hctx->ccid3hctx_x != old_x) 156 if (hctx->ccid3hctx_x != old_x)
159 ccid3_update_send_time(hctx); 157 ccid3_update_send_time(hctx);
160} 158}
@@ -196,12 +194,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
196 194
197 switch (hctx->ccid3hctx_state) { 195 switch (hctx->ccid3hctx_state) {
198 case TFRC_SSTATE_NO_FBACK: 196 case TFRC_SSTATE_NO_FBACK:
199 /* Halve send rate */ 197 /* RFC 3448, 4.4: Halve send rate directly */
200 hctx->ccid3hctx_x /= 2; 198 hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2,
201 if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s / 199 hctx->ccid3hctx_s / TFRC_T_MBI);
202 TFRC_MAX_BACK_OFF_TIME))
203 hctx->ccid3hctx_x = (hctx->ccid3hctx_s /
204 TFRC_MAX_BACK_OFF_TIME);
205 200
206 ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d " 201 ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d "
207 "bytes/s\n", 202 "bytes/s\n",
@@ -221,6 +216,8 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
221 if (!hctx->ccid3hctx_idle || 216 if (!hctx->ccid3hctx_idle ||
222 (hctx->ccid3hctx_x_recv >= 217 (hctx->ccid3hctx_x_recv >=
223 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) { 218 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
219 struct timeval now;
220
224 ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n", 221 ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
225 dccp_role(sk), sk, 222 dccp_role(sk), sk,
226 ccid3_tx_state_name(hctx->ccid3hctx_state)); 223 ccid3_tx_state_name(hctx->ccid3hctx_state));
@@ -238,12 +235,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
238 if (hctx->ccid3hctx_p < TFRC_SMALLEST_P || 235 if (hctx->ccid3hctx_p < TFRC_SMALLEST_P ||
239 hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) 236 hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv)
240 hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2, 237 hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2,
241 hctx->ccid3hctx_s / (2 * TFRC_MAX_BACK_OFF_TIME)); 238 hctx->ccid3hctx_s / (2 * TFRC_T_MBI));
242 else 239 else
243 hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4; 240 hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4;
244 241
245 /* Update sending rate */ 242 /* Update sending rate */
246 ccid3_hc_tx_update_x(sk); 243 dccp_timestamp(sk, &now);
244 ccid3_hc_tx_update_x(sk, &now);
247 } 245 }
248 /* 246 /*
249 * Schedule no feedback timer to expire in 247 * Schedule no feedback timer to expire in
@@ -473,11 +471,21 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
473 * q is a constant, RFC 3448 recomments 0.9 471 * q is a constant, RFC 3448 recomments 0.9
474 */ 472 */
475 if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { 473 if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {
474 /* Use Larger Initial Windows [RFC 4342, sec. 5]
475 * We deviate in that we use `s' instead of `MSS'. */
476 u16 w_init = max( 4 * hctx->ccid3hctx_s,
477 max(2 * hctx->ccid3hctx_s, 4380));
478 hctx->ccid3hctx_rtt = r_sample;
479 hctx->ccid3hctx_x = usecs_div(w_init, r_sample);
480 hctx->ccid3hctx_t_ld = now;
481
482 ccid3_update_send_time(hctx);
476 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); 483 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
477 hctx->ccid3hctx_rtt = r_sample; 484 } else {
478 } else
479 hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + 485 hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 +
480 r_sample / 10; 486 r_sample / 10;
487 ccid3_hc_tx_update_x(sk, &now);
488 }
481 489
482 ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " 490 ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, "
483 "r_sample=%us\n", dccp_role(sk), sk, 491 "r_sample=%us\n", dccp_role(sk), sk,
@@ -502,9 +510,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
502 /* unschedule no feedback timer */ 510 /* unschedule no feedback timer */
503 sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); 511 sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
504 512
505 /* Update sending rate (and likely t_ipi, t_nom, and delta) */
506 ccid3_hc_tx_update_x(sk);
507
508 /* remove all packets older than the one acked from history */ 513 /* remove all packets older than the one acked from history */
509 dccp_tx_hist_purge_older(ccid3_tx_hist, 514 dccp_tx_hist_purge_older(ccid3_tx_hist,
510 &hctx->ccid3hctx_hist, packet); 515 &hctx->ccid3hctx_hist, packet);
@@ -514,7 +519,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
514 */ 519 */
515 sk->sk_write_space(sk); 520 sk->sk_write_space(sk);
516 521
517
518 /* Update timeout interval. We use the alternative variant of 522 /* Update timeout interval. We use the alternative variant of
519 * [RFC 3448, 3.1] which sets the upper bound of t_rto to one 523 * [RFC 3448, 3.1] which sets the upper bound of t_rto to one
520 * second, as it is suggested for TCP (see RFC 2988, 2.4). */ 524 * second, as it is suggested for TCP (see RFC 2988, 2.4). */
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index dbb884426dfa..27cb20ae1da8 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -48,8 +48,8 @@
48/* In usecs - half the scheduling granularity as per RFC3448 4.6 */ 48/* In usecs - half the scheduling granularity as per RFC3448 4.6 */
49#define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ)) 49#define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ))
50 50
51/* In seconds */ 51/* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
52#define TFRC_MAX_BACK_OFF_TIME 64 52#define TFRC_T_MBI 64
53 53
54#define TFRC_SMALLEST_P 40 54#define TFRC_SMALLEST_P 40
55 55