diff options
Diffstat (limited to 'net/dccp/ccids/ccid3.c')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 549 |
1 files changed, 245 insertions, 304 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index cec23ad286de..70ebe705eb75 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -60,13 +60,11 @@ static u32 usecs_div(const u32 a, const u32 b) | |||
60 | return (b >= 2 * div) ? tmp / (b / div) : tmp; | 60 | return (b >= 2 * div) ? tmp / (b / div) : tmp; |
61 | } | 61 | } |
62 | 62 | ||
63 | static int ccid3_debug; | ||
64 | 63 | ||
65 | #ifdef CCID3_DEBUG | 64 | |
66 | #define ccid3_pr_debug(format, a...) \ | 65 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG |
67 | do { if (ccid3_debug) \ | 66 | static int ccid3_debug; |
68 | printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ | 67 | #define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) |
69 | } while (0) | ||
70 | #else | 68 | #else |
71 | #define ccid3_pr_debug(format, a...) | 69 | #define ccid3_pr_debug(format, a...) |
72 | #endif | 70 | #endif |
@@ -75,15 +73,7 @@ static struct dccp_tx_hist *ccid3_tx_hist; | |||
75 | static struct dccp_rx_hist *ccid3_rx_hist; | 73 | static struct dccp_rx_hist *ccid3_rx_hist; |
76 | static struct dccp_li_hist *ccid3_li_hist; | 74 | static struct dccp_li_hist *ccid3_li_hist; |
77 | 75 | ||
78 | /* TFRC sender states */ | 76 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG |
79 | enum ccid3_hc_tx_states { | ||
80 | TFRC_SSTATE_NO_SENT = 1, | ||
81 | TFRC_SSTATE_NO_FBACK, | ||
82 | TFRC_SSTATE_FBACK, | ||
83 | TFRC_SSTATE_TERM, | ||
84 | }; | ||
85 | |||
86 | #ifdef CCID3_DEBUG | ||
87 | static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) | 77 | static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) |
88 | { | 78 | { |
89 | static char *ccid3_state_names[] = { | 79 | static char *ccid3_state_names[] = { |
@@ -110,25 +100,24 @@ static void ccid3_hc_tx_set_state(struct sock *sk, | |||
110 | hctx->ccid3hctx_state = state; | 100 | hctx->ccid3hctx_state = state; |
111 | } | 101 | } |
112 | 102 | ||
113 | /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ | 103 | /* |
114 | static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx) | 104 | * Recalculate scheduled nominal send time t_nom, inter-packet interval |
105 | * t_ipi, and delta value. Should be called after each change to X. | ||
106 | */ | ||
107 | static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx) | ||
115 | { | 108 | { |
116 | /* | 109 | timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); |
117 | * If no feedback spec says t_ipi is 1 second (set elsewhere and then | ||
118 | * doubles after every no feedback timer (separate function) | ||
119 | */ | ||
120 | if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK) | ||
121 | hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, | ||
122 | hctx->ccid3hctx_x); | ||
123 | } | ||
124 | 110 | ||
125 | /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ | 111 | /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ |
126 | static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx) | 112 | hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x); |
127 | { | 113 | |
114 | /* Update nominal send time with regard to the new t_ipi */ | ||
115 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); | ||
116 | |||
117 | /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ | ||
128 | hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2, | 118 | hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2, |
129 | TFRC_OPSYS_HALF_TIME_GRAN); | 119 | TFRC_OPSYS_HALF_TIME_GRAN); |
130 | } | 120 | } |
131 | |||
132 | /* | 121 | /* |
133 | * Update X by | 122 | * Update X by |
134 | * If (p > 0) | 123 | * If (p > 0) |
@@ -139,76 +128,85 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx) | |||
139 | * X = max(min(2 * X, 2 * X_recv), s / R); | 128 | * X = max(min(2 * X, 2 * X_recv), s / R); |
140 | * tld = now; | 129 | * tld = now; |
141 | */ | 130 | */ |
142 | static void ccid3_hc_tx_update_x(struct sock *sk) | 131 | static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now) |
132 | |||
143 | { | 133 | { |
144 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 134 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
135 | const __u32 old_x = hctx->ccid3hctx_x; | ||
145 | 136 | ||
146 | /* To avoid large error in calcX */ | 137 | /* To avoid large error in calcX */ |
147 | if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) { | 138 | if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) { |
148 | hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, | 139 | hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, |
149 | hctx->ccid3hctx_rtt, | 140 | hctx->ccid3hctx_rtt, |
150 | hctx->ccid3hctx_p); | 141 | hctx->ccid3hctx_p); |
151 | 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, |
152 | 2 * hctx->ccid3hctx_x_recv), | 143 | hctx->ccid3hctx_x_recv * 2), |
153 | (hctx->ccid3hctx_s / | 144 | hctx->ccid3hctx_s / TFRC_T_MBI); |
154 | TFRC_MAX_BACK_OFF_TIME)); | 145 | |
155 | } else { | 146 | } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >= |
156 | 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"); | ||
157 | 155 | ||
158 | dccp_timestamp(sk, &now); | 156 | if (hctx->ccid3hctx_x != old_x) |
159 | if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >= | 157 | ccid3_update_send_time(hctx); |
160 | hctx->ccid3hctx_rtt) { | 158 | } |
161 | hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv, | 159 | |
162 | hctx->ccid3hctx_x) * 2, | 160 | /* |
163 | usecs_div(hctx->ccid3hctx_s, | 161 | * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1) |
164 | hctx->ccid3hctx_rtt)); | 162 | * @len: DCCP packet payload size in bytes |
165 | hctx->ccid3hctx_t_ld = now; | 163 | */ |
166 | } | 164 | static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len) |
167 | } | 165 | { |
166 | if (unlikely(len == 0)) | ||
167 | ccid3_pr_debug("Packet payload length is 0 - not updating\n"); | ||
168 | else | ||
169 | hctx->ccid3hctx_s = hctx->ccid3hctx_s == 0 ? len : | ||
170 | (9 * hctx->ccid3hctx_s + len) / 10; | ||
171 | /* | ||
172 | * Note: We could do a potential optimisation here - when `s' changes, | ||
173 | * recalculate sending rate and consequently t_ipi, t_delta, and | ||
174 | * t_now. This is however non-standard, and the benefits are not | ||
175 | * clear, so it is currently left out. | ||
176 | */ | ||
168 | } | 177 | } |
169 | 178 | ||
170 | static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | 179 | static void ccid3_hc_tx_no_feedback_timer(unsigned long data) |
171 | { | 180 | { |
172 | struct sock *sk = (struct sock *)data; | 181 | struct sock *sk = (struct sock *)data; |
173 | unsigned long next_tmout = 0; | ||
174 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 182 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
183 | unsigned long t_nfb = USEC_PER_SEC / 5; | ||
175 | 184 | ||
176 | bh_lock_sock(sk); | 185 | bh_lock_sock(sk); |
177 | if (sock_owned_by_user(sk)) { | 186 | if (sock_owned_by_user(sk)) { |
178 | /* Try again later. */ | 187 | /* Try again later. */ |
179 | /* XXX: set some sensible MIB */ | 188 | /* XXX: set some sensible MIB */ |
180 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, | 189 | goto restart_timer; |
181 | jiffies + HZ / 5); | ||
182 | goto out; | ||
183 | } | 190 | } |
184 | 191 | ||
185 | ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk, | 192 | ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk, |
186 | ccid3_tx_state_name(hctx->ccid3hctx_state)); | 193 | ccid3_tx_state_name(hctx->ccid3hctx_state)); |
187 | 194 | ||
188 | switch (hctx->ccid3hctx_state) { | 195 | switch (hctx->ccid3hctx_state) { |
189 | case TFRC_SSTATE_TERM: | ||
190 | goto out; | ||
191 | case TFRC_SSTATE_NO_FBACK: | 196 | case TFRC_SSTATE_NO_FBACK: |
192 | /* Halve send rate */ | 197 | /* RFC 3448, 4.4: Halve send rate directly */ |
193 | hctx->ccid3hctx_x /= 2; | 198 | hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2, |
194 | if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s / | 199 | hctx->ccid3hctx_s / TFRC_T_MBI); |
195 | TFRC_MAX_BACK_OFF_TIME)) | ||
196 | hctx->ccid3hctx_x = (hctx->ccid3hctx_s / | ||
197 | TFRC_MAX_BACK_OFF_TIME); | ||
198 | 200 | ||
199 | 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 " |
200 | "bytes/s\n", | 202 | "bytes/s\n", |
201 | dccp_role(sk), sk, | 203 | dccp_role(sk), sk, |
202 | ccid3_tx_state_name(hctx->ccid3hctx_state), | 204 | ccid3_tx_state_name(hctx->ccid3hctx_state), |
203 | hctx->ccid3hctx_x); | 205 | hctx->ccid3hctx_x); |
204 | next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s, | 206 | /* The value of R is still undefined and so we can not recompute |
205 | hctx->ccid3hctx_x), | 207 | * the timout value. Keep initial value as per [RFC 4342, 5]. */ |
206 | TFRC_INITIAL_TIMEOUT); | 208 | t_nfb = TFRC_INITIAL_TIMEOUT; |
207 | /* | 209 | ccid3_update_send_time(hctx); |
208 | * FIXME - not sure above calculation is correct. See section | ||
209 | * 5 of CCID3 11 should adjust tx_t_ipi and double that to | ||
210 | * achieve it really | ||
211 | */ | ||
212 | break; | 210 | break; |
213 | case TFRC_SSTATE_FBACK: | 211 | case TFRC_SSTATE_FBACK: |
214 | /* | 212 | /* |
@@ -218,6 +216,8 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
218 | if (!hctx->ccid3hctx_idle || | 216 | if (!hctx->ccid3hctx_idle || |
219 | (hctx->ccid3hctx_x_recv >= | 217 | (hctx->ccid3hctx_x_recv >= |
220 | 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) { | 218 | 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) { |
219 | struct timeval now; | ||
220 | |||
221 | ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n", | 221 | ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n", |
222 | dccp_role(sk), sk, | 222 | dccp_role(sk), sk, |
223 | ccid3_tx_state_name(hctx->ccid3hctx_state)); | 223 | ccid3_tx_state_name(hctx->ccid3hctx_state)); |
@@ -235,55 +235,60 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
235 | if (hctx->ccid3hctx_p < TFRC_SMALLEST_P || | 235 | if (hctx->ccid3hctx_p < TFRC_SMALLEST_P || |
236 | hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) | 236 | hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) |
237 | 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, |
238 | hctx->ccid3hctx_s / (2 * TFRC_MAX_BACK_OFF_TIME)); | 238 | hctx->ccid3hctx_s / (2 * TFRC_T_MBI)); |
239 | else | 239 | else |
240 | hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4; | 240 | hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4; |
241 | 241 | ||
242 | /* Update sending rate */ | 242 | /* Update sending rate */ |
243 | ccid3_hc_tx_update_x(sk); | 243 | dccp_timestamp(sk, &now); |
244 | ccid3_hc_tx_update_x(sk, &now); | ||
244 | } | 245 | } |
245 | /* | 246 | /* |
246 | * Schedule no feedback timer to expire in | 247 | * Schedule no feedback timer to expire in |
247 | * max(4 * R, 2 * s / X) | 248 | * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) |
248 | */ | 249 | */ |
249 | next_tmout = max_t(u32, hctx->ccid3hctx_t_rto, | 250 | t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); |
250 | 2 * usecs_div(hctx->ccid3hctx_s, | ||
251 | hctx->ccid3hctx_x)); | ||
252 | break; | 251 | break; |
253 | default: | 252 | case TFRC_SSTATE_NO_SENT: |
254 | printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", | 253 | DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk); |
255 | __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); | 254 | /* fall through */ |
256 | dump_stack(); | 255 | case TFRC_SSTATE_TERM: |
257 | goto out; | 256 | goto out; |
258 | } | 257 | } |
259 | 258 | ||
260 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, | ||
261 | jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout))); | ||
262 | hctx->ccid3hctx_idle = 1; | 259 | hctx->ccid3hctx_idle = 1; |
260 | |||
261 | restart_timer: | ||
262 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, | ||
263 | jiffies + usecs_to_jiffies(t_nfb)); | ||
263 | out: | 264 | out: |
264 | bh_unlock_sock(sk); | 265 | bh_unlock_sock(sk); |
265 | sock_put(sk); | 266 | sock_put(sk); |
266 | } | 267 | } |
267 | 268 | ||
268 | static int ccid3_hc_tx_send_packet(struct sock *sk, | 269 | /* |
269 | struct sk_buff *skb, int len) | 270 | * returns |
271 | * > 0: delay (in msecs) that should pass before actually sending | ||
272 | * = 0: can send immediately | ||
273 | * < 0: error condition; do not send packet | ||
274 | */ | ||
275 | static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | ||
270 | { | 276 | { |
271 | struct dccp_sock *dp = dccp_sk(sk); | 277 | struct dccp_sock *dp = dccp_sk(sk); |
272 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 278 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
273 | struct dccp_tx_hist_entry *new_packet; | 279 | struct dccp_tx_hist_entry *new_packet; |
274 | struct timeval now; | 280 | struct timeval now; |
275 | long delay; | 281 | long delay; |
276 | int rc = -ENOTCONN; | ||
277 | 282 | ||
278 | BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); | 283 | BUG_ON(hctx == NULL); |
279 | 284 | ||
280 | /* Check if pure ACK or Terminating*/ | ||
281 | /* | 285 | /* |
282 | * XXX: We only call this function for DATA and DATAACK, on, these | 286 | * This function is called only for Data and DataAck packets. Sending |
283 | * packets can have zero length, but why the comment about "pure ACK"? | 287 | * zero-sized Data(Ack)s is theoretically possible, but for congestion |
288 | * control this case is pathological - ignore it. | ||
284 | */ | 289 | */ |
285 | if (unlikely(len == 0)) | 290 | if (unlikely(skb->len == 0)) |
286 | goto out; | 291 | return -EBADMSG; |
287 | 292 | ||
288 | /* See if last packet allocated was not sent */ | 293 | /* See if last packet allocated was not sent */ |
289 | new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); | 294 | new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); |
@@ -291,12 +296,10 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, | |||
291 | new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist, | 296 | new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist, |
292 | SLAB_ATOMIC); | 297 | SLAB_ATOMIC); |
293 | 298 | ||
294 | rc = -ENOBUFS; | ||
295 | if (unlikely(new_packet == NULL)) { | 299 | if (unlikely(new_packet == NULL)) { |
296 | LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, not enough " | 300 | DCCP_WARN("%s, sk=%p, not enough mem to add to history," |
297 | "mem to add to history, send refused\n", | 301 | "send refused\n", dccp_role(sk), sk); |
298 | __FUNCTION__, dccp_role(sk), sk); | 302 | return -ENOBUFS; |
299 | goto out; | ||
300 | } | 303 | } |
301 | 304 | ||
302 | dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet); | 305 | dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet); |
@@ -311,123 +314,94 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, | |||
311 | hctx->ccid3hctx_last_win_count = 0; | 314 | hctx->ccid3hctx_last_win_count = 0; |
312 | hctx->ccid3hctx_t_last_win_count = now; | 315 | hctx->ccid3hctx_t_last_win_count = now; |
313 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); | 316 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); |
314 | hctx->ccid3hctx_t_ipi = TFRC_INITIAL_IPI; | ||
315 | 317 | ||
316 | /* Set nominal send time for initial packet */ | 318 | /* Set initial sending rate to 1 packet per second */ |
319 | ccid3_hc_tx_update_s(hctx, skb->len); | ||
320 | hctx->ccid3hctx_x = hctx->ccid3hctx_s; | ||
321 | |||
322 | /* First timeout, according to [RFC 3448, 4.2], is 1 second */ | ||
323 | hctx->ccid3hctx_t_ipi = USEC_PER_SEC; | ||
324 | /* Initial delta: minimum of 0.5 sec and t_gran/2 */ | ||
325 | hctx->ccid3hctx_delta = TFRC_OPSYS_HALF_TIME_GRAN; | ||
326 | |||
327 | /* Set t_0 for initial packet */ | ||
317 | hctx->ccid3hctx_t_nom = now; | 328 | hctx->ccid3hctx_t_nom = now; |
318 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, | ||
319 | hctx->ccid3hctx_t_ipi); | ||
320 | ccid3_calc_new_delta(hctx); | ||
321 | rc = 0; | ||
322 | break; | 329 | break; |
323 | case TFRC_SSTATE_NO_FBACK: | 330 | case TFRC_SSTATE_NO_FBACK: |
324 | case TFRC_SSTATE_FBACK: | 331 | case TFRC_SSTATE_FBACK: |
325 | delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) - | 332 | delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now); |
326 | hctx->ccid3hctx_delta); | 333 | /* |
327 | delay /= -1000; | 334 | * Scheduling of packet transmissions [RFC 3448, 4.6] |
328 | /* divide by -1000 is to convert to ms and get sign right */ | 335 | * |
329 | rc = delay > 0 ? delay : 0; | 336 | * if (t_now > t_nom - delta) |
330 | break; | 337 | * // send the packet now |
331 | default: | 338 | * else |
332 | printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", | 339 | * // send the packet in (t_nom - t_now) milliseconds. |
333 | __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); | 340 | */ |
334 | dump_stack(); | 341 | if (delay >= hctx->ccid3hctx_delta) |
335 | rc = -EINVAL; | 342 | return delay / 1000L; |
336 | break; | 343 | break; |
344 | case TFRC_SSTATE_TERM: | ||
345 | DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); | ||
346 | return -EINVAL; | ||
337 | } | 347 | } |
338 | 348 | ||
339 | /* Can we send? if so add options and add to packet history */ | 349 | /* prepare to send now (add options etc.) */ |
340 | if (rc == 0) { | 350 | dp->dccps_hc_tx_insert_options = 1; |
341 | dp->dccps_hc_tx_insert_options = 1; | 351 | new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval = |
342 | new_packet->dccphtx_ccval = | 352 | hctx->ccid3hctx_last_win_count; |
343 | DCCP_SKB_CB(skb)->dccpd_ccval = | 353 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); |
344 | hctx->ccid3hctx_last_win_count; | 354 | |
345 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, | 355 | return 0; |
346 | hctx->ccid3hctx_t_ipi); | ||
347 | } | ||
348 | out: | ||
349 | return rc; | ||
350 | } | 356 | } |
351 | 357 | ||
352 | static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) | 358 | static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) |
353 | { | 359 | { |
354 | const struct dccp_sock *dp = dccp_sk(sk); | 360 | const struct dccp_sock *dp = dccp_sk(sk); |
355 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 361 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
356 | struct timeval now; | 362 | struct timeval now; |
363 | unsigned long quarter_rtt; | ||
364 | struct dccp_tx_hist_entry *packet; | ||
357 | 365 | ||
358 | BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); | 366 | BUG_ON(hctx == NULL); |
359 | 367 | ||
360 | dccp_timestamp(sk, &now); | 368 | dccp_timestamp(sk, &now); |
361 | 369 | ||
362 | /* check if we have sent a data packet */ | 370 | ccid3_hc_tx_update_s(hctx, len); |
363 | if (len > 0) { | ||
364 | unsigned long quarter_rtt; | ||
365 | struct dccp_tx_hist_entry *packet; | ||
366 | 371 | ||
367 | packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); | 372 | packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); |
368 | if (unlikely(packet == NULL)) { | 373 | if (unlikely(packet == NULL)) { |
369 | LIMIT_NETDEBUG(KERN_WARNING "%s: packet doesn't " | 374 | DCCP_WARN("packet doesn't exist in history!\n"); |
370 | "exists in history!\n", __FUNCTION__); | ||
371 | return; | ||
372 | } | ||
373 | if (unlikely(packet->dccphtx_sent)) { | ||
374 | LIMIT_NETDEBUG(KERN_WARNING "%s: no unsent packet in " | ||
375 | "history!\n", __FUNCTION__); | ||
376 | return; | ||
377 | } | ||
378 | packet->dccphtx_tstamp = now; | ||
379 | packet->dccphtx_seqno = dp->dccps_gss; | ||
380 | /* | ||
381 | * Check if win_count have changed | ||
382 | * Algorithm in "8.1. Window Counter Value" in RFC 4342. | ||
383 | */ | ||
384 | quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count); | ||
385 | if (likely(hctx->ccid3hctx_rtt > 8)) | ||
386 | quarter_rtt /= hctx->ccid3hctx_rtt / 4; | ||
387 | |||
388 | if (quarter_rtt > 0) { | ||
389 | hctx->ccid3hctx_t_last_win_count = now; | ||
390 | hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + | ||
391 | min_t(unsigned long, quarter_rtt, 5)) % 16; | ||
392 | ccid3_pr_debug("%s, sk=%p, window changed from " | ||
393 | "%u to %u!\n", | ||
394 | dccp_role(sk), sk, | ||
395 | packet->dccphtx_ccval, | ||
396 | hctx->ccid3hctx_last_win_count); | ||
397 | } | ||
398 | |||
399 | hctx->ccid3hctx_idle = 0; | ||
400 | packet->dccphtx_rtt = hctx->ccid3hctx_rtt; | ||
401 | packet->dccphtx_sent = 1; | ||
402 | } else | ||
403 | ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n", | ||
404 | dccp_role(sk), sk, dp->dccps_gss); | ||
405 | |||
406 | switch (hctx->ccid3hctx_state) { | ||
407 | case TFRC_SSTATE_NO_SENT: | ||
408 | /* if first wasn't pure ack */ | ||
409 | if (len != 0) | ||
410 | printk(KERN_CRIT "%s: %s, First packet sent is noted " | ||
411 | "as a data packet\n", | ||
412 | __FUNCTION__, dccp_role(sk)); | ||
413 | return; | 375 | return; |
414 | case TFRC_SSTATE_NO_FBACK: | ||
415 | case TFRC_SSTATE_FBACK: | ||
416 | if (len > 0) { | ||
417 | timeval_sub_usecs(&hctx->ccid3hctx_t_nom, | ||
418 | hctx->ccid3hctx_t_ipi); | ||
419 | ccid3_calc_new_t_ipi(hctx); | ||
420 | ccid3_calc_new_delta(hctx); | ||
421 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, | ||
422 | hctx->ccid3hctx_t_ipi); | ||
423 | } | ||
424 | break; | ||
425 | default: | ||
426 | printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", | ||
427 | __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); | ||
428 | dump_stack(); | ||
429 | break; | ||
430 | } | 376 | } |
377 | if (unlikely(packet->dccphtx_sent)) { | ||
378 | DCCP_WARN("no unsent packet in history!\n"); | ||
379 | return; | ||
380 | } | ||
381 | packet->dccphtx_tstamp = now; | ||
382 | packet->dccphtx_seqno = dp->dccps_gss; | ||
383 | /* | ||
384 | * Check if win_count have changed | ||
385 | * Algorithm in "8.1. Window Counter Value" in RFC 4342. | ||
386 | */ | ||
387 | quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count); | ||
388 | if (likely(hctx->ccid3hctx_rtt > 8)) | ||
389 | quarter_rtt /= hctx->ccid3hctx_rtt / 4; | ||
390 | |||
391 | if (quarter_rtt > 0) { | ||
392 | hctx->ccid3hctx_t_last_win_count = now; | ||
393 | hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + | ||
394 | min_t(unsigned long, quarter_rtt, 5)) % 16; | ||
395 | ccid3_pr_debug("%s, sk=%p, window changed from " | ||
396 | "%u to %u!\n", | ||
397 | dccp_role(sk), sk, | ||
398 | packet->dccphtx_ccval, | ||
399 | hctx->ccid3hctx_last_win_count); | ||
400 | } | ||
401 | |||
402 | hctx->ccid3hctx_idle = 0; | ||
403 | packet->dccphtx_rtt = hctx->ccid3hctx_rtt; | ||
404 | packet->dccphtx_sent = 1; | ||
431 | } | 405 | } |
432 | 406 | ||
433 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | 407 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) |
@@ -437,13 +411,13 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
437 | struct ccid3_options_received *opt_recv; | 411 | struct ccid3_options_received *opt_recv; |
438 | struct dccp_tx_hist_entry *packet; | 412 | struct dccp_tx_hist_entry *packet; |
439 | struct timeval now; | 413 | struct timeval now; |
440 | unsigned long next_tmout; | 414 | unsigned long t_nfb; |
441 | u32 t_elapsed; | 415 | u32 t_elapsed; |
442 | u32 pinv; | 416 | u32 pinv; |
443 | u32 x_recv; | 417 | u32 x_recv; |
444 | u32 r_sample; | 418 | u32 r_sample; |
445 | 419 | ||
446 | BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); | 420 | BUG_ON(hctx == NULL); |
447 | 421 | ||
448 | /* we are only interested in ACKs */ | 422 | /* we are only interested in ACKs */ |
449 | if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || | 423 | if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || |
@@ -457,9 +431,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
457 | pinv = opt_recv->ccid3or_loss_event_rate; | 431 | pinv = opt_recv->ccid3or_loss_event_rate; |
458 | 432 | ||
459 | switch (hctx->ccid3hctx_state) { | 433 | switch (hctx->ccid3hctx_state) { |
460 | case TFRC_SSTATE_NO_SENT: | ||
461 | /* FIXME: what to do here? */ | ||
462 | return; | ||
463 | case TFRC_SSTATE_NO_FBACK: | 434 | case TFRC_SSTATE_NO_FBACK: |
464 | case TFRC_SSTATE_FBACK: | 435 | case TFRC_SSTATE_FBACK: |
465 | /* Calculate new round trip sample by | 436 | /* Calculate new round trip sample by |
@@ -468,11 +439,10 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
468 | packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, | 439 | packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, |
469 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 440 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
470 | if (unlikely(packet == NULL)) { | 441 | if (unlikely(packet == NULL)) { |
471 | LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno " | 442 | DCCP_WARN("%s, sk=%p, seqno %llu(%s) does't exist " |
472 | "%llu(%s) does't exist in history!\n", | 443 | "in history!\n", dccp_role(sk), sk, |
473 | __FUNCTION__, dccp_role(sk), sk, | ||
474 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, | 444 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, |
475 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); | 445 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); |
476 | return; | 446 | return; |
477 | } | 447 | } |
478 | 448 | ||
@@ -480,9 +450,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
480 | dccp_timestamp(sk, &now); | 450 | dccp_timestamp(sk, &now); |
481 | r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); | 451 | r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); |
482 | if (unlikely(r_sample <= t_elapsed)) | 452 | if (unlikely(r_sample <= t_elapsed)) |
483 | LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, " | 453 | DCCP_WARN("r_sample=%uus,t_elapsed=%uus\n", |
484 | "t_elapsed=%uus\n", | 454 | r_sample, t_elapsed); |
485 | __FUNCTION__, r_sample, t_elapsed); | ||
486 | else | 455 | else |
487 | r_sample -= t_elapsed; | 456 | r_sample -= t_elapsed; |
488 | 457 | ||
@@ -495,20 +464,26 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
495 | * q is a constant, RFC 3448 recomments 0.9 | 464 | * q is a constant, RFC 3448 recomments 0.9 |
496 | */ | 465 | */ |
497 | if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { | 466 | if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { |
467 | /* Use Larger Initial Windows [RFC 4342, sec. 5] | ||
468 | * We deviate in that we use `s' instead of `MSS'. */ | ||
469 | u16 w_init = max( 4 * hctx->ccid3hctx_s, | ||
470 | max(2 * hctx->ccid3hctx_s, 4380)); | ||
471 | hctx->ccid3hctx_rtt = r_sample; | ||
472 | hctx->ccid3hctx_x = usecs_div(w_init, r_sample); | ||
473 | hctx->ccid3hctx_t_ld = now; | ||
474 | |||
475 | ccid3_update_send_time(hctx); | ||
498 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); | 476 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); |
499 | hctx->ccid3hctx_rtt = r_sample; | 477 | } else { |
500 | } else | ||
501 | hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + | 478 | hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + |
502 | r_sample / 10; | 479 | r_sample / 10; |
480 | ccid3_hc_tx_update_x(sk, &now); | ||
481 | } | ||
503 | 482 | ||
504 | ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " | 483 | ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " |
505 | "r_sample=%us\n", dccp_role(sk), sk, | 484 | "r_sample=%us\n", dccp_role(sk), sk, |
506 | hctx->ccid3hctx_rtt, r_sample); | 485 | hctx->ccid3hctx_rtt, r_sample); |
507 | 486 | ||
508 | /* Update timeout interval */ | ||
509 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, | ||
510 | USEC_PER_SEC); | ||
511 | |||
512 | /* Update receive rate */ | 487 | /* Update receive rate */ |
513 | hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */ | 488 | hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */ |
514 | 489 | ||
@@ -528,49 +503,41 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
528 | /* unschedule no feedback timer */ | 503 | /* unschedule no feedback timer */ |
529 | sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); | 504 | sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); |
530 | 505 | ||
531 | /* Update sending rate */ | ||
532 | ccid3_hc_tx_update_x(sk); | ||
533 | |||
534 | /* Update next send time */ | ||
535 | timeval_sub_usecs(&hctx->ccid3hctx_t_nom, | ||
536 | hctx->ccid3hctx_t_ipi); | ||
537 | ccid3_calc_new_t_ipi(hctx); | ||
538 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, | ||
539 | hctx->ccid3hctx_t_ipi); | ||
540 | ccid3_calc_new_delta(hctx); | ||
541 | |||
542 | /* remove all packets older than the one acked from history */ | 506 | /* remove all packets older than the one acked from history */ |
543 | dccp_tx_hist_purge_older(ccid3_tx_hist, | 507 | dccp_tx_hist_purge_older(ccid3_tx_hist, |
544 | &hctx->ccid3hctx_hist, packet); | 508 | &hctx->ccid3hctx_hist, packet); |
545 | /* | 509 | /* |
546 | * As we have calculated new ipi, delta, t_nom it is possible that | 510 | * As we have calculated new ipi, delta, t_nom it is possible that |
547 | * we now can send a packet, so wake up dccp_wait_for_ccids. | 511 | * we now can send a packet, so wake up dccp_wait_for_ccid |
548 | */ | 512 | */ |
549 | sk->sk_write_space(sk); | 513 | sk->sk_write_space(sk); |
550 | 514 | ||
515 | /* Update timeout interval. We use the alternative variant of | ||
516 | * [RFC 3448, 3.1] which sets the upper bound of t_rto to one | ||
517 | * second, as it is suggested for TCP (see RFC 2988, 2.4). */ | ||
518 | hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, | ||
519 | USEC_PER_SEC ); | ||
551 | /* | 520 | /* |
552 | * Schedule no feedback timer to expire in | 521 | * Schedule no feedback timer to expire in |
553 | * max(4 * R, 2 * s / X) | 522 | * max(4 * R, 2 * s/X) = max(4 * R, 2 * t_ipi) |
554 | */ | 523 | */ |
555 | next_tmout = max(hctx->ccid3hctx_t_rto, | 524 | t_nfb = max(4 * hctx->ccid3hctx_rtt, 2 * hctx->ccid3hctx_t_ipi); |
556 | 2 * usecs_div(hctx->ccid3hctx_s, | ||
557 | hctx->ccid3hctx_x)); | ||
558 | 525 | ||
559 | ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " | 526 | ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " |
560 | "expire in %lu jiffies (%luus)\n", | 527 | "expire in %lu jiffies (%luus)\n", |
561 | dccp_role(sk), sk, | 528 | dccp_role(sk), sk, |
562 | usecs_to_jiffies(next_tmout), next_tmout); | 529 | usecs_to_jiffies(t_nfb), t_nfb); |
563 | 530 | ||
564 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, | 531 | sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, |
565 | jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout))); | 532 | jiffies + usecs_to_jiffies(t_nfb)); |
566 | 533 | ||
567 | /* set idle flag */ | 534 | /* set idle flag */ |
568 | hctx->ccid3hctx_idle = 1; | 535 | hctx->ccid3hctx_idle = 1; |
569 | break; | 536 | break; |
570 | default: | 537 | case TFRC_SSTATE_NO_SENT: |
571 | printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", | 538 | DCCP_WARN("Illegal ACK received - no packet has been sent\n"); |
572 | __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); | 539 | /* fall through */ |
573 | dump_stack(); | 540 | case TFRC_SSTATE_TERM: /* ignore feedback when closing */ |
574 | break; | 541 | break; |
575 | } | 542 | } |
576 | } | 543 | } |
@@ -610,9 +577,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
610 | switch (option) { | 577 | switch (option) { |
611 | case TFRC_OPT_LOSS_EVENT_RATE: | 578 | case TFRC_OPT_LOSS_EVENT_RATE: |
612 | if (unlikely(len != 4)) { | 579 | if (unlikely(len != 4)) { |
613 | LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " | 580 | DCCP_WARN("%s, sk=%p, invalid len %d " |
614 | "len for TFRC_OPT_LOSS_EVENT_RATE\n", | 581 | "for TFRC_OPT_LOSS_EVENT_RATE\n", |
615 | __FUNCTION__, dccp_role(sk), sk); | 582 | dccp_role(sk), sk, len); |
616 | rc = -EINVAL; | 583 | rc = -EINVAL; |
617 | } else { | 584 | } else { |
618 | opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value); | 585 | opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value); |
@@ -631,9 +598,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
631 | break; | 598 | break; |
632 | case TFRC_OPT_RECEIVE_RATE: | 599 | case TFRC_OPT_RECEIVE_RATE: |
633 | if (unlikely(len != 4)) { | 600 | if (unlikely(len != 4)) { |
634 | LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " | 601 | DCCP_WARN("%s, sk=%p, invalid len %d " |
635 | "len for TFRC_OPT_RECEIVE_RATE\n", | 602 | "for TFRC_OPT_RECEIVE_RATE\n", |
636 | __FUNCTION__, dccp_role(sk), sk); | 603 | dccp_role(sk), sk, len); |
637 | rc = -EINVAL; | 604 | rc = -EINVAL; |
638 | } else { | 605 | } else { |
639 | opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value); | 606 | opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value); |
@@ -649,18 +616,9 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
649 | 616 | ||
650 | static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) | 617 | static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) |
651 | { | 618 | { |
652 | struct dccp_sock *dp = dccp_sk(sk); | ||
653 | struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); | 619 | struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); |
654 | 620 | ||
655 | if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && | 621 | hctx->ccid3hctx_s = 0; |
656 | dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) | ||
657 | hctx->ccid3hctx_s = dp->dccps_packet_size; | ||
658 | else | ||
659 | hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE; | ||
660 | |||
661 | /* Set transmission rate to 1 packet per second */ | ||
662 | hctx->ccid3hctx_x = hctx->ccid3hctx_s; | ||
663 | hctx->ccid3hctx_t_rto = USEC_PER_SEC; | ||
664 | hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; | 622 | hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; |
665 | INIT_LIST_HEAD(&hctx->ccid3hctx_hist); | 623 | INIT_LIST_HEAD(&hctx->ccid3hctx_hist); |
666 | 624 | ||
@@ -688,14 +646,7 @@ static void ccid3_hc_tx_exit(struct sock *sk) | |||
688 | * RX Half Connection methods | 646 | * RX Half Connection methods |
689 | */ | 647 | */ |
690 | 648 | ||
691 | /* TFRC receiver states */ | 649 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG |
692 | enum ccid3_hc_rx_states { | ||
693 | TFRC_RSTATE_NO_DATA = 1, | ||
694 | TFRC_RSTATE_DATA, | ||
695 | TFRC_RSTATE_TERM = 127, | ||
696 | }; | ||
697 | |||
698 | #ifdef CCID3_DEBUG | ||
699 | static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) | 650 | static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) |
700 | { | 651 | { |
701 | static char *ccid3_rx_state_names[] = { | 652 | static char *ccid3_rx_state_names[] = { |
@@ -721,6 +672,15 @@ static void ccid3_hc_rx_set_state(struct sock *sk, | |||
721 | hcrx->ccid3hcrx_state = state; | 672 | hcrx->ccid3hcrx_state = state; |
722 | } | 673 | } |
723 | 674 | ||
675 | static inline void ccid3_hc_rx_update_s(struct ccid3_hc_rx_sock *hcrx, int len) | ||
676 | { | ||
677 | if (unlikely(len == 0)) /* don't update on empty packets (e.g. ACKs) */ | ||
678 | ccid3_pr_debug("Packet payload length is 0 - not updating\n"); | ||
679 | else | ||
680 | hcrx->ccid3hcrx_s = hcrx->ccid3hcrx_s == 0 ? len : | ||
681 | (9 * hcrx->ccid3hcrx_s + len) / 10; | ||
682 | } | ||
683 | |||
724 | static void ccid3_hc_rx_send_feedback(struct sock *sk) | 684 | static void ccid3_hc_rx_send_feedback(struct sock *sk) |
725 | { | 685 | { |
726 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | 686 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); |
@@ -743,18 +703,15 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) | |||
743 | delta); | 703 | delta); |
744 | } | 704 | } |
745 | break; | 705 | break; |
746 | default: | 706 | case TFRC_RSTATE_TERM: |
747 | printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", | 707 | DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); |
748 | __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); | ||
749 | dump_stack(); | ||
750 | return; | 708 | return; |
751 | } | 709 | } |
752 | 710 | ||
753 | packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist); | 711 | packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist); |
754 | if (unlikely(packet == NULL)) { | 712 | if (unlikely(packet == NULL)) { |
755 | LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet " | 713 | DCCP_WARN("%s, sk=%p, no data packet in history!\n", |
756 | "in history!\n", | 714 | dccp_role(sk), sk); |
757 | __FUNCTION__, dccp_role(sk), sk); | ||
758 | return; | 715 | return; |
759 | } | 716 | } |
760 | 717 | ||
@@ -842,29 +799,29 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) | |||
842 | } | 799 | } |
843 | 800 | ||
844 | if (unlikely(step == 0)) { | 801 | if (unlikely(step == 0)) { |
845 | LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history " | 802 | DCCP_WARN("%s, sk=%p, packet history has no data packets!\n", |
846 | "contains no data packets!\n", | 803 | dccp_role(sk), sk); |
847 | __FUNCTION__, dccp_role(sk), sk); | ||
848 | return ~0; | 804 | return ~0; |
849 | } | 805 | } |
850 | 806 | ||
851 | if (unlikely(interval == 0)) { | 807 | if (unlikely(interval == 0)) { |
852 | LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a " | 808 | DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0." |
853 | "win_count interval > 0. Defaulting to 1\n", | 809 | "Defaulting to 1\n", dccp_role(sk), sk); |
854 | __FUNCTION__, dccp_role(sk), sk); | ||
855 | interval = 1; | 810 | interval = 1; |
856 | } | 811 | } |
857 | found: | 812 | found: |
858 | if (!tail) { | 813 | if (!tail) { |
859 | LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n", | 814 | DCCP_CRIT("tail is null\n"); |
860 | __FUNCTION__); | ||
861 | return ~0; | 815 | return ~0; |
862 | } | 816 | } |
863 | rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; | 817 | rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; |
864 | ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", | 818 | ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", |
865 | dccp_role(sk), sk, rtt); | 819 | dccp_role(sk), sk, rtt); |
866 | if (rtt == 0) | 820 | |
867 | rtt = 1; | 821 | if (rtt == 0) { |
822 | DCCP_WARN("RTT==0, setting to 1\n"); | ||
823 | rtt = 1; | ||
824 | } | ||
868 | 825 | ||
869 | dccp_timestamp(sk, &tstamp); | 826 | dccp_timestamp(sk, &tstamp); |
870 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); | 827 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); |
@@ -878,9 +835,7 @@ found: | |||
878 | tmp2 = (u32)tmp1; | 835 | tmp2 = (u32)tmp1; |
879 | 836 | ||
880 | if (!tmp2) { | 837 | if (!tmp2) { |
881 | LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 " | 838 | DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt); |
882 | "%s: x_recv = %u, rtt =%u\n", | ||
883 | __FUNCTION__, x_recv, rtt); | ||
884 | return ~0; | 839 | return ~0; |
885 | } | 840 | } |
886 | 841 | ||
@@ -926,8 +881,7 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) | |||
926 | entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC); | 881 | entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC); |
927 | 882 | ||
928 | if (entry == NULL) { | 883 | if (entry == NULL) { |
929 | printk(KERN_CRIT "%s: out of memory\n",__FUNCTION__); | 884 | DCCP_BUG("out of memory - can not allocate entry"); |
930 | dump_stack(); | ||
931 | return; | 885 | return; |
932 | } | 886 | } |
933 | 887 | ||
@@ -1002,13 +956,10 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1002 | const struct dccp_options_received *opt_recv; | 956 | const struct dccp_options_received *opt_recv; |
1003 | struct dccp_rx_hist_entry *packet; | 957 | struct dccp_rx_hist_entry *packet; |
1004 | struct timeval now; | 958 | struct timeval now; |
1005 | u8 win_count; | ||
1006 | u32 p_prev, rtt_prev, r_sample, t_elapsed; | 959 | u32 p_prev, rtt_prev, r_sample, t_elapsed; |
1007 | int loss; | 960 | int loss, payload_size; |
1008 | 961 | ||
1009 | BUG_ON(hcrx == NULL || | 962 | BUG_ON(hcrx == NULL); |
1010 | !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || | ||
1011 | hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA)); | ||
1012 | 963 | ||
1013 | opt_recv = &dccp_sk(sk)->dccps_options_received; | 964 | opt_recv = &dccp_sk(sk)->dccps_options_received; |
1014 | 965 | ||
@@ -1026,9 +977,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1026 | t_elapsed = opt_recv->dccpor_elapsed_time * 10; | 977 | t_elapsed = opt_recv->dccpor_elapsed_time * 10; |
1027 | 978 | ||
1028 | if (unlikely(r_sample <= t_elapsed)) | 979 | if (unlikely(r_sample <= t_elapsed)) |
1029 | LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, " | 980 | DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n", |
1030 | "t_elapsed=%uus\n", | 981 | r_sample, t_elapsed); |
1031 | __FUNCTION__, r_sample, t_elapsed); | ||
1032 | else | 982 | else |
1033 | r_sample -= t_elapsed; | 983 | r_sample -= t_elapsed; |
1034 | 984 | ||
@@ -1052,19 +1002,19 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1052 | packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp, | 1002 | packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp, |
1053 | skb, SLAB_ATOMIC); | 1003 | skb, SLAB_ATOMIC); |
1054 | if (unlikely(packet == NULL)) { | 1004 | if (unlikely(packet == NULL)) { |
1055 | LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to " | 1005 | DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet " |
1056 | "add rx packet to history, consider it lost!\n", | 1006 | "to history, consider it lost!\n", dccp_role(sk), sk); |
1057 | __FUNCTION__, dccp_role(sk), sk); | ||
1058 | return; | 1007 | return; |
1059 | } | 1008 | } |
1060 | 1009 | ||
1061 | win_count = packet->dccphrx_ccval; | ||
1062 | |||
1063 | loss = ccid3_hc_rx_detect_loss(sk, packet); | 1010 | loss = ccid3_hc_rx_detect_loss(sk, packet); |
1064 | 1011 | ||
1065 | if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) | 1012 | if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) |
1066 | return; | 1013 | return; |
1067 | 1014 | ||
1015 | payload_size = skb->len - dccp_hdr(skb)->dccph_doff * 4; | ||
1016 | ccid3_hc_rx_update_s(hcrx, payload_size); | ||
1017 | |||
1068 | switch (hcrx->ccid3hcrx_state) { | 1018 | switch (hcrx->ccid3hcrx_state) { |
1069 | case TFRC_RSTATE_NO_DATA: | 1019 | case TFRC_RSTATE_NO_DATA: |
1070 | ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial " | 1020 | ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial " |
@@ -1075,8 +1025,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1075 | ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA); | 1025 | ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA); |
1076 | return; | 1026 | return; |
1077 | case TFRC_RSTATE_DATA: | 1027 | case TFRC_RSTATE_DATA: |
1078 | hcrx->ccid3hcrx_bytes_recv += skb->len - | 1028 | hcrx->ccid3hcrx_bytes_recv += payload_size; |
1079 | dccp_hdr(skb)->dccph_doff * 4; | ||
1080 | if (loss) | 1029 | if (loss) |
1081 | break; | 1030 | break; |
1082 | 1031 | ||
@@ -1087,10 +1036,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1087 | ccid3_hc_rx_send_feedback(sk); | 1036 | ccid3_hc_rx_send_feedback(sk); |
1088 | } | 1037 | } |
1089 | return; | 1038 | return; |
1090 | default: | 1039 | case TFRC_RSTATE_TERM: |
1091 | printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", | 1040 | DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk); |
1092 | __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); | ||
1093 | dump_stack(); | ||
1094 | return; | 1041 | return; |
1095 | } | 1042 | } |
1096 | 1043 | ||
@@ -1107,10 +1054,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1107 | /* Scaling up by 1000000 as fixed decimal */ | 1054 | /* Scaling up by 1000000 as fixed decimal */ |
1108 | if (i_mean != 0) | 1055 | if (i_mean != 0) |
1109 | hcrx->ccid3hcrx_p = 1000000 / i_mean; | 1056 | hcrx->ccid3hcrx_p = 1000000 / i_mean; |
1110 | } else { | 1057 | } else |
1111 | printk(KERN_CRIT "%s: empty loss hist\n",__FUNCTION__); | 1058 | DCCP_BUG("empty loss history"); |
1112 | dump_stack(); | ||
1113 | } | ||
1114 | 1059 | ||
1115 | if (hcrx->ccid3hcrx_p > p_prev) { | 1060 | if (hcrx->ccid3hcrx_p > p_prev) { |
1116 | ccid3_hc_rx_send_feedback(sk); | 1061 | ccid3_hc_rx_send_feedback(sk); |
@@ -1120,22 +1065,16 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1120 | 1065 | ||
1121 | static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) | 1066 | static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) |
1122 | { | 1067 | { |
1123 | struct dccp_sock *dp = dccp_sk(sk); | ||
1124 | struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); | 1068 | struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); |
1125 | 1069 | ||
1126 | ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); | 1070 | ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); |
1127 | 1071 | ||
1128 | if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && | ||
1129 | dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) | ||
1130 | hcrx->ccid3hcrx_s = dp->dccps_packet_size; | ||
1131 | else | ||
1132 | hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE; | ||
1133 | |||
1134 | hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; | 1072 | hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; |
1135 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); | 1073 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); |
1136 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); | 1074 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); |
1137 | dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack); | 1075 | dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack); |
1138 | hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack; | 1076 | hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack; |
1077 | hcrx->ccid3hcrx_s = 0; | ||
1139 | hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */ | 1078 | hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */ |
1140 | return 0; | 1079 | return 0; |
1141 | } | 1080 | } |
@@ -1261,8 +1200,10 @@ static struct ccid_operations ccid3 = { | |||
1261 | .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, | 1200 | .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, |
1262 | }; | 1201 | }; |
1263 | 1202 | ||
1203 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG | ||
1264 | module_param(ccid3_debug, int, 0444); | 1204 | module_param(ccid3_debug, int, 0444); |
1265 | MODULE_PARM_DESC(ccid3_debug, "Enable debug messages"); | 1205 | MODULE_PARM_DESC(ccid3_debug, "Enable debug messages"); |
1206 | #endif | ||
1266 | 1207 | ||
1267 | static __init int ccid3_module_init(void) | 1208 | static __init int ccid3_module_init(void) |
1268 | { | 1209 | { |