diff options
Diffstat (limited to 'net/dccp/ccids')
-rw-r--r-- | net/dccp/ccids/ccid2.c | 12 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.c | 517 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.h | 46 | ||||
-rw-r--r-- | net/dccp/ccids/lib/packet_history.c | 219 | ||||
-rw-r--r-- | net/dccp/ccids/lib/packet_history.h | 128 | ||||
-rw-r--r-- | net/dccp/ccids/lib/tfrc.h | 23 | ||||
-rw-r--r-- | net/dccp/ccids/lib/tfrc_equation.c | 28 |
7 files changed, 514 insertions, 459 deletions
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 2555be8f479..fd38b05d6f7 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c | |||
@@ -351,7 +351,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) | |||
351 | 351 | ||
352 | while (seqp != hctx->ccid2hctx_seqh) { | 352 | while (seqp != hctx->ccid2hctx_seqh) { |
353 | ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n", | 353 | ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n", |
354 | (unsigned long long)seqp->ccid2s_seq, | 354 | (unsigned long long)seqp->ccid2s_seq, |
355 | seqp->ccid2s_acked, seqp->ccid2s_sent); | 355 | seqp->ccid2s_acked, seqp->ccid2s_sent); |
356 | seqp = seqp->ccid2s_next; | 356 | seqp = seqp->ccid2s_next; |
357 | } | 357 | } |
@@ -473,7 +473,7 @@ static inline void ccid2_new_ack(struct sock *sk, | |||
473 | /* first measurement */ | 473 | /* first measurement */ |
474 | if (hctx->ccid2hctx_srtt == -1) { | 474 | if (hctx->ccid2hctx_srtt == -1) { |
475 | ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", | 475 | ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", |
476 | r, jiffies, | 476 | r, jiffies, |
477 | (unsigned long long)seqp->ccid2s_seq); | 477 | (unsigned long long)seqp->ccid2s_seq); |
478 | ccid2_change_srtt(hctx, r); | 478 | ccid2_change_srtt(hctx, r); |
479 | hctx->ccid2hctx_rttvar = r >> 1; | 479 | hctx->ccid2hctx_rttvar = r >> 1; |
@@ -518,8 +518,8 @@ static inline void ccid2_new_ack(struct sock *sk, | |||
518 | hctx->ccid2hctx_lastrtt = jiffies; | 518 | hctx->ccid2hctx_lastrtt = jiffies; |
519 | 519 | ||
520 | ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n", | 520 | ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n", |
521 | hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar, | 521 | hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar, |
522 | hctx->ccid2hctx_rto, HZ, r); | 522 | hctx->ccid2hctx_rto, HZ, r); |
523 | hctx->ccid2hctx_sent = 0; | 523 | hctx->ccid2hctx_sent = 0; |
524 | } | 524 | } |
525 | 525 | ||
@@ -667,9 +667,9 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
667 | /* new packet received or marked */ | 667 | /* new packet received or marked */ |
668 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED && | 668 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED && |
669 | !seqp->ccid2s_acked) { | 669 | !seqp->ccid2s_acked) { |
670 | if (state == | 670 | if (state == |
671 | DCCP_ACKVEC_STATE_ECN_MARKED) { | 671 | DCCP_ACKVEC_STATE_ECN_MARKED) { |
672 | ccid2_congestion_event(hctx, | 672 | ccid2_congestion_event(hctx, |
673 | seqp); | 673 | seqp); |
674 | } else | 674 | } else |
675 | ccid2_new_ack(sk, seqp, | 675 | ccid2_new_ack(sk, seqp, |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 66a27b9688c..fa6b75372ed 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -41,27 +41,6 @@ | |||
41 | #include "lib/tfrc.h" | 41 | #include "lib/tfrc.h" |
42 | #include "ccid3.h" | 42 | #include "ccid3.h" |
43 | 43 | ||
44 | /* | ||
45 | * Reason for maths here is to avoid 32 bit overflow when a is big. | ||
46 | * With this we get close to the limit. | ||
47 | */ | ||
48 | static u32 usecs_div(const u32 a, const u32 b) | ||
49 | { | ||
50 | const u32 div = a < (UINT_MAX / (USEC_PER_SEC / 10)) ? 10 : | ||
51 | a < (UINT_MAX / (USEC_PER_SEC / 50)) ? 50 : | ||
52 | a < (UINT_MAX / (USEC_PER_SEC / 100)) ? 100 : | ||
53 | a < (UINT_MAX / (USEC_PER_SEC / 500)) ? 500 : | ||
54 | a < (UINT_MAX / (USEC_PER_SEC / 1000)) ? 1000 : | ||
55 | a < (UINT_MAX / (USEC_PER_SEC / 5000)) ? 5000 : | ||
56 | a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 : | ||
57 | a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 : | ||
58 | 100000; | ||
59 | const u32 tmp = a * (USEC_PER_SEC / div); | ||
60 | return (b >= 2 * div) ? tmp / (b / div) : tmp; | ||
61 | } | ||
62 | |||
63 | |||
64 | |||
65 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG | 44 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG |
66 | static int ccid3_debug; | 45 | static int ccid3_debug; |
67 | #define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) | 46 | #define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) |
@@ -108,8 +87,9 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) | |||
108 | { | 87 | { |
109 | timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); | 88 | timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); |
110 | 89 | ||
111 | /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ | 90 | /* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */ |
112 | hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x); | 91 | hctx->ccid3hctx_t_ipi = scaled_div(hctx->ccid3hctx_s, |
92 | hctx->ccid3hctx_x >> 6); | ||
113 | 93 | ||
114 | /* Update nominal send time with regard to the new t_ipi */ | 94 | /* Update nominal send time with regard to the new t_ipi */ |
115 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); | 95 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); |
@@ -128,40 +108,44 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) | |||
128 | * X = max(min(2 * X, 2 * X_recv), s / R); | 108 | * X = max(min(2 * X, 2 * X_recv), s / R); |
129 | * tld = now; | 109 | * tld = now; |
130 | * | 110 | * |
111 | * Note: X and X_recv are both stored in units of 64 * bytes/second, to support | ||
112 | * fine-grained resolution of sending rates. This requires scaling by 2^6 | ||
113 | * throughout the code. Only X_calc is unscaled (in bytes/second). | ||
114 | * | ||
131 | * If X has changed, we also update the scheduled send time t_now, | 115 | * If X has changed, we also update the scheduled send time t_now, |
132 | * the inter-packet interval t_ipi, and the delta value. | 116 | * the inter-packet interval t_ipi, and the delta value. |
133 | */ | 117 | */ |
134 | static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) | 118 | static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) |
135 | 119 | ||
136 | { | 120 | { |
137 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 121 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
138 | const __u32 old_x = hctx->ccid3hctx_x; | 122 | const __u64 old_x = hctx->ccid3hctx_x; |
139 | 123 | ||
140 | if (hctx->ccid3hctx_p > 0) { | 124 | if (hctx->ccid3hctx_p > 0) { |
141 | hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, | 125 | |
142 | hctx->ccid3hctx_rtt, | 126 | hctx->ccid3hctx_x = min(((__u64)hctx->ccid3hctx_x_calc) << 6, |
143 | hctx->ccid3hctx_p); | 127 | hctx->ccid3hctx_x_recv * 2); |
144 | hctx->ccid3hctx_x = max_t(u32, min(hctx->ccid3hctx_x_calc, | 128 | hctx->ccid3hctx_x = max(hctx->ccid3hctx_x, |
145 | hctx->ccid3hctx_x_recv * 2), | 129 | (((__u64)hctx->ccid3hctx_s) << 6) / |
146 | hctx->ccid3hctx_s / TFRC_T_MBI); | 130 | TFRC_T_MBI); |
147 | 131 | ||
148 | } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >= | 132 | } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) - |
149 | hctx->ccid3hctx_rtt) { | 133 | (suseconds_t)hctx->ccid3hctx_rtt >= 0) { |
150 | hctx->ccid3hctx_x = max(min(hctx->ccid3hctx_x_recv, | 134 | |
151 | hctx->ccid3hctx_x ) * 2, | 135 | hctx->ccid3hctx_x = |
152 | usecs_div(hctx->ccid3hctx_s, | 136 | max(2 * min(hctx->ccid3hctx_x, hctx->ccid3hctx_x_recv), |
153 | hctx->ccid3hctx_rtt) ); | 137 | scaled_div(((__u64)hctx->ccid3hctx_s) << 6, |
138 | hctx->ccid3hctx_rtt)); | ||
154 | hctx->ccid3hctx_t_ld = *now; | 139 | hctx->ccid3hctx_t_ld = *now; |
155 | } else | 140 | } |
156 | ccid3_pr_debug("Not changing X\n"); | ||
157 | 141 | ||
158 | if (hctx->ccid3hctx_x != old_x) | 142 | if (hctx->ccid3hctx_x != old_x) |
159 | ccid3_update_send_time(hctx); | 143 | ccid3_update_send_time(hctx); |
160 | } | 144 | } |
161 | 145 | ||
162 | /* | 146 | /* |
163 | * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1) | 147 | * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1) |
164 | * @len: DCCP packet payload size in bytes | 148 | * @len: DCCP packet payload size in bytes |
165 | */ | 149 | */ |
166 | static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len) | 150 | static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len) |
167 | { | 151 | { |
@@ -178,6 +162,33 @@ static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len) | |||
178 | */ | 162 | */ |
179 | } | 163 | } |
180 | 164 | ||
165 | /* | ||
166 | * Update Window Counter using the algorithm from [RFC 4342, 8.1]. | ||
167 | * The algorithm is not applicable if RTT < 4 microseconds. | ||
168 | */ | ||
169 | static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx, | ||
170 | struct timeval *now) | ||
171 | { | ||
172 | suseconds_t delta; | ||
173 | u32 quarter_rtts; | ||
174 | |||
175 | if (unlikely(hctx->ccid3hctx_rtt < 4)) /* avoid divide-by-zero */ | ||
176 | return; | ||
177 | |||
178 | delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count); | ||
179 | DCCP_BUG_ON(delta < 0); | ||
180 | |||
181 | quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4); | ||
182 | |||
183 | if (quarter_rtts > 0) { | ||
184 | hctx->ccid3hctx_t_last_win_count = *now; | ||
185 | hctx->ccid3hctx_last_win_count += min_t(u32, quarter_rtts, 5); | ||
186 | hctx->ccid3hctx_last_win_count &= 0xF; /* mod 16 */ | ||
187 | |||
188 | ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count); | ||
189 | } | ||
190 | } | ||
191 | |||
181 | static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | 192 | static void ccid3_hc_tx_no_feedback_timer(unsigned long data) |
182 | { | 193 | { |
183 | struct sock *sk = (struct sock *)data; | 194 | struct sock *sk = (struct sock *)data; |
@@ -191,20 +202,20 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
191 | goto restart_timer; | 202 | goto restart_timer; |
192 | } | 203 | } |
193 | 204 | ||
194 | ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk, | 205 | ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk, |
195 | ccid3_tx_state_name(hctx->ccid3hctx_state)); | 206 | ccid3_tx_state_name(hctx->ccid3hctx_state)); |
196 | 207 | ||
197 | switch (hctx->ccid3hctx_state) { | 208 | switch (hctx->ccid3hctx_state) { |
198 | case TFRC_SSTATE_NO_FBACK: | 209 | case TFRC_SSTATE_NO_FBACK: |
199 | /* RFC 3448, 4.4: Halve send rate directly */ | 210 | /* RFC 3448, 4.4: Halve send rate directly */ |
200 | hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2, | 211 | hctx->ccid3hctx_x = max(hctx->ccid3hctx_x / 2, |
201 | hctx->ccid3hctx_s / TFRC_T_MBI); | 212 | (((__u64)hctx->ccid3hctx_s) << 6) / |
213 | TFRC_T_MBI); | ||
202 | 214 | ||
203 | ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d " | 215 | ccid3_pr_debug("%s(%p, state=%s), updated tx rate to %u " |
204 | "bytes/s\n", | 216 | "bytes/s\n", dccp_role(sk), sk, |
205 | dccp_role(sk), sk, | ||
206 | ccid3_tx_state_name(hctx->ccid3hctx_state), | 217 | ccid3_tx_state_name(hctx->ccid3hctx_state), |
207 | hctx->ccid3hctx_x); | 218 | (unsigned)(hctx->ccid3hctx_x >> 6)); |
208 | /* The value of R is still undefined and so we can not recompute | 219 | /* The value of R is still undefined and so we can not recompute |
209 | * the timout value. Keep initial value as per [RFC 4342, 5]. */ | 220 | * the timout value. Keep initial value as per [RFC 4342, 5]. */ |
210 | t_nfb = TFRC_INITIAL_TIMEOUT; | 221 | t_nfb = TFRC_INITIAL_TIMEOUT; |
@@ -213,34 +224,46 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
213 | case TFRC_SSTATE_FBACK: | 224 | case TFRC_SSTATE_FBACK: |
214 | /* | 225 | /* |
215 | * Check if IDLE since last timeout and recv rate is less than | 226 | * Check if IDLE since last timeout and recv rate is less than |
216 | * 4 packets per RTT | 227 | * 4 packets (in units of 64*bytes/sec) per RTT |
217 | */ | 228 | */ |
218 | if (!hctx->ccid3hctx_idle || | 229 | if (!hctx->ccid3hctx_idle || |
219 | (hctx->ccid3hctx_x_recv >= | 230 | (hctx->ccid3hctx_x_recv >= 4 * |
220 | 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) { | 231 | scaled_div(((__u64)hctx->ccid3hctx_s) << 6, |
232 | hctx->ccid3hctx_rtt))) { | ||
221 | struct timeval now; | 233 | struct timeval now; |
222 | 234 | ||
223 | ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n", | 235 | ccid3_pr_debug("%s(%p, state=%s), not idle\n", |
224 | dccp_role(sk), sk, | 236 | dccp_role(sk), sk, |
225 | ccid3_tx_state_name(hctx->ccid3hctx_state)); | 237 | ccid3_tx_state_name(hctx->ccid3hctx_state)); |
226 | /* Halve sending rate */ | ||
227 | 238 | ||
228 | /* If (p == 0 || X_calc > 2 * X_recv) | 239 | /* |
240 | * Modify the cached value of X_recv [RFC 3448, 4.4] | ||
241 | * | ||
242 | * If (p == 0 || X_calc > 2 * X_recv) | ||
229 | * X_recv = max(X_recv / 2, s / (2 * t_mbi)); | 243 | * X_recv = max(X_recv / 2, s / (2 * t_mbi)); |
230 | * Else | 244 | * Else |
231 | * X_recv = X_calc / 4; | 245 | * X_recv = X_calc / 4; |
246 | * | ||
247 | * Note that X_recv is scaled by 2^6 while X_calc is not | ||
232 | */ | 248 | */ |
233 | BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc); | 249 | BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc); |
234 | 250 | ||
235 | if (hctx->ccid3hctx_p == 0 || | 251 | if (hctx->ccid3hctx_p == 0 || |
236 | hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) | 252 | (hctx->ccid3hctx_x_calc > |
237 | hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2, | 253 | (hctx->ccid3hctx_x_recv >> 5))) { |
238 | hctx->ccid3hctx_s / (2 * TFRC_T_MBI)); | 254 | |
239 | else | 255 | hctx->ccid3hctx_x_recv = |
240 | hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4; | 256 | max(hctx->ccid3hctx_x_recv / 2, |
241 | 257 | (((__u64)hctx->ccid3hctx_s) << 6) / | |
242 | /* Update sending rate */ | 258 | (2 * TFRC_T_MBI)); |
243 | dccp_timestamp(sk, &now); | 259 | |
260 | if (hctx->ccid3hctx_p == 0) | ||
261 | dccp_timestamp(sk, &now); | ||
262 | } else { | ||
263 | hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc; | ||
264 | hctx->ccid3hctx_x_recv <<= 4; | ||
265 | } | ||
266 | /* Now recalculate X [RFC 3448, 4.3, step (4)] */ | ||
244 | ccid3_hc_tx_update_x(sk, &now); | 267 | ccid3_hc_tx_update_x(sk, &now); |
245 | } | 268 | } |
246 | /* | 269 | /* |
@@ -251,7 +274,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
251 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); | 274 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); |
252 | break; | 275 | break; |
253 | case TFRC_SSTATE_NO_SENT: | 276 | case TFRC_SSTATE_NO_SENT: |
254 | DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); | 277 | DCCP_BUG("%s(%p) - Illegal state NO_SENT", dccp_role(sk), sk); |
255 | /* fall through */ | 278 | /* fall through */ |
256 | case TFRC_SSTATE_TERM: | 279 | case TFRC_SSTATE_TERM: |
257 | goto out; | 280 | goto out; |
@@ -277,9 +300,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
277 | { | 300 | { |
278 | struct dccp_sock *dp = dccp_sk(sk); | 301 | struct dccp_sock *dp = dccp_sk(sk); |
279 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 302 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
280 | struct dccp_tx_hist_entry *new_packet; | ||
281 | struct timeval now; | 303 | struct timeval now; |
282 | long delay; | 304 | suseconds_t delay; |
283 | 305 | ||
284 | BUG_ON(hctx == NULL); | 306 | BUG_ON(hctx == NULL); |
285 | 307 | ||
@@ -291,34 +313,21 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
291 | if (unlikely(skb->len == 0)) | 313 | if (unlikely(skb->len == 0)) |
292 | return -EBADMSG; | 314 | return -EBADMSG; |
293 | 315 | ||
294 | /* See if last packet allocated was not sent */ | ||
295 | new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); | ||
296 | if (new_packet == NULL || new_packet->dccphtx_sent) { | ||
297 | new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist, | ||
298 | GFP_ATOMIC); | ||
299 | |||
300 | if (unlikely(new_packet == NULL)) { | ||
301 | DCCP_WARN("%s, sk=%p, not enough mem to add to history," | ||
302 | "send refused\n", dccp_role(sk), sk); | ||
303 | return -ENOBUFS; | ||
304 | } | ||
305 | |||
306 | dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet); | ||
307 | } | ||
308 | |||
309 | dccp_timestamp(sk, &now); | 316 | dccp_timestamp(sk, &now); |
310 | 317 | ||
311 | switch (hctx->ccid3hctx_state) { | 318 | switch (hctx->ccid3hctx_state) { |
312 | case TFRC_SSTATE_NO_SENT: | 319 | case TFRC_SSTATE_NO_SENT: |
313 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, | 320 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, |
314 | jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)); | 321 | (jiffies + |
322 | usecs_to_jiffies(TFRC_INITIAL_TIMEOUT))); | ||
315 | hctx->ccid3hctx_last_win_count = 0; | 323 | hctx->ccid3hctx_last_win_count = 0; |
316 | hctx->ccid3hctx_t_last_win_count = now; | 324 | hctx->ccid3hctx_t_last_win_count = now; |
317 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); | 325 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); |
318 | 326 | ||
319 | /* Set initial sending rate to 1 packet per second */ | 327 | /* Set initial sending rate X/s to 1pps (X is scaled by 2^6) */ |
320 | ccid3_hc_tx_update_s(hctx, skb->len); | 328 | ccid3_hc_tx_update_s(hctx, skb->len); |
321 | hctx->ccid3hctx_x = hctx->ccid3hctx_s; | 329 | hctx->ccid3hctx_x = hctx->ccid3hctx_s; |
330 | hctx->ccid3hctx_x <<= 6; | ||
322 | 331 | ||
323 | /* First timeout, according to [RFC 3448, 4.2], is 1 second */ | 332 | /* First timeout, according to [RFC 3448, 4.2], is 1 second */ |
324 | hctx->ccid3hctx_t_ipi = USEC_PER_SEC; | 333 | hctx->ccid3hctx_t_ipi = USEC_PER_SEC; |
@@ -332,77 +341,57 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
332 | case TFRC_SSTATE_FBACK: | 341 | case TFRC_SSTATE_FBACK: |
333 | delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now); | 342 | delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now); |
334 | /* | 343 | /* |
335 | * Scheduling of packet transmissions [RFC 3448, 4.6] | 344 | * Scheduling of packet transmissions [RFC 3448, 4.6] |
336 | * | 345 | * |
337 | * if (t_now > t_nom - delta) | 346 | * if (t_now > t_nom - delta) |
338 | * // send the packet now | 347 | * // send the packet now |
339 | * else | 348 | * else |
340 | * // send the packet in (t_nom - t_now) milliseconds. | 349 | * // send the packet in (t_nom - t_now) milliseconds. |
341 | */ | 350 | */ |
342 | if (delay - (long)hctx->ccid3hctx_delta >= 0) | 351 | if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0) |
343 | return delay / 1000L; | 352 | return delay / 1000L; |
353 | |||
354 | ccid3_hc_tx_update_win_count(hctx, &now); | ||
344 | break; | 355 | break; |
345 | case TFRC_SSTATE_TERM: | 356 | case TFRC_SSTATE_TERM: |
346 | DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); | 357 | DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk); |
347 | return -EINVAL; | 358 | return -EINVAL; |
348 | } | 359 | } |
349 | 360 | ||
350 | /* prepare to send now (add options etc.) */ | 361 | /* prepare to send now (add options etc.) */ |
351 | dp->dccps_hc_tx_insert_options = 1; | 362 | dp->dccps_hc_tx_insert_options = 1; |
352 | new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval = | 363 | DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count; |
353 | hctx->ccid3hctx_last_win_count; | 364 | |
365 | /* set the nominal send time for the next following packet */ | ||
354 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); | 366 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); |
355 | 367 | ||
356 | return 0; | 368 | return 0; |
357 | } | 369 | } |
358 | 370 | ||
359 | static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) | 371 | static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, |
372 | unsigned int len) | ||
360 | { | 373 | { |
361 | const struct dccp_sock *dp = dccp_sk(sk); | ||
362 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 374 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
363 | struct timeval now; | 375 | struct timeval now; |
364 | unsigned long quarter_rtt; | ||
365 | struct dccp_tx_hist_entry *packet; | 376 | struct dccp_tx_hist_entry *packet; |
366 | 377 | ||
367 | BUG_ON(hctx == NULL); | 378 | BUG_ON(hctx == NULL); |
368 | 379 | ||
369 | dccp_timestamp(sk, &now); | ||
370 | |||
371 | ccid3_hc_tx_update_s(hctx, len); | 380 | ccid3_hc_tx_update_s(hctx, len); |
372 | 381 | ||
373 | packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); | 382 | packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC); |
374 | if (unlikely(packet == NULL)) { | 383 | if (unlikely(packet == NULL)) { |
375 | DCCP_WARN("packet doesn't exist in history!\n"); | 384 | DCCP_CRIT("packet history - out of memory!"); |
376 | return; | ||
377 | } | ||
378 | if (unlikely(packet->dccphtx_sent)) { | ||
379 | DCCP_WARN("no unsent packet in history!\n"); | ||
380 | return; | 385 | return; |
381 | } | 386 | } |
382 | packet->dccphtx_tstamp = now; | 387 | dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet); |
383 | packet->dccphtx_seqno = dp->dccps_gss; | ||
384 | /* | ||
385 | * Check if win_count have changed | ||
386 | * Algorithm in "8.1. Window Counter Value" in RFC 4342. | ||
387 | */ | ||
388 | quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count); | ||
389 | if (likely(hctx->ccid3hctx_rtt > 8)) | ||
390 | quarter_rtt /= hctx->ccid3hctx_rtt / 4; | ||
391 | |||
392 | if (quarter_rtt > 0) { | ||
393 | hctx->ccid3hctx_t_last_win_count = now; | ||
394 | hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + | ||
395 | min_t(unsigned long, quarter_rtt, 5)) % 16; | ||
396 | ccid3_pr_debug("%s, sk=%p, window changed from " | ||
397 | "%u to %u!\n", | ||
398 | dccp_role(sk), sk, | ||
399 | packet->dccphtx_ccval, | ||
400 | hctx->ccid3hctx_last_win_count); | ||
401 | } | ||
402 | 388 | ||
403 | hctx->ccid3hctx_idle = 0; | 389 | dccp_timestamp(sk, &now); |
404 | packet->dccphtx_rtt = hctx->ccid3hctx_rtt; | 390 | packet->dccphtx_tstamp = now; |
405 | packet->dccphtx_sent = 1; | 391 | packet->dccphtx_seqno = dccp_sk(sk)->dccps_gss; |
392 | packet->dccphtx_rtt = hctx->ccid3hctx_rtt; | ||
393 | packet->dccphtx_sent = 1; | ||
394 | hctx->ccid3hctx_idle = 0; | ||
406 | } | 395 | } |
407 | 396 | ||
408 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | 397 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) |
@@ -414,7 +403,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
414 | struct timeval now; | 403 | struct timeval now; |
415 | unsigned long t_nfb; | 404 | unsigned long t_nfb; |
416 | u32 pinv; | 405 | u32 pinv; |
417 | long r_sample, t_elapsed; | 406 | suseconds_t r_sample, t_elapsed; |
418 | 407 | ||
419 | BUG_ON(hctx == NULL); | 408 | BUG_ON(hctx == NULL); |
420 | 409 | ||
@@ -430,44 +419,44 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
430 | case TFRC_SSTATE_FBACK: | 419 | case TFRC_SSTATE_FBACK: |
431 | /* get packet from history to look up t_recvdata */ | 420 | /* get packet from history to look up t_recvdata */ |
432 | packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, | 421 | packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, |
433 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 422 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
434 | if (unlikely(packet == NULL)) { | 423 | if (unlikely(packet == NULL)) { |
435 | DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist " | 424 | DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist " |
436 | "in history!\n", dccp_role(sk), sk, | 425 | "in history!\n", dccp_role(sk), sk, |
437 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, | 426 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, |
438 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); | 427 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); |
439 | return; | 428 | return; |
440 | } | 429 | } |
441 | 430 | ||
442 | /* Update receive rate */ | 431 | /* Update receive rate in units of 64 * bytes/second */ |
443 | hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate; | 432 | hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate; |
433 | hctx->ccid3hctx_x_recv <<= 6; | ||
444 | 434 | ||
445 | /* Update loss event rate */ | 435 | /* Update loss event rate */ |
446 | pinv = opt_recv->ccid3or_loss_event_rate; | 436 | pinv = opt_recv->ccid3or_loss_event_rate; |
447 | if (pinv == ~0U || pinv == 0) | 437 | if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */ |
448 | hctx->ccid3hctx_p = 0; | 438 | hctx->ccid3hctx_p = 0; |
449 | else | 439 | else /* can not exceed 100% */ |
450 | hctx->ccid3hctx_p = 1000000 / pinv; | 440 | hctx->ccid3hctx_p = 1000000 / pinv; |
451 | 441 | ||
452 | dccp_timestamp(sk, &now); | 442 | dccp_timestamp(sk, &now); |
453 | 443 | ||
454 | /* | 444 | /* |
455 | * Calculate new round trip sample as per [RFC 3448, 4.3] by | 445 | * Calculate new round trip sample as per [RFC 3448, 4.3] by |
456 | * R_sample = (now - t_recvdata) - t_elapsed | 446 | * R_sample = (now - t_recvdata) - t_elapsed |
457 | */ | 447 | */ |
458 | r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); | 448 | r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); |
459 | t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10; | 449 | t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10; |
460 | 450 | ||
461 | if (unlikely(r_sample <= 0)) { | 451 | DCCP_BUG_ON(r_sample < 0); |
462 | DCCP_WARN("WARNING: R_sample (%ld) <= 0!\n", r_sample); | 452 | if (unlikely(r_sample <= t_elapsed)) |
463 | r_sample = 0; | 453 | DCCP_WARN("WARNING: r_sample=%dus <= t_elapsed=%dus\n", |
464 | } else if (unlikely(r_sample <= t_elapsed)) | 454 | (int)r_sample, (int)t_elapsed); |
465 | DCCP_WARN("WARNING: r_sample=%ldus <= t_elapsed=%ldus\n", | ||
466 | r_sample, t_elapsed); | ||
467 | else | 455 | else |
468 | r_sample -= t_elapsed; | 456 | r_sample -= t_elapsed; |
457 | CCID3_RTT_SANITY_CHECK(r_sample); | ||
469 | 458 | ||
470 | /* Update RTT estimate by | 459 | /* Update RTT estimate by |
471 | * If (No feedback recv) | 460 | * If (No feedback recv) |
472 | * R = R_sample; | 461 | * R = R_sample; |
473 | * Else | 462 | * Else |
@@ -476,34 +465,45 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
476 | * q is a constant, RFC 3448 recomments 0.9 | 465 | * q is a constant, RFC 3448 recomments 0.9 |
477 | */ | 466 | */ |
478 | if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { | 467 | if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { |
479 | /* Use Larger Initial Windows [RFC 4342, sec. 5] | 468 | /* |
480 | * We deviate in that we use `s' instead of `MSS'. */ | 469 | * Larger Initial Windows [RFC 4342, sec. 5] |
481 | u16 w_init = max( 4 * hctx->ccid3hctx_s, | 470 | * We deviate in that we use `s' instead of `MSS'. |
482 | max(2 * hctx->ccid3hctx_s, 4380)); | 471 | */ |
472 | __u64 w_init = min(4 * hctx->ccid3hctx_s, | ||
473 | max(2 * hctx->ccid3hctx_s, 4380)); | ||
483 | hctx->ccid3hctx_rtt = r_sample; | 474 | hctx->ccid3hctx_rtt = r_sample; |
484 | hctx->ccid3hctx_x = usecs_div(w_init, r_sample); | 475 | hctx->ccid3hctx_x = scaled_div(w_init << 6, r_sample); |
485 | hctx->ccid3hctx_t_ld = now; | 476 | hctx->ccid3hctx_t_ld = now; |
486 | 477 | ||
487 | ccid3_update_send_time(hctx); | 478 | ccid3_update_send_time(hctx); |
488 | 479 | ||
489 | ccid3_pr_debug("%s(%p), s=%u, w_init=%u, " | 480 | ccid3_pr_debug("%s(%p), s=%u, w_init=%llu, " |
490 | "R_sample=%ldus, X=%u\n", dccp_role(sk), | 481 | "R_sample=%dus, X=%u\n", dccp_role(sk), |
491 | sk, hctx->ccid3hctx_s, w_init, r_sample, | 482 | sk, hctx->ccid3hctx_s, w_init, |
492 | hctx->ccid3hctx_x); | 483 | (int)r_sample, |
484 | (unsigned)(hctx->ccid3hctx_x >> 6)); | ||
493 | 485 | ||
494 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); | 486 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); |
495 | } else { | 487 | } else { |
496 | hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt + | 488 | hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt + |
497 | (u32)r_sample ) / 10; | 489 | (u32)r_sample) / 10; |
498 | 490 | ||
491 | /* Update sending rate (step 4 of [RFC 3448, 4.3]) */ | ||
492 | if (hctx->ccid3hctx_p > 0) | ||
493 | hctx->ccid3hctx_x_calc = | ||
494 | tfrc_calc_x(hctx->ccid3hctx_s, | ||
495 | hctx->ccid3hctx_rtt, | ||
496 | hctx->ccid3hctx_p); | ||
499 | ccid3_hc_tx_update_x(sk, &now); | 497 | ccid3_hc_tx_update_x(sk, &now); |
500 | 498 | ||
501 | ccid3_pr_debug("%s(%p), RTT=%uus (sample=%ldus), s=%u, " | 499 | ccid3_pr_debug("%s(%p), RTT=%uus (sample=%dus), s=%u, " |
502 | "p=%u, X_calc=%u, X=%u\n", dccp_role(sk), | 500 | "p=%u, X_calc=%u, X_recv=%u, X=%u\n", |
503 | sk, hctx->ccid3hctx_rtt, r_sample, | 501 | dccp_role(sk), |
502 | sk, hctx->ccid3hctx_rtt, (int)r_sample, | ||
504 | hctx->ccid3hctx_s, hctx->ccid3hctx_p, | 503 | hctx->ccid3hctx_s, hctx->ccid3hctx_p, |
505 | hctx->ccid3hctx_x_calc, | 504 | hctx->ccid3hctx_x_calc, |
506 | hctx->ccid3hctx_x); | 505 | (unsigned)(hctx->ccid3hctx_x_recv >> 6), |
506 | (unsigned)(hctx->ccid3hctx_x >> 6)); | ||
507 | } | 507 | } |
508 | 508 | ||
509 | /* unschedule no feedback timer */ | 509 | /* unschedule no feedback timer */ |
@@ -513,57 +513,48 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
513 | dccp_tx_hist_purge_older(ccid3_tx_hist, | 513 | dccp_tx_hist_purge_older(ccid3_tx_hist, |
514 | &hctx->ccid3hctx_hist, packet); | 514 | &hctx->ccid3hctx_hist, packet); |
515 | /* | 515 | /* |
516 | * As we have calculated new ipi, delta, t_nom it is possible that | 516 | * As we have calculated new ipi, delta, t_nom it is possible |
517 | * we now can send a packet, so wake up dccp_wait_for_ccid | 517 | * that we now can send a packet, so wake up dccp_wait_for_ccid |
518 | */ | 518 | */ |
519 | sk->sk_write_space(sk); | 519 | sk->sk_write_space(sk); |
520 | 520 | ||
521 | /* | 521 | /* |
522 | * Update timeout interval for the nofeedback timer. | 522 | * Update timeout interval for the nofeedback timer. |
523 | * We use a configuration option to increase the lower bound. | 523 | * We use a configuration option to increase the lower bound. |
524 | * This can help avoid triggering the nofeedback timer too often | 524 | * This can help avoid triggering the nofeedback timer too |
525 | * ('spinning') on LANs with small RTTs. | 525 | * often ('spinning') on LANs with small RTTs. |
526 | */ | 526 | */ |
527 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, | 527 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, |
528 | CONFIG_IP_DCCP_CCID3_RTO * | 528 | CONFIG_IP_DCCP_CCID3_RTO * |
529 | (USEC_PER_SEC/1000) ); | 529 | (USEC_PER_SEC/1000)); |
530 | /* | 530 | /* |
531 | * Schedule no feedback timer to expire in | 531 | * Schedule no feedback timer to expire in |
532 | * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) | 532 | * max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi) |
533 | */ | 533 | */ |
534 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); | 534 | t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi); |
535 | 535 | ||
536 | ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " | 536 | ccid3_pr_debug("%s(%p), Scheduled no feedback timer to " |
537 | "expire in %lu jiffies (%luus)\n", | 537 | "expire in %lu jiffies (%luus)\n", |
538 | dccp_role(sk), sk, | 538 | dccp_role(sk), |
539 | usecs_to_jiffies(t_nfb), t_nfb); | 539 | sk, usecs_to_jiffies(t_nfb), t_nfb); |
540 | 540 | ||
541 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, | 541 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, |
542 | jiffies + usecs_to_jiffies(t_nfb)); | 542 | jiffies + usecs_to_jiffies(t_nfb)); |
543 | 543 | ||
544 | /* set idle flag */ | 544 | /* set idle flag */ |
545 | hctx->ccid3hctx_idle = 1; | 545 | hctx->ccid3hctx_idle = 1; |
546 | break; | 546 | break; |
547 | case TFRC_SSTATE_NO_SENT: | 547 | case TFRC_SSTATE_NO_SENT: |
548 | if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT) | 548 | /* |
549 | DCCP_WARN("Illegal ACK received - no packet sent\n"); | 549 | * XXX when implementing bidirectional rx/tx check this again |
550 | */ | ||
551 | DCCP_WARN("Illegal ACK received - no packet sent\n"); | ||
550 | /* fall through */ | 552 | /* fall through */ |
551 | case TFRC_SSTATE_TERM: /* ignore feedback when closing */ | 553 | case TFRC_SSTATE_TERM: /* ignore feedback when closing */ |
552 | break; | 554 | break; |
553 | } | 555 | } |
554 | } | 556 | } |
555 | 557 | ||
556 | static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb) | ||
557 | { | ||
558 | const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | ||
559 | |||
560 | BUG_ON(hctx == NULL); | ||
561 | |||
562 | if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN) | ||
563 | DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count; | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | 558 | static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, |
568 | unsigned char len, u16 idx, | 559 | unsigned char len, u16 idx, |
569 | unsigned char *value) | 560 | unsigned char *value) |
@@ -588,13 +579,14 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
588 | switch (option) { | 579 | switch (option) { |
589 | case TFRC_OPT_LOSS_EVENT_RATE: | 580 | case TFRC_OPT_LOSS_EVENT_RATE: |
590 | if (unlikely(len != 4)) { | 581 | if (unlikely(len != 4)) { |
591 | DCCP_WARN("%s, sk=%p, invalid len %d " | 582 | DCCP_WARN("%s(%p), invalid len %d " |
592 | "for TFRC_OPT_LOSS_EVENT_RATE\n", | 583 | "for TFRC_OPT_LOSS_EVENT_RATE\n", |
593 | dccp_role(sk), sk, len); | 584 | dccp_role(sk), sk, len); |
594 | rc = -EINVAL; | 585 | rc = -EINVAL; |
595 | } else { | 586 | } else { |
596 | opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value); | 587 | opt_recv->ccid3or_loss_event_rate = |
597 | ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n", | 588 | ntohl(*(__be32 *)value); |
589 | ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", | ||
598 | dccp_role(sk), sk, | 590 | dccp_role(sk), sk, |
599 | opt_recv->ccid3or_loss_event_rate); | 591 | opt_recv->ccid3or_loss_event_rate); |
600 | } | 592 | } |
@@ -602,20 +594,21 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
602 | case TFRC_OPT_LOSS_INTERVALS: | 594 | case TFRC_OPT_LOSS_INTERVALS: |
603 | opt_recv->ccid3or_loss_intervals_idx = idx; | 595 | opt_recv->ccid3or_loss_intervals_idx = idx; |
604 | opt_recv->ccid3or_loss_intervals_len = len; | 596 | opt_recv->ccid3or_loss_intervals_len = len; |
605 | ccid3_pr_debug("%s, sk=%p, LOSS_INTERVALS=(%u, %u)\n", | 597 | ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n", |
606 | dccp_role(sk), sk, | 598 | dccp_role(sk), sk, |
607 | opt_recv->ccid3or_loss_intervals_idx, | 599 | opt_recv->ccid3or_loss_intervals_idx, |
608 | opt_recv->ccid3or_loss_intervals_len); | 600 | opt_recv->ccid3or_loss_intervals_len); |
609 | break; | 601 | break; |
610 | case TFRC_OPT_RECEIVE_RATE: | 602 | case TFRC_OPT_RECEIVE_RATE: |
611 | if (unlikely(len != 4)) { | 603 | if (unlikely(len != 4)) { |
612 | DCCP_WARN("%s, sk=%p, invalid len %d " | 604 | DCCP_WARN("%s(%p), invalid len %d " |
613 | "for TFRC_OPT_RECEIVE_RATE\n", | 605 | "for TFRC_OPT_RECEIVE_RATE\n", |
614 | dccp_role(sk), sk, len); | 606 | dccp_role(sk), sk, len); |
615 | rc = -EINVAL; | 607 | rc = -EINVAL; |
616 | } else { | 608 | } else { |
617 | opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value); | 609 | opt_recv->ccid3or_receive_rate = |
618 | ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n", | 610 | ntohl(*(__be32 *)value); |
611 | ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", | ||
619 | dccp_role(sk), sk, | 612 | dccp_role(sk), sk, |
620 | opt_recv->ccid3or_receive_rate); | 613 | opt_recv->ccid3or_receive_rate); |
621 | } | 614 | } |
@@ -630,10 +623,12 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) | |||
630 | struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); | 623 | struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); |
631 | 624 | ||
632 | hctx->ccid3hctx_s = 0; | 625 | hctx->ccid3hctx_s = 0; |
626 | hctx->ccid3hctx_rtt = 0; | ||
633 | hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; | 627 | hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; |
634 | INIT_LIST_HEAD(&hctx->ccid3hctx_hist); | 628 | INIT_LIST_HEAD(&hctx->ccid3hctx_hist); |
635 | 629 | ||
636 | hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer; | 630 | hctx->ccid3hctx_no_feedback_timer.function = |
631 | ccid3_hc_tx_no_feedback_timer; | ||
637 | hctx->ccid3hctx_no_feedback_timer.data = (unsigned long)sk; | 632 | hctx->ccid3hctx_no_feedback_timer.data = (unsigned long)sk; |
638 | init_timer(&hctx->ccid3hctx_no_feedback_timer); | 633 | init_timer(&hctx->ccid3hctx_no_feedback_timer); |
639 | 634 | ||
@@ -698,8 +693,9 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) | |||
698 | struct dccp_sock *dp = dccp_sk(sk); | 693 | struct dccp_sock *dp = dccp_sk(sk); |
699 | struct dccp_rx_hist_entry *packet; | 694 | struct dccp_rx_hist_entry *packet; |
700 | struct timeval now; | 695 | struct timeval now; |
696 | suseconds_t delta; | ||
701 | 697 | ||
702 | ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); | 698 | ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk); |
703 | 699 | ||
704 | dccp_timestamp(sk, &now); | 700 | dccp_timestamp(sk, &now); |
705 | 701 | ||
@@ -707,21 +703,21 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) | |||
707 | case TFRC_RSTATE_NO_DATA: | 703 | case TFRC_RSTATE_NO_DATA: |
708 | hcrx->ccid3hcrx_x_recv = 0; | 704 | hcrx->ccid3hcrx_x_recv = 0; |
709 | break; | 705 | break; |
710 | case TFRC_RSTATE_DATA: { | 706 | case TFRC_RSTATE_DATA: |
711 | const u32 delta = timeval_delta(&now, | 707 | delta = timeval_delta(&now, |
712 | &hcrx->ccid3hcrx_tstamp_last_feedback); | 708 | &hcrx->ccid3hcrx_tstamp_last_feedback); |
713 | hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, | 709 | DCCP_BUG_ON(delta < 0); |
714 | delta); | 710 | hcrx->ccid3hcrx_x_recv = |
715 | } | 711 | scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta); |
716 | break; | 712 | break; |
717 | case TFRC_RSTATE_TERM: | 713 | case TFRC_RSTATE_TERM: |
718 | DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); | 714 | DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk); |
719 | return; | 715 | return; |
720 | } | 716 | } |
721 | 717 | ||
722 | packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist); | 718 | packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist); |
723 | if (unlikely(packet == NULL)) { | 719 | if (unlikely(packet == NULL)) { |
724 | DCCP_WARN("%s, sk=%p, no data packet in history!\n", | 720 | DCCP_WARN("%s(%p), no data packet in history!\n", |
725 | dccp_role(sk), sk); | 721 | dccp_role(sk), sk); |
726 | return; | 722 | return; |
727 | } | 723 | } |
@@ -730,13 +726,19 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) | |||
730 | hcrx->ccid3hcrx_ccval_last_counter = packet->dccphrx_ccval; | 726 | hcrx->ccid3hcrx_ccval_last_counter = packet->dccphrx_ccval; |
731 | hcrx->ccid3hcrx_bytes_recv = 0; | 727 | hcrx->ccid3hcrx_bytes_recv = 0; |
732 | 728 | ||
733 | /* Convert to multiples of 10us */ | 729 | /* Elapsed time information [RFC 4340, 13.2] in units of 10 * usecs */ |
734 | hcrx->ccid3hcrx_elapsed_time = | 730 | delta = timeval_delta(&now, &packet->dccphrx_tstamp); |
735 | timeval_delta(&now, &packet->dccphrx_tstamp) / 10; | 731 | DCCP_BUG_ON(delta < 0); |
732 | hcrx->ccid3hcrx_elapsed_time = delta / 10; | ||
733 | |||
736 | if (hcrx->ccid3hcrx_p == 0) | 734 | if (hcrx->ccid3hcrx_p == 0) |
737 | hcrx->ccid3hcrx_pinv = ~0; | 735 | hcrx->ccid3hcrx_pinv = ~0U; /* see RFC 4342, 8.5 */ |
738 | else | 736 | else if (hcrx->ccid3hcrx_p > 1000000) { |
737 | DCCP_WARN("p (%u) > 100%%\n", hcrx->ccid3hcrx_p); | ||
738 | hcrx->ccid3hcrx_pinv = 1; /* use 100% in this case */ | ||
739 | } else | ||
739 | hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p; | 740 | hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p; |
741 | |||
740 | dp->dccps_hc_rx_insert_options = 1; | 742 | dp->dccps_hc_rx_insert_options = 1; |
741 | dccp_send_ack(sk); | 743 | dccp_send_ack(sk); |
742 | } | 744 | } |
@@ -764,9 +766,9 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) | |||
764 | hcrx->ccid3hcrx_elapsed_time)) || | 766 | hcrx->ccid3hcrx_elapsed_time)) || |
765 | dccp_insert_option_timestamp(sk, skb) || | 767 | dccp_insert_option_timestamp(sk, skb) || |
766 | dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE, | 768 | dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE, |
767 | &pinv, sizeof(pinv)) || | 769 | &pinv, sizeof(pinv)) || |
768 | dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE, | 770 | dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE, |
769 | &x_recv, sizeof(x_recv))) | 771 | &x_recv, sizeof(x_recv))) |
770 | return -1; | 772 | return -1; |
771 | 773 | ||
772 | return 0; | 774 | return 0; |
@@ -780,12 +782,13 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) | |||
780 | { | 782 | { |
781 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | 783 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); |
782 | struct dccp_rx_hist_entry *entry, *next, *tail = NULL; | 784 | struct dccp_rx_hist_entry *entry, *next, *tail = NULL; |
783 | u32 rtt, delta, x_recv, fval, p, tmp2; | 785 | u32 x_recv, p; |
786 | suseconds_t rtt, delta; | ||
784 | struct timeval tstamp = { 0, }; | 787 | struct timeval tstamp = { 0, }; |
785 | int interval = 0; | 788 | int interval = 0; |
786 | int win_count = 0; | 789 | int win_count = 0; |
787 | int step = 0; | 790 | int step = 0; |
788 | u64 tmp1; | 791 | u64 fval; |
789 | 792 | ||
790 | list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, | 793 | list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, |
791 | dccphrx_node) { | 794 | dccphrx_node) { |
@@ -810,13 +813,13 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) | |||
810 | } | 813 | } |
811 | 814 | ||
812 | if (unlikely(step == 0)) { | 815 | if (unlikely(step == 0)) { |
813 | DCCP_WARN("%s, sk=%p, packet history has no data packets!\n", | 816 | DCCP_WARN("%s(%p), packet history has no data packets!\n", |
814 | dccp_role(sk), sk); | 817 | dccp_role(sk), sk); |
815 | return ~0; | 818 | return ~0; |
816 | } | 819 | } |
817 | 820 | ||
818 | if (unlikely(interval == 0)) { | 821 | if (unlikely(interval == 0)) { |
819 | DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0." | 822 | DCCP_WARN("%s(%p), Could not find a win_count interval > 0." |
820 | "Defaulting to 1\n", dccp_role(sk), sk); | 823 | "Defaulting to 1\n", dccp_role(sk), sk); |
821 | interval = 1; | 824 | interval = 1; |
822 | } | 825 | } |
@@ -825,41 +828,51 @@ found: | |||
825 | DCCP_CRIT("tail is null\n"); | 828 | DCCP_CRIT("tail is null\n"); |
826 | return ~0; | 829 | return ~0; |
827 | } | 830 | } |
828 | rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; | ||
829 | ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", | ||
830 | dccp_role(sk), sk, rtt); | ||
831 | 831 | ||
832 | if (rtt == 0) { | 832 | delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp); |
833 | DCCP_WARN("RTT==0, setting to 1\n"); | 833 | DCCP_BUG_ON(delta < 0); |
834 | rtt = 1; | 834 | |
835 | rtt = delta * 4 / interval; | ||
836 | ccid3_pr_debug("%s(%p), approximated RTT to %dus\n", | ||
837 | dccp_role(sk), sk, (int)rtt); | ||
838 | |||
839 | /* | ||
840 | * Determine the length of the first loss interval via inverse lookup. | ||
841 | * Assume that X_recv can be computed by the throughput equation | ||
842 | * s | ||
843 | * X_recv = -------- | ||
844 | * R * fval | ||
845 | * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1]. | ||
846 | */ | ||
847 | if (rtt == 0) { /* would result in divide-by-zero */ | ||
848 | DCCP_WARN("RTT==0, returning 1/p = 1\n"); | ||
849 | return 1000000; | ||
835 | } | 850 | } |
836 | 851 | ||
837 | dccp_timestamp(sk, &tstamp); | 852 | dccp_timestamp(sk, &tstamp); |
838 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); | 853 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); |
839 | x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta); | 854 | DCCP_BUG_ON(delta <= 0); |
840 | 855 | ||
841 | if (x_recv == 0) | 856 | x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta); |
842 | x_recv = hcrx->ccid3hcrx_x_recv; | 857 | if (x_recv == 0) { /* would also trigger divide-by-zero */ |
843 | 858 | DCCP_WARN("X_recv==0\n"); | |
844 | tmp1 = (u64)x_recv * (u64)rtt; | 859 | if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) { |
845 | do_div(tmp1,10000000); | 860 | DCCP_BUG("stored value of X_recv is zero"); |
846 | tmp2 = (u32)tmp1; | 861 | return 1000000; |
847 | 862 | } | |
848 | if (!tmp2) { | ||
849 | DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt); | ||
850 | return ~0; | ||
851 | } | 863 | } |
852 | 864 | ||
853 | fval = (hcrx->ccid3hcrx_s * 100000) / tmp2; | 865 | fval = scaled_div(hcrx->ccid3hcrx_s, rtt); |
854 | /* do not alter order above or you will get overflow on 32 bit */ | 866 | fval = scaled_div32(fval, x_recv); |
855 | p = tfrc_calc_x_reverse_lookup(fval); | 867 | p = tfrc_calc_x_reverse_lookup(fval); |
856 | ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied " | 868 | |
869 | ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied " | ||
857 | "loss rate=%u\n", dccp_role(sk), sk, x_recv, p); | 870 | "loss rate=%u\n", dccp_role(sk), sk, x_recv, p); |
858 | 871 | ||
859 | if (p == 0) | 872 | if (p == 0) |
860 | return ~0; | 873 | return ~0; |
861 | else | 874 | else |
862 | return 1000000 / p; | 875 | return 1000000 / p; |
863 | } | 876 | } |
864 | 877 | ||
865 | static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) | 878 | static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) |
@@ -913,7 +926,8 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk, | |||
913 | struct dccp_rx_hist_entry *packet) | 926 | struct dccp_rx_hist_entry *packet) |
914 | { | 927 | { |
915 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | 928 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); |
916 | struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist); | 929 | struct dccp_rx_hist_entry *rx_hist = |
930 | dccp_rx_hist_head(&hcrx->ccid3hcrx_hist); | ||
917 | u64 seqno = packet->dccphrx_seqno; | 931 | u64 seqno = packet->dccphrx_seqno; |
918 | u64 tmp_seqno; | 932 | u64 tmp_seqno; |
919 | int loss = 0; | 933 | int loss = 0; |
@@ -941,7 +955,7 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk, | |||
941 | dccp_inc_seqno(&tmp_seqno); | 955 | dccp_inc_seqno(&tmp_seqno); |
942 | while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist, | 956 | while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist, |
943 | tmp_seqno, &ccval)) { | 957 | tmp_seqno, &ccval)) { |
944 | hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; | 958 | hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; |
945 | hcrx->ccid3hcrx_ccval_nonloss = ccval; | 959 | hcrx->ccid3hcrx_ccval_nonloss = ccval; |
946 | dccp_inc_seqno(&tmp_seqno); | 960 | dccp_inc_seqno(&tmp_seqno); |
947 | } | 961 | } |
@@ -967,7 +981,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
967 | const struct dccp_options_received *opt_recv; | 981 | const struct dccp_options_received *opt_recv; |
968 | struct dccp_rx_hist_entry *packet; | 982 | struct dccp_rx_hist_entry *packet; |
969 | struct timeval now; | 983 | struct timeval now; |
970 | u32 p_prev, rtt_prev, r_sample, t_elapsed; | 984 | u32 p_prev, rtt_prev; |
985 | suseconds_t r_sample, t_elapsed; | ||
971 | int loss, payload_size; | 986 | int loss, payload_size; |
972 | 987 | ||
973 | BUG_ON(hcrx == NULL); | 988 | BUG_ON(hcrx == NULL); |
@@ -987,11 +1002,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
987 | r_sample = timeval_usecs(&now); | 1002 | r_sample = timeval_usecs(&now); |
988 | t_elapsed = opt_recv->dccpor_elapsed_time * 10; | 1003 | t_elapsed = opt_recv->dccpor_elapsed_time * 10; |
989 | 1004 | ||
1005 | DCCP_BUG_ON(r_sample < 0); | ||
990 | if (unlikely(r_sample <= t_elapsed)) | 1006 | if (unlikely(r_sample <= t_elapsed)) |
991 | DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n", | 1007 | DCCP_WARN("r_sample=%ldus, t_elapsed=%ldus\n", |
992 | r_sample, t_elapsed); | 1008 | r_sample, t_elapsed); |
993 | else | 1009 | else |
994 | r_sample -= t_elapsed; | 1010 | r_sample -= t_elapsed; |
1011 | CCID3_RTT_SANITY_CHECK(r_sample); | ||
995 | 1012 | ||
996 | if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA) | 1013 | if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA) |
997 | hcrx->ccid3hcrx_rtt = r_sample; | 1014 | hcrx->ccid3hcrx_rtt = r_sample; |
@@ -1000,8 +1017,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1000 | r_sample / 10; | 1017 | r_sample / 10; |
1001 | 1018 | ||
1002 | if (rtt_prev != hcrx->ccid3hcrx_rtt) | 1019 | if (rtt_prev != hcrx->ccid3hcrx_rtt) |
1003 | ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n", | 1020 | ccid3_pr_debug("%s(%p), New RTT=%uus, elapsed time=%u\n", |
1004 | dccp_role(sk), hcrx->ccid3hcrx_rtt, | 1021 | dccp_role(sk), sk, hcrx->ccid3hcrx_rtt, |
1005 | opt_recv->dccpor_elapsed_time); | 1022 | opt_recv->dccpor_elapsed_time); |
1006 | break; | 1023 | break; |
1007 | case DCCP_PKT_DATA: | 1024 | case DCCP_PKT_DATA: |
@@ -1013,7 +1030,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1013 | packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp, | 1030 | packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp, |
1014 | skb, GFP_ATOMIC); | 1031 | skb, GFP_ATOMIC); |
1015 | if (unlikely(packet == NULL)) { | 1032 | if (unlikely(packet == NULL)) { |
1016 | DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet " | 1033 | DCCP_WARN("%s(%p), Not enough mem to add rx packet " |
1017 | "to history, consider it lost!\n", dccp_role(sk), sk); | 1034 | "to history, consider it lost!\n", dccp_role(sk), sk); |
1018 | return; | 1035 | return; |
1019 | } | 1036 | } |
@@ -1028,9 +1045,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1028 | 1045 | ||
1029 | switch (hcrx->ccid3hcrx_state) { | 1046 | switch (hcrx->ccid3hcrx_state) { |
1030 | case TFRC_RSTATE_NO_DATA: | 1047 | case TFRC_RSTATE_NO_DATA: |
1031 | ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial " | 1048 | ccid3_pr_debug("%s(%p, state=%s), skb=%p, sending initial " |
1032 | "feedback\n", | 1049 | "feedback\n", dccp_role(sk), sk, |
1033 | dccp_role(sk), sk, | ||
1034 | dccp_state_name(sk->sk_state), skb); | 1050 | dccp_state_name(sk->sk_state), skb); |
1035 | ccid3_hc_rx_send_feedback(sk); | 1051 | ccid3_hc_rx_send_feedback(sk); |
1036 | ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA); | 1052 | ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA); |
@@ -1041,19 +1057,19 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1041 | break; | 1057 | break; |
1042 | 1058 | ||
1043 | dccp_timestamp(sk, &now); | 1059 | dccp_timestamp(sk, &now); |
1044 | if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >= | 1060 | if ((timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) - |
1045 | hcrx->ccid3hcrx_rtt) { | 1061 | (suseconds_t)hcrx->ccid3hcrx_rtt) >= 0) { |
1046 | hcrx->ccid3hcrx_tstamp_last_ack = now; | 1062 | hcrx->ccid3hcrx_tstamp_last_ack = now; |
1047 | ccid3_hc_rx_send_feedback(sk); | 1063 | ccid3_hc_rx_send_feedback(sk); |
1048 | } | 1064 | } |
1049 | return; | 1065 | return; |
1050 | case TFRC_RSTATE_TERM: | 1066 | case TFRC_RSTATE_TERM: |
1051 | DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); | 1067 | DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk); |
1052 | return; | 1068 | return; |
1053 | } | 1069 | } |
1054 | 1070 | ||
1055 | /* Dealing with packet loss */ | 1071 | /* Dealing with packet loss */ |
1056 | ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n", | 1072 | ccid3_pr_debug("%s(%p, state=%s), data loss! Reacting...\n", |
1057 | dccp_role(sk), sk, dccp_state_name(sk->sk_state)); | 1073 | dccp_role(sk), sk, dccp_state_name(sk->sk_state)); |
1058 | 1074 | ||
1059 | p_prev = hcrx->ccid3hcrx_p; | 1075 | p_prev = hcrx->ccid3hcrx_p; |
@@ -1078,7 +1094,7 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) | |||
1078 | { | 1094 | { |
1079 | struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); | 1095 | struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); |
1080 | 1096 | ||
1081 | ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); | 1097 | ccid3_pr_debug("entry\n"); |
1082 | 1098 | ||
1083 | hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; | 1099 | hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; |
1084 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); | 1100 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); |
@@ -1086,7 +1102,7 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) | |||
1086 | dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack); | 1102 | dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack); |
1087 | hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack; | 1103 | hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack; |
1088 | hcrx->ccid3hcrx_s = 0; | 1104 | hcrx->ccid3hcrx_s = 0; |
1089 | hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */ | 1105 | hcrx->ccid3hcrx_rtt = 0; |
1090 | return 0; | 1106 | return 0; |
1091 | } | 1107 | } |
1092 | 1108 | ||
@@ -1115,9 +1131,9 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) | |||
1115 | 1131 | ||
1116 | BUG_ON(hcrx == NULL); | 1132 | BUG_ON(hcrx == NULL); |
1117 | 1133 | ||
1118 | info->tcpi_ca_state = hcrx->ccid3hcrx_state; | 1134 | info->tcpi_ca_state = hcrx->ccid3hcrx_state; |
1119 | info->tcpi_options |= TCPI_OPT_TIMESTAMPS; | 1135 | info->tcpi_options |= TCPI_OPT_TIMESTAMPS; |
1120 | info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt; | 1136 | info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt; |
1121 | } | 1137 | } |
1122 | 1138 | ||
1123 | static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) | 1139 | static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) |
@@ -1198,7 +1214,6 @@ static struct ccid_operations ccid3 = { | |||
1198 | .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet, | 1214 | .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet, |
1199 | .ccid_hc_tx_packet_sent = ccid3_hc_tx_packet_sent, | 1215 | .ccid_hc_tx_packet_sent = ccid3_hc_tx_packet_sent, |
1200 | .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv, | 1216 | .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv, |
1201 | .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options, | ||
1202 | .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options, | 1217 | .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options, |
1203 | .ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock), | 1218 | .ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock), |
1204 | .ccid_hc_rx_init = ccid3_hc_rx_init, | 1219 | .ccid_hc_rx_init = ccid3_hc_rx_init, |
@@ -1210,7 +1225,7 @@ static struct ccid_operations ccid3 = { | |||
1210 | .ccid_hc_rx_getsockopt = ccid3_hc_rx_getsockopt, | 1225 | .ccid_hc_rx_getsockopt = ccid3_hc_rx_getsockopt, |
1211 | .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, | 1226 | .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, |
1212 | }; | 1227 | }; |
1213 | 1228 | ||
1214 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG | 1229 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG |
1215 | module_param(ccid3_debug, int, 0444); | 1230 | module_param(ccid3_debug, int, 0444); |
1216 | MODULE_PARM_DESC(ccid3_debug, "Enable debug messages"); | 1231 | MODULE_PARM_DESC(ccid3_debug, "Enable debug messages"); |
@@ -1233,7 +1248,7 @@ static __init int ccid3_module_init(void) | |||
1233 | goto out_free_tx; | 1248 | goto out_free_tx; |
1234 | 1249 | ||
1235 | rc = ccid_register(&ccid3); | 1250 | rc = ccid_register(&ccid3); |
1236 | if (rc != 0) | 1251 | if (rc != 0) |
1237 | goto out_free_loss_interval_history; | 1252 | goto out_free_loss_interval_history; |
1238 | out: | 1253 | out: |
1239 | return rc; | 1254 | return rc; |
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 07596d704ef..15776a88c09 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h | |||
@@ -51,6 +51,16 @@ | |||
51 | /* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */ | 51 | /* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */ |
52 | #define TFRC_T_MBI 64 | 52 | #define TFRC_T_MBI 64 |
53 | 53 | ||
54 | /* What we think is a reasonable upper limit on RTT values */ | ||
55 | #define CCID3_SANE_RTT_MAX ((suseconds_t)(4 * USEC_PER_SEC)) | ||
56 | |||
57 | #define CCID3_RTT_SANITY_CHECK(rtt) do { \ | ||
58 | if (rtt > CCID3_SANE_RTT_MAX) { \ | ||
59 | DCCP_CRIT("RTT (%d) too large, substituting %d", \ | ||
60 | (int)rtt, (int)CCID3_SANE_RTT_MAX); \ | ||
61 | rtt = CCID3_SANE_RTT_MAX; \ | ||
62 | } } while (0) | ||
63 | |||
54 | enum ccid3_options { | 64 | enum ccid3_options { |
55 | TFRC_OPT_LOSS_EVENT_RATE = 192, | 65 | TFRC_OPT_LOSS_EVENT_RATE = 192, |
56 | TFRC_OPT_LOSS_INTERVALS = 193, | 66 | TFRC_OPT_LOSS_INTERVALS = 193, |
@@ -67,7 +77,7 @@ struct ccid3_options_received { | |||
67 | 77 | ||
68 | /* TFRC sender states */ | 78 | /* TFRC sender states */ |
69 | enum ccid3_hc_tx_states { | 79 | enum ccid3_hc_tx_states { |
70 | TFRC_SSTATE_NO_SENT = 1, | 80 | TFRC_SSTATE_NO_SENT = 1, |
71 | TFRC_SSTATE_NO_FBACK, | 81 | TFRC_SSTATE_NO_FBACK, |
72 | TFRC_SSTATE_FBACK, | 82 | TFRC_SSTATE_FBACK, |
73 | TFRC_SSTATE_TERM, | 83 | TFRC_SSTATE_TERM, |
@@ -75,23 +85,23 @@ enum ccid3_hc_tx_states { | |||
75 | 85 | ||
76 | /** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket | 86 | /** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket |
77 | * | 87 | * |
78 | * @ccid3hctx_x - Current sending rate | 88 | * @ccid3hctx_x - Current sending rate in 64 * bytes per second |
79 | * @ccid3hctx_x_recv - Receive rate | 89 | * @ccid3hctx_x_recv - Receive rate in 64 * bytes per second |
80 | * @ccid3hctx_x_calc - Calculated send rate (RFC 3448, 3.1) | 90 | * @ccid3hctx_x_calc - Calculated rate in bytes per second |
81 | * @ccid3hctx_rtt - Estimate of current round trip time in usecs | 91 | * @ccid3hctx_rtt - Estimate of current round trip time in usecs |
82 | * @ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000 | 92 | * @ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000 |
83 | * @ccid3hctx_s - Packet size | 93 | * @ccid3hctx_s - Packet size in bytes |
84 | * @ccid3hctx_t_rto - Retransmission Timeout (RFC 3448, 3.1) | 94 | * @ccid3hctx_t_rto - Nofeedback Timer setting in usecs |
85 | * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6) | 95 | * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6) in usecs |
86 | * @ccid3hctx_state - Sender state, one of %ccid3_hc_tx_states | 96 | * @ccid3hctx_state - Sender state, one of %ccid3_hc_tx_states |
87 | * @ccid3hctx_last_win_count - Last window counter sent | 97 | * @ccid3hctx_last_win_count - Last window counter sent |
88 | * @ccid3hctx_t_last_win_count - Timestamp of earliest packet | 98 | * @ccid3hctx_t_last_win_count - Timestamp of earliest packet |
89 | * with last_win_count value sent | 99 | * with last_win_count value sent |
90 | * @ccid3hctx_no_feedback_timer - Handle to no feedback timer | 100 | * @ccid3hctx_no_feedback_timer - Handle to no feedback timer |
91 | * @ccid3hctx_idle - Flag indicating that sender is idling | 101 | * @ccid3hctx_idle - Flag indicating that sender is idling |
92 | * @ccid3hctx_t_ld - Time last doubled during slow start | 102 | * @ccid3hctx_t_ld - Time last doubled during slow start |
93 | * @ccid3hctx_t_nom - Nominal send time of next packet | 103 | * @ccid3hctx_t_nom - Nominal send time of next packet |
94 | * @ccid3hctx_delta - Send timer delta | 104 | * @ccid3hctx_delta - Send timer delta (RFC 3448, 4.6) in usecs |
95 | * @ccid3hctx_hist - Packet history | 105 | * @ccid3hctx_hist - Packet history |
96 | * @ccid3hctx_options_received - Parsed set of retrieved options | 106 | * @ccid3hctx_options_received - Parsed set of retrieved options |
97 | */ | 107 | */ |
@@ -105,7 +115,7 @@ struct ccid3_hc_tx_sock { | |||
105 | #define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto | 115 | #define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto |
106 | #define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi | 116 | #define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi |
107 | u16 ccid3hctx_s; | 117 | u16 ccid3hctx_s; |
108 | enum ccid3_hc_tx_states ccid3hctx_state:8; | 118 | enum ccid3_hc_tx_states ccid3hctx_state:8; |
109 | u8 ccid3hctx_last_win_count; | 119 | u8 ccid3hctx_last_win_count; |
110 | u8 ccid3hctx_idle; | 120 | u8 ccid3hctx_idle; |
111 | struct timeval ccid3hctx_t_last_win_count; | 121 | struct timeval ccid3hctx_t_last_win_count; |
@@ -119,7 +129,7 @@ struct ccid3_hc_tx_sock { | |||
119 | 129 | ||
120 | /* TFRC receiver states */ | 130 | /* TFRC receiver states */ |
121 | enum ccid3_hc_rx_states { | 131 | enum ccid3_hc_rx_states { |
122 | TFRC_RSTATE_NO_DATA = 1, | 132 | TFRC_RSTATE_NO_DATA = 1, |
123 | TFRC_RSTATE_DATA, | 133 | TFRC_RSTATE_DATA, |
124 | TFRC_RSTATE_TERM = 127, | 134 | TFRC_RSTATE_TERM = 127, |
125 | }; | 135 | }; |
@@ -147,18 +157,18 @@ struct ccid3_hc_rx_sock { | |||
147 | #define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv | 157 | #define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv |
148 | #define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt | 158 | #define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt |
149 | #define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p | 159 | #define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p |
150 | u64 ccid3hcrx_seqno_nonloss:48, | 160 | u64 ccid3hcrx_seqno_nonloss:48, |
151 | ccid3hcrx_ccval_nonloss:4, | 161 | ccid3hcrx_ccval_nonloss:4, |
152 | ccid3hcrx_ccval_last_counter:4; | 162 | ccid3hcrx_ccval_last_counter:4; |
153 | enum ccid3_hc_rx_states ccid3hcrx_state:8; | 163 | enum ccid3_hc_rx_states ccid3hcrx_state:8; |
154 | u32 ccid3hcrx_bytes_recv; | 164 | u32 ccid3hcrx_bytes_recv; |
155 | struct timeval ccid3hcrx_tstamp_last_feedback; | 165 | struct timeval ccid3hcrx_tstamp_last_feedback; |
156 | struct timeval ccid3hcrx_tstamp_last_ack; | 166 | struct timeval ccid3hcrx_tstamp_last_ack; |
157 | struct list_head ccid3hcrx_hist; | 167 | struct list_head ccid3hcrx_hist; |
158 | struct list_head ccid3hcrx_li_hist; | 168 | struct list_head ccid3hcrx_li_hist; |
159 | u16 ccid3hcrx_s; | 169 | u16 ccid3hcrx_s; |
160 | u32 ccid3hcrx_pinv; | 170 | u32 ccid3hcrx_pinv; |
161 | u32 ccid3hcrx_elapsed_time; | 171 | u32 ccid3hcrx_elapsed_time; |
162 | }; | 172 | }; |
163 | 173 | ||
164 | static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) | 174 | static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) |
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c index b876c9c81c6..2e8ef42721e 100644 --- a/net/dccp/ccids/lib/packet_history.c +++ b/net/dccp/ccids/lib/packet_history.c | |||
@@ -36,9 +36,100 @@ | |||
36 | 36 | ||
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/string.h> | 38 | #include <linux/string.h> |
39 | |||
40 | #include "packet_history.h" | 39 | #include "packet_history.h" |
41 | 40 | ||
41 | /* | ||
42 | * Transmitter History Routines | ||
43 | */ | ||
44 | struct dccp_tx_hist *dccp_tx_hist_new(const char *name) | ||
45 | { | ||
46 | struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | ||
47 | static const char dccp_tx_hist_mask[] = "tx_hist_%s"; | ||
48 | char *slab_name; | ||
49 | |||
50 | if (hist == NULL) | ||
51 | goto out; | ||
52 | |||
53 | slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1, | ||
54 | GFP_ATOMIC); | ||
55 | if (slab_name == NULL) | ||
56 | goto out_free_hist; | ||
57 | |||
58 | sprintf(slab_name, dccp_tx_hist_mask, name); | ||
59 | hist->dccptxh_slab = kmem_cache_create(slab_name, | ||
60 | sizeof(struct dccp_tx_hist_entry), | ||
61 | 0, SLAB_HWCACHE_ALIGN, | ||
62 | NULL, NULL); | ||
63 | if (hist->dccptxh_slab == NULL) | ||
64 | goto out_free_slab_name; | ||
65 | out: | ||
66 | return hist; | ||
67 | out_free_slab_name: | ||
68 | kfree(slab_name); | ||
69 | out_free_hist: | ||
70 | kfree(hist); | ||
71 | hist = NULL; | ||
72 | goto out; | ||
73 | } | ||
74 | |||
75 | EXPORT_SYMBOL_GPL(dccp_tx_hist_new); | ||
76 | |||
77 | void dccp_tx_hist_delete(struct dccp_tx_hist *hist) | ||
78 | { | ||
79 | const char* name = kmem_cache_name(hist->dccptxh_slab); | ||
80 | |||
81 | kmem_cache_destroy(hist->dccptxh_slab); | ||
82 | kfree(name); | ||
83 | kfree(hist); | ||
84 | } | ||
85 | |||
86 | EXPORT_SYMBOL_GPL(dccp_tx_hist_delete); | ||
87 | |||
88 | struct dccp_tx_hist_entry * | ||
89 | dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq) | ||
90 | { | ||
91 | struct dccp_tx_hist_entry *packet = NULL, *entry; | ||
92 | |||
93 | list_for_each_entry(entry, list, dccphtx_node) | ||
94 | if (entry->dccphtx_seqno == seq) { | ||
95 | packet = entry; | ||
96 | break; | ||
97 | } | ||
98 | |||
99 | return packet; | ||
100 | } | ||
101 | |||
102 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); | ||
103 | |||
104 | void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list) | ||
105 | { | ||
106 | struct dccp_tx_hist_entry *entry, *next; | ||
107 | |||
108 | list_for_each_entry_safe(entry, next, list, dccphtx_node) { | ||
109 | list_del_init(&entry->dccphtx_node); | ||
110 | dccp_tx_hist_entry_delete(hist, entry); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); | ||
115 | |||
116 | void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | ||
117 | struct list_head *list, | ||
118 | struct dccp_tx_hist_entry *packet) | ||
119 | { | ||
120 | struct dccp_tx_hist_entry *next; | ||
121 | |||
122 | list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) { | ||
123 | list_del_init(&packet->dccphtx_node); | ||
124 | dccp_tx_hist_entry_delete(hist, packet); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older); | ||
129 | |||
130 | /* | ||
131 | * Receiver History Routines | ||
132 | */ | ||
42 | struct dccp_rx_hist *dccp_rx_hist_new(const char *name) | 133 | struct dccp_rx_hist *dccp_rx_hist_new(const char *name) |
43 | { | 134 | { |
44 | struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | 135 | struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); |
@@ -83,18 +174,24 @@ void dccp_rx_hist_delete(struct dccp_rx_hist *hist) | |||
83 | 174 | ||
84 | EXPORT_SYMBOL_GPL(dccp_rx_hist_delete); | 175 | EXPORT_SYMBOL_GPL(dccp_rx_hist_delete); |
85 | 176 | ||
86 | void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list) | 177 | int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, |
178 | u8 *ccval) | ||
87 | { | 179 | { |
88 | struct dccp_rx_hist_entry *entry, *next; | 180 | struct dccp_rx_hist_entry *packet = NULL, *entry; |
89 | 181 | ||
90 | list_for_each_entry_safe(entry, next, list, dccphrx_node) { | 182 | list_for_each_entry(entry, list, dccphrx_node) |
91 | list_del_init(&entry->dccphrx_node); | 183 | if (entry->dccphrx_seqno == seq) { |
92 | kmem_cache_free(hist->dccprxh_slab, entry); | 184 | packet = entry; |
93 | } | 185 | break; |
94 | } | 186 | } |
95 | 187 | ||
96 | EXPORT_SYMBOL_GPL(dccp_rx_hist_purge); | 188 | if (packet) |
189 | *ccval = packet->dccphrx_ccval; | ||
97 | 190 | ||
191 | return packet != NULL; | ||
192 | } | ||
193 | |||
194 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry); | ||
98 | struct dccp_rx_hist_entry * | 195 | struct dccp_rx_hist_entry * |
99 | dccp_rx_hist_find_data_packet(const struct list_head *list) | 196 | dccp_rx_hist_find_data_packet(const struct list_head *list) |
100 | { | 197 | { |
@@ -184,110 +281,18 @@ void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, | |||
184 | 281 | ||
185 | EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); | 282 | EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); |
186 | 283 | ||
187 | struct dccp_tx_hist *dccp_tx_hist_new(const char *name) | 284 | void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list) |
188 | { | ||
189 | struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | ||
190 | static const char dccp_tx_hist_mask[] = "tx_hist_%s"; | ||
191 | char *slab_name; | ||
192 | |||
193 | if (hist == NULL) | ||
194 | goto out; | ||
195 | |||
196 | slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1, | ||
197 | GFP_ATOMIC); | ||
198 | if (slab_name == NULL) | ||
199 | goto out_free_hist; | ||
200 | |||
201 | sprintf(slab_name, dccp_tx_hist_mask, name); | ||
202 | hist->dccptxh_slab = kmem_cache_create(slab_name, | ||
203 | sizeof(struct dccp_tx_hist_entry), | ||
204 | 0, SLAB_HWCACHE_ALIGN, | ||
205 | NULL, NULL); | ||
206 | if (hist->dccptxh_slab == NULL) | ||
207 | goto out_free_slab_name; | ||
208 | out: | ||
209 | return hist; | ||
210 | out_free_slab_name: | ||
211 | kfree(slab_name); | ||
212 | out_free_hist: | ||
213 | kfree(hist); | ||
214 | hist = NULL; | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | EXPORT_SYMBOL_GPL(dccp_tx_hist_new); | ||
219 | |||
220 | void dccp_tx_hist_delete(struct dccp_tx_hist *hist) | ||
221 | { | ||
222 | const char* name = kmem_cache_name(hist->dccptxh_slab); | ||
223 | |||
224 | kmem_cache_destroy(hist->dccptxh_slab); | ||
225 | kfree(name); | ||
226 | kfree(hist); | ||
227 | } | ||
228 | |||
229 | EXPORT_SYMBOL_GPL(dccp_tx_hist_delete); | ||
230 | |||
231 | struct dccp_tx_hist_entry * | ||
232 | dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq) | ||
233 | { | ||
234 | struct dccp_tx_hist_entry *packet = NULL, *entry; | ||
235 | |||
236 | list_for_each_entry(entry, list, dccphtx_node) | ||
237 | if (entry->dccphtx_seqno == seq) { | ||
238 | packet = entry; | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | return packet; | ||
243 | } | ||
244 | |||
245 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); | ||
246 | |||
247 | int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, | ||
248 | u8 *ccval) | ||
249 | { | ||
250 | struct dccp_rx_hist_entry *packet = NULL, *entry; | ||
251 | |||
252 | list_for_each_entry(entry, list, dccphrx_node) | ||
253 | if (entry->dccphrx_seqno == seq) { | ||
254 | packet = entry; | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | if (packet) | ||
259 | *ccval = packet->dccphrx_ccval; | ||
260 | |||
261 | return packet != NULL; | ||
262 | } | ||
263 | |||
264 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry); | ||
265 | |||
266 | void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | ||
267 | struct list_head *list, | ||
268 | struct dccp_tx_hist_entry *packet) | ||
269 | { | 285 | { |
270 | struct dccp_tx_hist_entry *next; | 286 | struct dccp_rx_hist_entry *entry, *next; |
271 | 287 | ||
272 | list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) { | 288 | list_for_each_entry_safe(entry, next, list, dccphrx_node) { |
273 | list_del_init(&packet->dccphtx_node); | 289 | list_del_init(&entry->dccphrx_node); |
274 | dccp_tx_hist_entry_delete(hist, packet); | 290 | kmem_cache_free(hist->dccprxh_slab, entry); |
275 | } | 291 | } |
276 | } | 292 | } |
277 | 293 | ||
278 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older); | 294 | EXPORT_SYMBOL_GPL(dccp_rx_hist_purge); |
279 | |||
280 | void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list) | ||
281 | { | ||
282 | struct dccp_tx_hist_entry *entry, *next; | ||
283 | |||
284 | list_for_each_entry_safe(entry, next, list, dccphtx_node) { | ||
285 | list_del_init(&entry->dccphtx_node); | ||
286 | dccp_tx_hist_entry_delete(hist, entry); | ||
287 | } | ||
288 | } | ||
289 | 295 | ||
290 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); | ||
291 | 296 | ||
292 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " | 297 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " |
293 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); | 298 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); |
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h index 9a8bcf224aa..1f960c19ea1 100644 --- a/net/dccp/ccids/lib/packet_history.h +++ b/net/dccp/ccids/lib/packet_history.h | |||
@@ -49,43 +49,27 @@ | |||
49 | #define TFRC_WIN_COUNT_PER_RTT 4 | 49 | #define TFRC_WIN_COUNT_PER_RTT 4 |
50 | #define TFRC_WIN_COUNT_LIMIT 16 | 50 | #define TFRC_WIN_COUNT_LIMIT 16 |
51 | 51 | ||
52 | /* | ||
53 | * Transmitter History data structures and declarations | ||
54 | */ | ||
52 | struct dccp_tx_hist_entry { | 55 | struct dccp_tx_hist_entry { |
53 | struct list_head dccphtx_node; | 56 | struct list_head dccphtx_node; |
54 | u64 dccphtx_seqno:48, | 57 | u64 dccphtx_seqno:48, |
55 | dccphtx_ccval:4, | ||
56 | dccphtx_sent:1; | 58 | dccphtx_sent:1; |
57 | u32 dccphtx_rtt; | 59 | u32 dccphtx_rtt; |
58 | struct timeval dccphtx_tstamp; | 60 | struct timeval dccphtx_tstamp; |
59 | }; | 61 | }; |
60 | 62 | ||
61 | struct dccp_rx_hist_entry { | ||
62 | struct list_head dccphrx_node; | ||
63 | u64 dccphrx_seqno:48, | ||
64 | dccphrx_ccval:4, | ||
65 | dccphrx_type:4; | ||
66 | u32 dccphrx_ndp; /* In fact it is from 8 to 24 bits */ | ||
67 | struct timeval dccphrx_tstamp; | ||
68 | }; | ||
69 | |||
70 | struct dccp_tx_hist { | 63 | struct dccp_tx_hist { |
71 | struct kmem_cache *dccptxh_slab; | 64 | struct kmem_cache *dccptxh_slab; |
72 | }; | 65 | }; |
73 | 66 | ||
74 | extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name); | 67 | extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name); |
75 | extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist); | 68 | extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist); |
76 | |||
77 | struct dccp_rx_hist { | ||
78 | struct kmem_cache *dccprxh_slab; | ||
79 | }; | ||
80 | |||
81 | extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name); | ||
82 | extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist); | ||
83 | extern struct dccp_rx_hist_entry * | ||
84 | dccp_rx_hist_find_data_packet(const struct list_head *list); | ||
85 | 69 | ||
86 | static inline struct dccp_tx_hist_entry * | 70 | static inline struct dccp_tx_hist_entry * |
87 | dccp_tx_hist_entry_new(struct dccp_tx_hist *hist, | 71 | dccp_tx_hist_entry_new(struct dccp_tx_hist *hist, |
88 | const gfp_t prio) | 72 | const gfp_t prio) |
89 | { | 73 | { |
90 | struct dccp_tx_hist_entry *entry = kmem_cache_alloc(hist->dccptxh_slab, | 74 | struct dccp_tx_hist_entry *entry = kmem_cache_alloc(hist->dccptxh_slab, |
91 | prio); | 75 | prio); |
@@ -96,18 +80,20 @@ static inline struct dccp_tx_hist_entry * | |||
96 | return entry; | 80 | return entry; |
97 | } | 81 | } |
98 | 82 | ||
99 | static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist, | 83 | static inline struct dccp_tx_hist_entry * |
100 | struct dccp_tx_hist_entry *entry) | 84 | dccp_tx_hist_head(struct list_head *list) |
101 | { | 85 | { |
102 | if (entry != NULL) | 86 | struct dccp_tx_hist_entry *head = NULL; |
103 | kmem_cache_free(hist->dccptxh_slab, entry); | 87 | |
88 | if (!list_empty(list)) | ||
89 | head = list_entry(list->next, struct dccp_tx_hist_entry, | ||
90 | dccphtx_node); | ||
91 | return head; | ||
104 | } | 92 | } |
105 | 93 | ||
106 | extern struct dccp_tx_hist_entry * | 94 | extern struct dccp_tx_hist_entry * |
107 | dccp_tx_hist_find_entry(const struct list_head *list, | 95 | dccp_tx_hist_find_entry(const struct list_head *list, |
108 | const u64 seq); | 96 | const u64 seq); |
109 | extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, | ||
110 | u8 *ccval); | ||
111 | 97 | ||
112 | static inline void dccp_tx_hist_add_entry(struct list_head *list, | 98 | static inline void dccp_tx_hist_add_entry(struct list_head *list, |
113 | struct dccp_tx_hist_entry *entry) | 99 | struct dccp_tx_hist_entry *entry) |
@@ -115,30 +101,45 @@ static inline void dccp_tx_hist_add_entry(struct list_head *list, | |||
115 | list_add(&entry->dccphtx_node, list); | 101 | list_add(&entry->dccphtx_node, list); |
116 | } | 102 | } |
117 | 103 | ||
104 | static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist, | ||
105 | struct dccp_tx_hist_entry *entry) | ||
106 | { | ||
107 | if (entry != NULL) | ||
108 | kmem_cache_free(hist->dccptxh_slab, entry); | ||
109 | } | ||
110 | |||
111 | extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist, | ||
112 | struct list_head *list); | ||
113 | |||
118 | extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | 114 | extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, |
119 | struct list_head *list, | 115 | struct list_head *list, |
120 | struct dccp_tx_hist_entry *next); | 116 | struct dccp_tx_hist_entry *next); |
121 | 117 | ||
122 | extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist, | 118 | /* |
123 | struct list_head *list); | 119 | * Receiver History data structures and declarations |
120 | */ | ||
121 | struct dccp_rx_hist_entry { | ||
122 | struct list_head dccphrx_node; | ||
123 | u64 dccphrx_seqno:48, | ||
124 | dccphrx_ccval:4, | ||
125 | dccphrx_type:4; | ||
126 | u32 dccphrx_ndp; /* In fact it is from 8 to 24 bits */ | ||
127 | struct timeval dccphrx_tstamp; | ||
128 | }; | ||
124 | 129 | ||
125 | static inline struct dccp_tx_hist_entry * | 130 | struct dccp_rx_hist { |
126 | dccp_tx_hist_head(struct list_head *list) | 131 | struct kmem_cache *dccprxh_slab; |
127 | { | 132 | }; |
128 | struct dccp_tx_hist_entry *head = NULL; | ||
129 | 133 | ||
130 | if (!list_empty(list)) | 134 | extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name); |
131 | head = list_entry(list->next, struct dccp_tx_hist_entry, | 135 | extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist); |
132 | dccphtx_node); | ||
133 | return head; | ||
134 | } | ||
135 | 136 | ||
136 | static inline struct dccp_rx_hist_entry * | 137 | static inline struct dccp_rx_hist_entry * |
137 | dccp_rx_hist_entry_new(struct dccp_rx_hist *hist, | 138 | dccp_rx_hist_entry_new(struct dccp_rx_hist *hist, |
138 | const struct sock *sk, | 139 | const struct sock *sk, |
139 | const u32 ndp, | 140 | const u32 ndp, |
140 | const struct sk_buff *skb, | 141 | const struct sk_buff *skb, |
141 | const gfp_t prio) | 142 | const gfp_t prio) |
142 | { | 143 | { |
143 | struct dccp_rx_hist_entry *entry = kmem_cache_alloc(hist->dccprxh_slab, | 144 | struct dccp_rx_hist_entry *entry = kmem_cache_alloc(hist->dccprxh_slab, |
144 | prio); | 145 | prio); |
@@ -156,18 +157,8 @@ static inline struct dccp_rx_hist_entry * | |||
156 | return entry; | 157 | return entry; |
157 | } | 158 | } |
158 | 159 | ||
159 | static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist, | ||
160 | struct dccp_rx_hist_entry *entry) | ||
161 | { | ||
162 | if (entry != NULL) | ||
163 | kmem_cache_free(hist->dccprxh_slab, entry); | ||
164 | } | ||
165 | |||
166 | extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist, | ||
167 | struct list_head *list); | ||
168 | |||
169 | static inline struct dccp_rx_hist_entry * | 160 | static inline struct dccp_rx_hist_entry * |
170 | dccp_rx_hist_head(struct list_head *list) | 161 | dccp_rx_hist_head(struct list_head *list) |
171 | { | 162 | { |
172 | struct dccp_rx_hist_entry *head = NULL; | 163 | struct dccp_rx_hist_entry *head = NULL; |
173 | 164 | ||
@@ -177,6 +168,27 @@ static inline struct dccp_rx_hist_entry * | |||
177 | return head; | 168 | return head; |
178 | } | 169 | } |
179 | 170 | ||
171 | extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, | ||
172 | u8 *ccval); | ||
173 | extern struct dccp_rx_hist_entry * | ||
174 | dccp_rx_hist_find_data_packet(const struct list_head *list); | ||
175 | |||
176 | extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, | ||
177 | struct list_head *rx_list, | ||
178 | struct list_head *li_list, | ||
179 | struct dccp_rx_hist_entry *packet, | ||
180 | u64 nonloss_seqno); | ||
181 | |||
182 | static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist, | ||
183 | struct dccp_rx_hist_entry *entry) | ||
184 | { | ||
185 | if (entry != NULL) | ||
186 | kmem_cache_free(hist->dccprxh_slab, entry); | ||
187 | } | ||
188 | |||
189 | extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist, | ||
190 | struct list_head *list); | ||
191 | |||
180 | static inline int | 192 | static inline int |
181 | dccp_rx_hist_entry_data_packet(const struct dccp_rx_hist_entry *entry) | 193 | dccp_rx_hist_entry_data_packet(const struct dccp_rx_hist_entry *entry) |
182 | { | 194 | { |
@@ -184,12 +196,6 @@ static inline int | |||
184 | entry->dccphrx_type == DCCP_PKT_DATAACK; | 196 | entry->dccphrx_type == DCCP_PKT_DATAACK; |
185 | } | 197 | } |
186 | 198 | ||
187 | extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, | ||
188 | struct list_head *rx_list, | ||
189 | struct list_head *li_list, | ||
190 | struct dccp_rx_hist_entry *packet, | ||
191 | u64 nonloss_seqno); | ||
192 | |||
193 | extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list, | 199 | extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list, |
194 | struct list_head *li_list, u8 *win_loss); | 200 | struct list_head *li_list, u8 *win_loss); |
195 | 201 | ||
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h index 45f30f59ea2..faf5f7e219e 100644 --- a/net/dccp/ccids/lib/tfrc.h +++ b/net/dccp/ccids/lib/tfrc.h | |||
@@ -13,8 +13,29 @@ | |||
13 | * the Free Software Foundation; either version 2 of the License, or | 13 | * the Free Software Foundation; either version 2 of the License, or |
14 | * (at your option) any later version. | 14 | * (at your option) any later version. |
15 | */ | 15 | */ |
16 | |||
17 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <asm/div64.h> | ||
18 | |||
19 | /* integer-arithmetic divisions of type (a * 1000000)/b */ | ||
20 | static inline u64 scaled_div(u64 a, u32 b) | ||
21 | { | ||
22 | BUG_ON(b==0); | ||
23 | a *= 1000000; | ||
24 | do_div(a, b); | ||
25 | return a; | ||
26 | } | ||
27 | |||
28 | static inline u32 scaled_div32(u64 a, u32 b) | ||
29 | { | ||
30 | u64 result = scaled_div(a, b); | ||
31 | |||
32 | if (result > UINT_MAX) { | ||
33 | DCCP_CRIT("Overflow: a(%llu)/b(%u) > ~0U", | ||
34 | (unsigned long long)a, b); | ||
35 | return UINT_MAX; | ||
36 | } | ||
37 | return result; | ||
38 | } | ||
18 | 39 | ||
19 | extern u32 tfrc_calc_x(u16 s, u32 R, u32 p); | 40 | extern u32 tfrc_calc_x(u16 s, u32 R, u32 p); |
20 | extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue); | 41 | extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue); |
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index ddac2c511e2..90009fd77e1 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <asm/div64.h> | ||
17 | #include "../../dccp.h" | 16 | #include "../../dccp.h" |
18 | #include "tfrc.h" | 17 | #include "tfrc.h" |
19 | 18 | ||
@@ -616,15 +615,12 @@ static inline u32 tfrc_binsearch(u32 fval, u8 small) | |||
616 | * @R: RTT scaled by 1000000 (i.e., microseconds) | 615 | * @R: RTT scaled by 1000000 (i.e., microseconds) |
617 | * @p: loss ratio estimate scaled by 1000000 | 616 | * @p: loss ratio estimate scaled by 1000000 |
618 | * Returns X_calc in bytes per second (not scaled). | 617 | * Returns X_calc in bytes per second (not scaled). |
619 | * | ||
620 | * Note: DO NOT alter this code unless you run test cases against it, | ||
621 | * as the code has been optimized to stop underflow/overflow. | ||
622 | */ | 618 | */ |
623 | u32 tfrc_calc_x(u16 s, u32 R, u32 p) | 619 | u32 tfrc_calc_x(u16 s, u32 R, u32 p) |
624 | { | 620 | { |
625 | int index; | 621 | u16 index; |
626 | u32 f; | 622 | u32 f; |
627 | u64 tmp1, tmp2; | 623 | u64 result; |
628 | 624 | ||
629 | /* check against invalid parameters and divide-by-zero */ | 625 | /* check against invalid parameters and divide-by-zero */ |
630 | BUG_ON(p > 1000000); /* p must not exceed 100% */ | 626 | BUG_ON(p > 1000000); /* p must not exceed 100% */ |
@@ -650,15 +646,17 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p) | |||
650 | f = tfrc_calc_x_lookup[index][0]; | 646 | f = tfrc_calc_x_lookup[index][0]; |
651 | } | 647 | } |
652 | 648 | ||
653 | /* The following computes X = s/(R*f(p)) in bytes per second. Since f(p) | 649 | /* |
654 | * and R are both scaled by 1000000, we need to multiply by 1000000^2. | 650 | * Compute X = s/(R*f(p)) in bytes per second. |
655 | * ==> DO NOT alter this unless you test against overflow on 32 bit */ | 651 | * Since f(p) and R are both scaled by 1000000, we need to multiply by |
656 | tmp1 = ((u64)s * 100000000); | 652 | * 1000000^2. To avoid overflow, the result is computed in two stages. |
657 | tmp2 = ((u64)R * (u64)f); | 653 | * This works under almost all reasonable operational conditions, for a |
658 | do_div(tmp2, 10000); | 654 | * wide range of parameters. Yet, should some strange combination of |
659 | do_div(tmp1, tmp2); | 655 | * parameters result in overflow, the use of scaled_div32 will catch |
660 | 656 | * this and return UINT_MAX - which is a logically adequate consequence. | |
661 | return (u32)tmp1; | 657 | */ |
658 | result = scaled_div(s, R); | ||
659 | return scaled_div32(result, f); | ||
662 | } | 660 | } |
663 | 661 | ||
664 | EXPORT_SYMBOL_GPL(tfrc_calc_x); | 662 | EXPORT_SYMBOL_GPL(tfrc_calc_x); |