dccp_tfrc.c revision 1.1 1 /* $KAME: dccp_tfrc.c,v 1.16 2006/03/01 17:34:08 nishida Exp $ */
2 /* $NetBSD: dccp_tfrc.c,v 1.1 2015/02/10 19:11:52 rjs Exp $ */
3
4 /*
5 * Copyright (c) 2003 Nils-Erik Mattsson
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Id: dccp_tfrc.c,v 1.47 2003/05/28 17:36:15 nilmat-8 Exp
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: dccp_tfrc.c,v 1.1 2015/02/10 19:11:52 rjs Exp $");
36
37 #include "opt_dccp.h"
38
39 /*
40 * This implementation conforms to the drafts of DCCP dated Mars 2003.
41 * The options used are window counter, elapsed time, loss event rate
42 * and receive rate. No support for history discounting or oscillation
43 * prevention.
44 */
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/domain.h>
49 #include <sys/kernel.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/mbuf.h>
53 #include <sys/proc.h>
54 #include <sys/protosw.h>
55 #include <sys/signalvar.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/mutex.h>
59 #include <sys/sysctl.h>
60 #include <sys/syslog.h>
61 #include <sys/queue.h>
62 #include <sys/callout.h>
63
64 #include <net/if.h>
65 #include <net/route.h>
66
67 #include <netinet/in.h>
68 #include <netinet/in_systm.h>
69 #include <netinet/ip.h>
70
71 #include <netinet/in_pcb.h>
72 #include <netinet/in_var.h>
73 #include <netinet/ip_icmp.h>
74 #include <netinet/icmp_var.h>
75 #include <netinet/ip_var.h>
76
77 #include <netinet/dccp.h>
78 #include <netinet/dccp_var.h>
79 #include <netinet/dccp_tfrc.h>
80 #include <netinet/dccp_tfrc_lookup.h>
81
82 #define TFRCDEBUG
83 #if 0
84 #define TFRCDEBUGTIMERS
85 #define NOTFRCSENDER
86 #define NOTFRCRECV
87 #endif
88
89 #ifdef TFRCDEBUG
90 #ifdef __FreeBSD__
91 #define TFRC_DEBUG(args) log args
92 #else
93 #define TFRC_DEBUG(args) dccp_log args
94 #endif
95 #else
96 #define TFRC_DEBUG(args)
97 #endif
98
99 #ifdef TFRCDEBUGTIMERS
100 #ifdef __FreeBSD__
101 #define TFRC_DEBUG_TIME(args) log args
102 #else
103 #define TFRC_DEBUG_TIME(args) dccp_log args
104 #endif
105 #else
106 #define TFRC_DEBUG_TIME(args)
107 #endif
108
109 #if !defined(__FreeBSD__) || __FreeBSD_version < 500000
110 #define INP_INFO_LOCK_INIT(x,y)
111 #define INP_INFO_WLOCK(x)
112 #define INP_INFO_WUNLOCK(x)
113 #define INP_INFO_RLOCK(x)
114 #define INP_INFO_RUNLOCK(x)
115 #define INP_LOCK(x)
116 #define INP_UNLOCK(x)
117 #endif
118
119
120 /* Timeval operations */
121 const struct timeval delta_half = {0, TFRC_OPSYS_TIME_GRAN / 2};
122
123 /*
124 * Half time value struct (accurate to +- 0.5us)
125 * args: tvp - pointer to timeval structure
126 * Tested u:OK
127 */
128 #define HALFTIMEVAL(tvp) \
129 do { \
130 if ((tvp)->tv_sec & 1) \
131 (tvp)->tv_usec += 1000000; \
132 (tvp)->tv_sec = (tvp)->tv_sec >> 1; \
133 (tvp)->tv_usec = (tvp)->tv_usec >> 1; \
134 } while (0)
135
136 /* Sender side */
137
138 /* Calculate new t_ipi (inter packet interval) by
139 * t_ipi = s/X_inst;
140 * args: ccbp - pointer to sender ccb block
141 * Tested u:OK - Note: No check for x = 0 -> t_ipi = {0xFFF...,0xFFF}
142 */
143 #define CALCNEWTIPI(ccbp) \
144 do { \
145 struct fixpoint x1, y1; \
146 x1.num = ccbp->s; \
147 x1.denom = 1; \
148 fixpoint_div(&x1, &x1, &(ccbp)->x); \
149 y1.num = (ccbp)->t_ipi.tv_sec = fixpoint_getlong(&x1); \
150 y1.denom = 1; \
151 fixpoint_sub(&x1, &x1, &y1); \
152 y1.num = 1000000; \
153 y1.denom = 1; \
154 fixpoint_mul(&x1, &x1, &y1); \
155 (ccbp)->t_ipi.tv_usec = fixpoint_getlong(&x1); \
156 } while (0)
157
158 /* Calculate new delta by
159 * delta = min(t_ipi/2, t_gran/2);
160 * args: ccbp - pointer to sender ccb block
161 * Tested u:OK
162 */
163 #define CALCNEWDELTA(ccbp) \
164 do { \
165 (ccbp)->delta = delta_half; \
166 if ((ccbp)->t_ipi.tv_sec == 0 && \
167 (ccbp)->t_ipi.tv_usec < TFRC_OPSYS_TIME_GRAN) { \
168 (ccbp)->delta = (ccbp)->t_ipi; \
169 HALFTIMEVAL(&((ccbp)->delta)); \
170 } \
171 } while (0)
172
173 #ifdef TFRCDEBUG
174 #define PRINTFLOAT(x) TFRC_DEBUG((LOG_INFO, "%lld/%lld", (x)->num, (x)->denom));
175 #endif
176
177 const struct fixpoint tfrc_smallest_p = { 4LL, 1000000LL };
178
179 /* External declarations */
180 extern int dccp_get_option(char *, int, int, char *, int);
181
182 /* Forward declarations */
183 void tfrc_time_no_feedback(void *);
184 void tfrc_time_send(void *);
185 void tfrc_set_send_timer(struct tfrc_send_ccb *, struct timeval);
186 void tfrc_updateX(struct tfrc_send_ccb *, struct timeval);
187 const struct fixpoint *tfrc_calcX(u_int16_t, u_int32_t,
188 const struct fixpoint *);
189 void tfrc_send_term(void *);
190
191 static void normalize(long long *, long long *);
192 struct fixpoint *fixpoint_add(struct fixpoint *, const struct fixpoint *,
193 const struct fixpoint *);
194 struct fixpoint *fixpoint_sub(struct fixpoint *, const struct fixpoint *,
195 const struct fixpoint *);
196 int fixpoint_cmp(const struct fixpoint *, const struct fixpoint *);
197 struct fixpoint *fixpoint_mul(struct fixpoint *, const struct fixpoint *,
198 const struct fixpoint *);
199 struct fixpoint *fixpoint_div(struct fixpoint *, const struct fixpoint *,
200 const struct fixpoint *);
201 long fixpoint_getlong(const struct fixpoint *);
202
203 const struct fixpoint *flookup(const struct fixpoint *);
204 const struct fixpoint *tfrc_flookup_reverse(const struct fixpoint *);
205
206 /*
207 * Calculate the send rate according to TCP throughput eq.
208 * args: s - packet size (in bytes)
209 * R - Round trip time (in micro seconds)
210 * p - loss event rate (0<=p<=1)
211 * returns: calculated send rate (in bytes per second)
212 * Tested u:OK
213 */
214 __inline const struct fixpoint *
215 tfrc_calcX(u_int16_t s, u_int32_t r, const struct fixpoint *p)
216 {
217 static struct fixpoint x;
218
219 x.num = 1000000 * s;
220 x.denom = 1 * r;
221 fixpoint_div(&x, &x, p);
222 return &x;
223 }
224
225 /*
226 * Function called by the send timer (to send packet)
227 * args: cb - sender congestion control block
228 */
229 void
230 tfrc_time_send(void *ccb)
231 {
232 struct tfrc_send_ccb *cb = (struct tfrc_send_ccb *) ccb;
233 int s;
234 /*struct inpcb *inp;*/
235
236 if (cb->state == TFRC_SSTATE_TERM) {
237 TFRC_DEBUG((LOG_INFO,
238 "TFRC - Send timer is ordered to terminate. (tfrc_time_send)\n"));
239 return;
240 }
241 if (callout_pending(&cb->ch_stimer)) {
242 TFRC_DEBUG((LOG_INFO,
243 "TFRC - Callout pending. (tfrc_time_send)\n"));
244 return;
245 }
246 /* aquire locks for dccp_output */
247 s = splsoftnet();
248 INP_INFO_RLOCK(&dccpbinfo);
249 /*inp = cb->pcb->d_inpcb;*/
250 INP_LOCK(inp);
251 INP_INFO_RUNLOCK(&dccpbinfo);
252
253 callout_stop(&cb->ch_stimer);
254
255 dccp_output(cb->pcb, 1);
256 /* make sure we schedule next send time */
257 tfrc_send_packet_sent(cb, 0, -1);
258
259 /* release locks */
260 INP_UNLOCK(inp);
261 splx(s);
262 }
263 /*
264 * Calculate and set when the send timer should expire
265 * args: cb - sender congestion control block
266 * t_now - timeval struct containing actual time
267 * Tested u:OK
268 */
269 void
270 tfrc_set_send_timer(struct tfrc_send_ccb * cb, struct timeval t_now)
271 {
272 struct timeval t_temp;
273 long t_ticks;
274
275 /* set send timer to fire in t_ipi - (t_now-t_nom_old) or in other
276 * words after t_nom - t_now */
277 t_temp = cb->t_nom;
278 timersub(&t_temp, &t_now, &t_temp);
279
280 #ifdef TFRCDEBUG
281 if (t_temp.tv_sec < 0 || t_temp.tv_usec < 0)
282 panic("TFRC - scheduled a negative time! (tfrc_set_send_timer)");
283 #endif
284
285 t_ticks = (t_temp.tv_usec + 1000000 * t_temp.tv_sec) / (1000000 / hz);
286 if (t_ticks == 0) t_ticks = 1;
287
288 TFRC_DEBUG_TIME((LOG_INFO,
289 "TFRC scheduled send timer to expire in %ld ticks (hz=%lu)\n", t_ticks, (unsigned long)hz));
290
291 callout_reset(&cb->ch_stimer, t_ticks, tfrc_time_send, cb);
292 }
293
294 /*
295 * Update X by
296 * If (p > 0)
297 * x_calc = calcX(s,R,p);
298 * X = max(min(X_calc, 2*X_recv), s/t_mbi);
299 * Else
300 * If (t_now - tld >= R)
301 * X = max(min("2*X, 2*X_recv),s/R);
302 * tld = t_now;
303 * args: cb - sender congestion control block
304 * t_now - timeval struct containing actual time
305 * Tested u:OK
306 */
307 void
308 tfrc_updateX(struct tfrc_send_ccb * cb, struct timeval t_now)
309 {
310 struct fixpoint temp, temp2;
311 struct timeval t_temp, t_rtt = {0, 0};
312
313 /* to avoid large error in calcX */
314 if (fixpoint_cmp(&cb->p, &tfrc_smallest_p) >= 0) {
315 cb->x_calc = *tfrc_calcX(cb->s, cb->rtt, &cb->p);
316 temp = cb->x_recv;
317 temp.num *= 2;
318 if (fixpoint_cmp(&cb->x_calc, &temp) < 0)
319 temp = cb->x_calc;
320 cb->x = temp;
321 temp2.num = cb->s;
322 temp2.denom = TFRC_MAX_BACK_OFF_TIME;
323 if (fixpoint_cmp(&temp, &temp2) < 0)
324 cb->x = temp2;
325 normalize(&cb->x.num, &cb->x.denom);
326 TFRC_DEBUG((LOG_INFO, "TFRC updated send rate to "));
327 PRINTFLOAT(&cb->x);
328 TFRC_DEBUG((LOG_INFO, " bytes/s (tfrc_updateX, p>0)\n"));
329 } else {
330 t_rtt.tv_usec = cb->rtt % 1000000;
331 t_rtt.tv_sec = cb->rtt / 1000000;
332 t_temp = t_now;
333 timersub(&t_temp, &cb->t_ld, &t_temp);
334 if (timercmp(&t_temp, &t_rtt, >=)) {
335 temp = cb->x_recv;
336 temp.num *= 2;
337 temp2 = cb->x;
338 temp2.num *= 2;
339 if (fixpoint_cmp(&temp2, &temp) < 0)
340 temp = temp2;
341 cb->x.num = cb->s;
342 cb->x.denom = 1;
343 cb->x.num *= 1000000;
344 cb->x.denom *= cb->rtt;
345 if (fixpoint_cmp(&temp, &cb->x) > 0)
346 cb->x = temp;
347 normalize(&cb->x.num, &cb->x.denom);
348 cb->t_ld = t_now;
349 TFRC_DEBUG((LOG_INFO, "TFRC updated send rate to "));
350 PRINTFLOAT(&cb->x);
351 TFRC_DEBUG((LOG_INFO, " bytes/s (tfrc_updateX, p==0)\n"));
352 } else
353 TFRC_DEBUG((LOG_INFO, "TFRC didn't update send rate! (tfrc_updateX, p==0)\n"));
354 }
355 }
356
357 /*
358 * Function called by the no feedback timer
359 * args: cb - sender congestion control block
360 * Tested u:OK
361 */
362 void
363 tfrc_time_no_feedback(void *ccb)
364 {
365 struct fixpoint v, w;
366 u_int32_t next_time_out = 1; /* remove init! */
367 struct timeval t_now;
368 struct tfrc_send_ccb *cb = (struct tfrc_send_ccb *) ccb;
369
370 mutex_enter(&(cb->mutex));
371
372 if (cb->state == TFRC_SSTATE_TERM) {
373 TFRC_DEBUG((LOG_INFO, "TFRC - No feedback timer is ordered to terminate\n"));
374 goto nf_release;
375 }
376 if (callout_pending(&(cb)->ch_nftimer)) {
377 TFRC_DEBUG((LOG_INFO, "TFRC - Callout pending, exiting...(tfrc_time_no_feedback)\n"));
378 goto nf_release;
379 }
380 switch (cb->state) {
381 case TFRC_SSTATE_NO_FBACK:
382 TFRC_DEBUG((LOG_INFO, "TFRC - no feedback timer expired, state NO_FBACK\n"));
383 /* half send rate */
384 cb->x.denom *= 2;
385 v.num = cb->s;
386 v.denom *= TFRC_MAX_BACK_OFF_TIME;
387 if (fixpoint_cmp(&cb->x, &v) < 0)
388 cb->x = v;
389
390 TFRC_DEBUG((LOG_INFO, "TFRC updated send rate to "));
391 PRINTFLOAT(&cb->x);
392 TFRC_DEBUG((LOG_INFO, " bytes/s (tfrc_time_no_feedback\n"));
393
394 /* reschedule next time out */
395
396 v.num = 2;
397 v.denom = 1;
398 w.num = cb->s;
399 w.denom = 1;
400 fixpoint_mul(&v, &v, &w);
401 fixpoint_div(&v, &v, &(cb->x));
402 v.num *= 1000000;
403 normalize(&v.num, &v.denom);
404 next_time_out = v.num / v.denom;
405 if (next_time_out < TFRC_INITIAL_TIMEOUT * 1000000)
406 next_time_out = TFRC_INITIAL_TIMEOUT * 1000000;
407 break;
408 case TFRC_SSTATE_FBACK:
409 /*
410 * Check if IDLE since last timeout and recv rate is less than
411 * 4 packets per RTT
412 */
413
414 v.num = cb->s;
415 v.num *= 4;
416 v.denom *= cb->rtt;
417 v.num *= 1000000;
418 normalize(&v.num, &v.denom);
419 if (!cb->idle || fixpoint_cmp(&cb->x_recv, &v) >= 0) {
420 TFRC_DEBUG((LOG_INFO, "TFRC - no feedback timer expired, state FBACK, not idle\n"));
421 /* Half sending rate */
422
423 /*
424 * If (X_calc > 2* X_recv) X_recv = max(X_recv/2,
425 * s/(2*t_mbi)); Else X_recv = X_calc/4;
426 */
427 v.num = TFRC_SMALLEST_P;
428 v.denom = 1;
429 if (fixpoint_cmp(&cb->p, &v) < 0 && cb->x_calc.num == 0)
430 panic("TFRC - X_calc is zero! (tfrc_time_no_feedback)\n");
431
432 /* check also if p i zero -> x_calc is infinity ?? */
433 w = cb->x_recv;
434 w.num *= 2;
435 if (fixpoint_cmp(&cb->p, &v) || fixpoint_cmp(&cb->x_calc, &w) > 0) {
436 cb->x_recv.denom *= 2;
437 w.num = cb->s;
438 w.denom *= (2 * TFRC_MAX_BACK_OFF_TIME);
439 if (fixpoint_cmp(&cb->x_recv, &w) < 0)
440 cb->x_recv = w;
441 } else
442 cb->x_recv.denom *= 4;
443 normalize(&cb->x_recv.num, &cb->x_recv.denom);
444
445 /* Update sending rate */
446 microtime(&t_now);
447 tfrc_updateX(cb, t_now);
448 }
449 /* Schedule no feedback timer to expire in max(4*R, 2*s/X) */
450 v.num = cb->s;
451 v.num *= 2;
452 fixpoint_div(&v, &v, &cb->x);
453 v.num *= 1000000;
454 next_time_out = v.num / v.denom;
455 if (next_time_out < cb->t_rto)
456 next_time_out = cb->t_rto;
457 break;
458 default:
459 panic("tfrc_no_feedback: Illegal state!");
460 break;
461 }
462
463 /* Set timer */
464
465 next_time_out = next_time_out / (1000000 / hz);
466 if (next_time_out == 0)
467 next_time_out = 1;
468
469 TFRC_DEBUG_TIME((LOG_INFO, "TFRC scheduled no feedback timer to expire in %u ticks (hz=%u)\n", next_time_out, hz));
470
471 callout_reset(&cb->ch_nftimer, next_time_out, tfrc_time_no_feedback, cb);
472
473 /* set idle flag */
474 cb->idle = 1;
475 nf_release:
476 mutex_exit(&(cb->mutex));
477 }
478
479 /*
480 * Removes ccb from memory
481 * args: ccb - ccb of sender
482 */
483 void
484 tfrc_send_term(void *ccb)
485 {
486 struct tfrc_send_ccb *cb = (struct tfrc_send_ccb *) ccb;
487
488 if (ccb == 0)
489 panic("TFRC - Sender ccb is null! (free)");
490
491 /* free sender */
492
493 mutex_destroy(&(cb->mutex));
494
495 free(cb, M_PCB);
496 TFRC_DEBUG((LOG_INFO, "TFRC sender is destroyed\n"));
497 }
498
499 /* Functions declared in struct dccp_cc_sw */
500
501 /*
502 * Initialises the sender side
503 * args: pcb - dccp protocol control block
504 * returns: pointer to a tfrc_send_ccb struct on success, otherwise 0
505 * Tested u:OK
506 */
507 void *
508 tfrc_send_init(struct dccpcb * pcb)
509 {
510 struct tfrc_send_ccb *ccb;
511
512 ccb = malloc(sizeof(struct tfrc_send_ccb), M_PCB, M_NOWAIT | M_ZERO);
513 if (ccb == 0) {
514 TFRC_DEBUG((LOG_INFO, "Unable to allocate memory for tfrc_send_ccb!\n"));
515 return 0;
516 }
517 /* init sender */
518
519 mutex_init(&(ccb->mutex), MUTEX_DEFAULT, IPL_SOFTNET);
520
521 ccb->pcb = pcb;
522 if (ccb->pcb->avgpsize >= TFRC_MIN_PACKET_SIZE && ccb->pcb->avgpsize <= TFRC_MAX_PACKET_SIZE)
523 ccb->s = (u_int16_t) ccb->pcb->avgpsize;
524 else
525 ccb->s = TFRC_STD_PACKET_SIZE;
526
527 TFRC_DEBUG((LOG_INFO, "TFRC - Sender is using packet size %u\n", ccb->s));
528
529 ccb->x.num = ccb->s; /* set transmissionrate to 1 packet per second */
530 ccb->x.denom = 1;
531
532 ccb->t_ld.tv_sec = -1;
533 ccb->t_ld.tv_usec = 0;
534
535 #ifdef TFRCDEBUG
536 ccb->t_last_win_count.tv_sec = -1;
537 #endif
538 callout_init(&ccb->ch_stimer, 0);
539 callout_init(&ccb->ch_nftimer, 0);
540
541 /* init packet history */
542 TAILQ_INIT(&(ccb->hist));
543
544 ccb->state = TFRC_SSTATE_NO_SENT;
545
546 TFRC_DEBUG((LOG_INFO, "TFRC sender initialised!\n"));
547 dccpstat.tfrcs_send_conn++;
548 return ccb;
549 }
550
551 /*
552 * Free the sender side
553 * args: ccb - ccb of sender
554 * Tested u:OK
555 */
556 void
557 tfrc_send_free(void *ccb)
558 {
559 struct s_hist_entry *elm, *elm2;
560 struct tfrc_send_ccb *cb = (struct tfrc_send_ccb *) ccb;
561
562 TFRC_DEBUG((LOG_INFO, "TFRC send free called!\n"));
563
564 if (ccb == 0)
565 return;
566
567 /* uninit sender */
568
569 /* get mutex */
570 mutex_enter(&(cb->mutex));
571
572 cb->state = TFRC_SSTATE_TERM;
573 /* unschedule timers */
574 callout_stop(&cb->ch_stimer);
575 callout_stop(&cb->ch_nftimer);
576
577 /* Empty packet history */
578 elm = TAILQ_FIRST(&(cb->hist));
579 while (elm != NULL) {
580 elm2 = TAILQ_NEXT(elm, linfo);
581 free(elm, M_TEMP); /* M_TEMP ?? */
582 elm = elm2;
583 }
584 TAILQ_INIT(&(cb->hist));
585
586 mutex_exit(&(cb->mutex));
587
588 /* schedule the removal of ccb */
589 callout_reset(&cb->ch_stimer, TFRC_SEND_WAIT_TERM * hz, tfrc_send_term, cb);
590 }
591
592 /*
593 * Ask TFRC whether one can send a packet or not
594 * args: ccb - ccb block for current connection
595 * returns: 1 if ok, else 0.
596 */
597 int
598 tfrc_send_packet(void *ccb, long datasize)
599 {
600 struct s_hist_entry *new_packet;
601 u_int8_t answer = 0;
602 u_int8_t win_count = 0;
603 u_int32_t uw_win_count = 0;
604 struct timeval t_now, t_temp;
605 struct tfrc_send_ccb *cb = (struct tfrc_send_ccb *) ccb;
606 #ifdef NOTFRCSENDER
607 return 1;
608 #endif
609
610 /* check if pure ACK or Terminating */
611 if (datasize == 0 || cb->state == TFRC_SSTATE_TERM) {
612 return 1;
613 } else if (cb->state == TFRC_SSTATE_TERM) {
614 TFRC_DEBUG((LOG_INFO, "TFRC - Asked to send packet when terminating!\n"));
615 return 0;
616 }
617 /* we have data to send */
618 mutex_enter(&(cb->mutex));
619
620 /* check to see if we already have allocated memory last time */
621 new_packet = TAILQ_FIRST(&(cb->hist));
622
623 if ((new_packet != NULL && new_packet->t_sent.tv_sec >= 0) || new_packet == NULL) {
624 /* check to see if we have memory to add to packet history */
625 new_packet = malloc(sizeof(struct s_hist_entry), M_TEMP, M_NOWAIT); /* M_TEMP?? */
626 if (new_packet == NULL) {
627 TFRC_DEBUG((LOG_INFO, "TFRC - Not enough memory to add packet to packet history (send refused)! (tfrc_send_packet)\n"));
628 answer = 0;
629 dccpstat.tfrcs_send_nomem++;
630 goto sp_release;
631 }
632 new_packet->t_sent.tv_sec = -1; /* mark as unsent */
633 TAILQ_INSERT_HEAD(&(cb->hist), new_packet, linfo);
634 }
635 switch (cb->state) {
636 case TFRC_SSTATE_NO_SENT:
637 TFRC_DEBUG((LOG_INFO, "TFRC - DCCP ask permission to send first data packet (tfrc_send_packet)\n"));
638 microtime(&(cb->t_nom)); /* set nominal send time for initial packet */
639 t_now = cb->t_nom;
640
641 /* init feedback timer */
642
643 callout_reset(&cb->ch_nftimer, TFRC_INITIAL_TIMEOUT * hz, tfrc_time_no_feedback, cb);
644 win_count = 0;
645 cb->t_last_win_count = t_now;
646 TFRC_DEBUG((LOG_INFO, "TFRC - Permission granted. Scheduled no feedback timer (initial) to expire in %u ticks (hz=%u) (tfrc_send_packet)\n", TFRC_INITIAL_TIMEOUT * hz, hz));
647 /* start send timer */
648
649 /* Calculate new t_ipi */
650 CALCNEWTIPI(cb);
651 timeradd(&cb->t_nom, &cb->t_ipi, &cb->t_nom);
652 /* Calculate new delta */
653 CALCNEWDELTA(cb);
654 tfrc_set_send_timer(cb, t_now); /* if so schedule sendtimer */
655 cb->state = TFRC_SSTATE_NO_FBACK;
656 answer = 1;
657 break;
658 case TFRC_SSTATE_NO_FBACK:
659 case TFRC_SSTATE_FBACK:
660 if (!callout_pending(&cb->ch_stimer)) {
661 microtime(&t_now);
662
663 t_temp = t_now;
664 timeradd(&t_temp, &cb->delta, &t_temp);
665
666 if ((timercmp(&(t_temp), &(cb->t_nom), >))) {
667 /* Packet can be sent */
668
669 #ifdef TFRCDEBUG
670 if (cb->t_last_win_count.tv_sec == -1)
671 panic("TFRC - t_last_win_count unitialized (tfrc_send_packet)\n");
672 #endif
673 t_temp = t_now;
674 timersub(&t_temp, &(cb->t_last_win_count), &t_temp);
675
676 /* XXX calculate window counter */
677 if (cb->state == TFRC_SSTATE_NO_FBACK) {
678 /* Assume RTT = t_rto(initial)/4 */
679 uw_win_count = (t_temp.tv_sec + (t_temp.tv_usec / 1000000))
680 / TFRC_INITIAL_TIMEOUT / (4 * TFRC_WIN_COUNT_PER_RTT);
681 } else {
682 if (cb->rtt)
683 uw_win_count = (t_temp.tv_sec * 1000000 + t_temp.tv_usec)
684 / cb->rtt / TFRC_WIN_COUNT_PER_RTT;
685 else
686 uw_win_count = 0;
687 }
688 uw_win_count += cb->last_win_count;
689 win_count = uw_win_count % TFRC_WIN_COUNT_LIMIT;
690 answer = 1;
691 } else {
692 answer = 0;
693 }
694 } else {
695 answer = 0;
696 }
697 break;
698 default:
699 panic("tfrc_send_packet: Illegal state!");
700 break;
701 }
702
703 if (answer) {
704 cb->pcb->ccval = win_count;
705 new_packet->win_count = win_count;
706 }
707
708 sp_release:
709 mutex_exit(&(cb->mutex));
710 return answer;
711 }
712 /* Notify sender that a packet has been sent
713 * args: ccb - ccb block for current connection
714 * moreToSend - if there exists more packets to send
715 * dataSize - packet size
716 */
717 void
718 tfrc_send_packet_sent(void *ccb, int moreToSend, long datasize)
719 {
720 struct timeval t_now, t_temp;
721 struct s_hist_entry *packet;
722 struct tfrc_send_ccb *cb = (struct tfrc_send_ccb *) ccb;
723
724 #ifdef NOTFRCSENDER
725 return;
726 #endif
727
728 if (cb->state == TFRC_SSTATE_TERM) {
729 TFRC_DEBUG((LOG_INFO, "TFRC - Packet sent when terminating!\n"));
730 return;
731 }
732 mutex_enter(&(cb->mutex));
733 microtime(&t_now);
734
735 /* check if we have sent a data packet */
736 if (datasize > 0) {
737 /* add send time to history */
738 packet = TAILQ_FIRST(&(cb->hist));
739 if (packet == NULL)
740 panic("TFRC - Packet does not exist in history! (tfrc_send_packet_sent)");
741 else if (packet != NULL && packet->t_sent.tv_sec >= 0)
742 panic("TFRC - No unsent packet in history! (tfrc_send_packet_sent)");
743 packet->t_sent = t_now;
744 packet->seq = cb->pcb->seq_snd;
745 /* check if win_count have changed */
746 if (packet->win_count != cb->last_win_count) {
747 cb->t_last_win_count = t_now;
748 cb->last_win_count = packet->win_count;
749 }
750 TFRC_DEBUG((LOG_INFO, "TFRC - Packet sent (%llu, %u, (%lu.%lu)",
751 packet->seq, packet->win_count, packet->t_sent.tv_sec, packet->t_sent.tv_usec));
752 cb->idle = 0;
753 }
754
755 /* if timer is running, do nothing */
756 if (callout_pending(&cb->ch_stimer)) {
757 goto sps_release;
758 }
759
760 switch (cb->state) {
761 case TFRC_SSTATE_NO_SENT:
762 /* if first was pure ack */
763 if (datasize == 0) {
764 goto sps_release;
765 } else
766 panic("TFRC - First packet sent is noted as a data packet in tfrc_send_packet_sent\n");
767 break;
768 case TFRC_SSTATE_NO_FBACK:
769 case TFRC_SSTATE_FBACK:
770 if (datasize <= 0) { /* we have ack (or simulate a sent
771 * packet which never can have
772 * moreToSend */
773 moreToSend = 0;
774 } else {
775 /* Calculate new t_ipi */
776 CALCNEWTIPI(cb);
777 timeradd(&cb->t_nom, &cb->t_ipi, &cb->t_nom);
778 /* Calculate new delta */
779 CALCNEWDELTA(cb);
780 }
781
782 if (!moreToSend) {
783 /* loop until we find a send time in the future */
784 microtime(&t_now);
785 t_temp = t_now;
786 timeradd(&t_temp, &cb->delta, &t_temp);
787 while ((timercmp(&(t_temp), &(cb->t_nom), >))) {
788 /* Calculate new t_ipi */
789 CALCNEWTIPI(cb);
790 timeradd(&cb->t_nom, &cb->t_ipi, &cb->t_nom);
791
792 /* Calculate new delta */
793 CALCNEWDELTA(cb);
794
795 microtime(&t_now);
796 t_temp = t_now;
797 timeradd(&t_temp, &cb->delta, &t_temp);
798 }
799 tfrc_set_send_timer(cb, t_now);
800 } else {
801 microtime(&t_now);
802 t_temp = t_now;
803 timeradd(&t_temp, &cb->delta, &t_temp);
804
805 /* Check if next packet can not be sent immediately */
806 if (!(timercmp(&(t_temp), &(cb->t_nom), >))) {
807 tfrc_set_send_timer(cb, t_now); /* if so schedule sendtimer */
808 }
809 }
810 break;
811 default:
812 panic("tfrc_send_packet_sent: Illegal state!");
813 break;
814 }
815
816 sps_release:
817 mutex_exit(&(cb->mutex));
818 }
819 /* Notify that a an ack package was received (i.e. a feedback packet)
820 * args: ccb - ccb block for current connection
821 */
822 void
823 tfrc_send_packet_recv(void *ccb, char *options, int optlen)
824 {
825 u_int32_t next_time_out;
826 struct timeval t_now;
827 struct fixpoint x,y;
828 int res;
829 u_int16_t t_elapsed = 0;
830 u_int32_t t_elapsed_l = 0;
831 u_int32_t pinv;
832 u_int32_t x_recv;
833
834 u_int32_t r_sample;
835
836 struct s_hist_entry *elm, *elm2;
837 struct tfrc_send_ccb *cb = (struct tfrc_send_ccb *) ccb;
838
839 #ifdef NOTFRCSENDER
840 return;
841 #endif
842
843 if (cb->state == TFRC_SSTATE_TERM) {
844 TFRC_DEBUG((LOG_INFO, "TFRC - Sender received a packet when terminating!\n"));
845 return;
846 }
847 /* we are only interested in ACKs */
848 if (!(cb->pcb->type_rcv == DCCP_TYPE_ACK || cb->pcb->type_rcv == DCCP_TYPE_DATAACK))
849 return;
850
851 res = dccp_get_option(options, optlen, TFRC_OPT_LOSS_RATE, (char *) &pinv, 6);
852 if (res == 0) {
853 TFRC_DEBUG((LOG_INFO, "TFRC - Missing Loss rate option! (tfrc_send_packet_recv)\n"));
854 dccpstat.tfrcs_send_noopt++;
855 return;
856 }
857
858 res = dccp_get_option(options, optlen, DCCP_OPT_ELAPSEDTIME, (char *) &t_elapsed_l, 6);
859 if (res == 0) {
860 /* try 2 bytes elapsed time */
861 res = dccp_get_option(options, optlen, DCCP_OPT_ELAPSEDTIME, (char *) &t_elapsed, 4);
862 if (res == 0){
863 TFRC_DEBUG((LOG_INFO, "TFRC - Missing elapsed time option! (tfrc_send_packet_recv)\n"));
864 dccpstat.tfrcs_send_noopt++;
865 return;
866 }
867 }
868 res = dccp_get_option(options, optlen, TFRC_OPT_RECEIVE_RATE, (char *) &x_recv, 4);
869 if (res == 0) {
870 TFRC_DEBUG((LOG_INFO, "TFRC - Missing x_recv option! (tfrc_send_packet_recv)\n"));
871 dccpstat.tfrcs_send_noopt++;
872 return;
873 }
874 dccpstat.tfrcs_send_fbacks++;
875 /* change byte order */
876 if (t_elapsed)
877 t_elapsed = ntohs(t_elapsed);
878 else
879 t_elapsed_l = ntohl(t_elapsed_l);
880 x_recv = ntohl(x_recv);
881 pinv = ntohl(pinv);
882 if (pinv == 0xFFFFFFFF) pinv = 0;
883
884 if (t_elapsed)
885 TFRC_DEBUG((LOG_INFO, "TFRC - Receieved options on ack %llu: pinv=%u, t_elapsed=%u, x_recv=%u ! (tfrc_send_packet_recv)\n", cb->pcb->ack_rcv, pinv, t_elapsed, x_recv));
886 else
887 TFRC_DEBUG((LOG_INFO, "TFRC - Receieved options on ack %llu: pinv=%u, t_elapsed=%u, x_recv=%u ! (tfrc_send_packet_recv)\n", cb->pcb->ack_rcv, pinv, t_elapsed_l, x_recv));
888
889 mutex_enter(&(cb->mutex));
890
891 switch (cb->state) {
892 case TFRC_SSTATE_NO_FBACK:
893 case TFRC_SSTATE_FBACK:
894 /* Calculate new round trip sample by R_sample = (t_now -
895 * t_recvdata)-t_delay; */
896
897 /* get t_recvdata from history */
898 elm = TAILQ_FIRST(&(cb->hist));
899 while (elm != NULL) {
900 if (elm->seq == cb->pcb->ack_rcv)
901 break;
902 elm = TAILQ_NEXT(elm, linfo);
903 }
904
905 if (elm == NULL) {
906 TFRC_DEBUG((LOG_INFO,
907 "TFRC - Packet does not exist in history (seq=%llu)! (tfrc_send_packet_recv)", cb->pcb->ack_rcv));
908 goto sar_release;
909 }
910 /* Update RTT */
911 microtime(&t_now);
912 timersub(&t_now, &(elm->t_sent), &t_now);
913 r_sample = t_now.tv_sec * 1000000 + t_now.tv_usec;
914 if (t_elapsed)
915 r_sample = r_sample - ((u_int32_t) t_elapsed * 10); /* t_elapsed in us */
916 else
917 r_sample = r_sample - (t_elapsed_l * 10); /* t_elapsed in us */
918
919 /* Update RTT estimate by If (No feedback recv) R = R_sample;
920 * Else R = q*R+(1-q)*R_sample; */
921 if (cb->state == TFRC_SSTATE_NO_FBACK) {
922 cb->state = TFRC_SSTATE_FBACK;
923 cb->rtt = r_sample;
924 } else {
925 cb->rtt = (u_int32_t) (TFRC_RTT_FILTER_CONST * cb->rtt +
926 (1 - TFRC_RTT_FILTER_CONST) * r_sample);
927 }
928
929 TFRC_DEBUG((LOG_INFO, "TFRC - New RTT estimate %u (tfrc_send_packet_recv)\n", cb->rtt));
930
931 /* Update timeout interval */
932 cb->t_rto = 4 * cb->rtt;
933
934 /* Update receive rate */
935 x.num = x_recv;
936 y.num = 8;
937 x.denom = y.denom = 1;
938 fixpoint_div(&(cb)->x_recv, &x, &y);
939
940 /* Update loss event rate */
941 if (pinv == 0) {
942 cb->p.num = cb->p.denom = 0;
943 } else {
944 cb->p.num = 1.0;
945 cb->p.denom = pinv;
946 if (fixpoint_cmp(&cb->p, &tfrc_smallest_p) <= 0) {
947 cb->p.num = tfrc_smallest_p.num;
948 cb->p.denom = tfrc_smallest_p.denom;
949 TFRC_DEBUG((LOG_INFO, "TFRC - Smallest p used!\n"));
950 }
951 }
952
953 /* unschedule no feedback timer */
954 if (!callout_pending(&cb->ch_nftimer)) {
955 callout_stop(&cb->ch_nftimer);
956 }
957 /* Update sending rate */
958 microtime(&t_now);
959 tfrc_updateX(cb, t_now);
960
961 /* Update next send time */
962 timersub(&cb->t_nom, &cb->t_ipi, &cb->t_nom);
963
964 /* Calculate new t_ipi */
965 CALCNEWTIPI(cb);
966 timeradd(&cb->t_nom, &cb->t_ipi, &cb->t_nom);
967 /* Calculate new delta */
968 CALCNEWDELTA(cb);
969
970 if (callout_pending(&cb->ch_stimer)) {
971 callout_stop(&cb->ch_stimer);
972 }
973
974 #if 0 /* XXX do not send ack of ack so far */
975 dccp_output(cb->pcb, 1);
976 tfrc_send_packet_sent(cb, 0, -1); /* make sure we schedule next send time */
977 #endif
978
979 /* remove all packets older than the one acked from history */
980 /* elm points to acked package! */
981
982 elm2 = TAILQ_NEXT(elm, linfo);
983
984 while (elm2 != NULL) {
985 TAILQ_REMOVE(&(cb->hist), elm2, linfo);
986 free(elm2, M_TEMP);
987 elm2 = TAILQ_NEXT(elm, linfo);
988 }
989
990 /* Schedule no feedback timer to expire in max(4*R, 2*s/X) */
991 /* next_time_out = (u_int32_t) (2 * cb->s * 1000000 / cb->x); */
992
993 x.num = 2;
994 x.denom = 1;
995 y.num = cb->s;
996 y.denom = 1;
997 fixpoint_mul(&x, &x, &y);
998 fixpoint_div(&x, &x, &(cb->x));
999 x.num *= 1000000;
1000 normalize(&x.num, &x.denom);
1001 next_time_out = x.num / x.denom;
1002
1003 if (next_time_out < cb->t_rto)
1004 next_time_out = cb->t_rto;
1005 TFRC_DEBUG_TIME((LOG_INFO,
1006 "TFRC - Scheduled no feedback timer to expire in %u ticks (%u us) (hz=%u)(tfrc_send_packet_recv)\n",
1007 next_time_out / (1000000 / hz), next_time_out, hz));
1008 next_time_out = next_time_out / (1000000 / hz);
1009 if (next_time_out == 0)
1010 next_time_out = 1;
1011
1012 callout_reset(&cb->ch_nftimer, next_time_out, tfrc_time_no_feedback, cb);
1013
1014 /* set idle flag */
1015 cb->idle = 1;
1016 break;
1017 default:
1018 panic("tfrc_send_packet_recv: Illegal state!");
1019 break;
1020 }
1021 sar_release:
1022 mutex_exit(&(cb->mutex));
1023 }
1024 /* Receiver side */
1025
1026 /* Forward declarations */
1027 long tfrc_calclmean(struct tfrc_recv_ccb *);
1028 void tfrc_recv_send_feedback(struct tfrc_recv_ccb *);
1029 int tfrc_recv_add_hist(struct tfrc_recv_ccb *, struct r_hist_entry *);
1030 void tfrc_recv_detectLoss(struct tfrc_recv_ccb *);
1031 u_int32_t tfrc_recv_calcFirstLI(struct tfrc_recv_ccb *);
1032 void tfrc_recv_updateLI(struct tfrc_recv_ccb *, long, u_int8_t);
1033
1034 /* Weights used to calculate loss event rate */
1035 /* const double tfrc_recv_w[] = { 1, 1, 1, 1, 0.8, 0.6, 0.4, 0.2}; */
1036 const struct fixpoint tfrc_recv_w[] = {{1,1}, {1,1}, {1,1}, {1,1}, {4,5}, {3,5}, {2,5}, {1,5}};
1037
1038 /* Find a data packet in history
1039 * args: cb - ccb of receiver
1040 * elm - pointer to element (variable)
1041 * num - number in history (variable)
1042 * returns: elm points to found packet, otherwise NULL
1043 * Tested u:OK
1044 */
1045 #define TFRC_RECV_FINDDATAPACKET(cb,elm,num) \
1046 do { \
1047 elm = TAILQ_FIRST(&((cb)->hist)); \
1048 while ((elm) != NULL) { \
1049 if ((elm)->type == DCCP_TYPE_DATA || (elm)->type == DCCP_TYPE_DATAACK) \
1050 (num)--; \
1051 if (num == 0) \
1052 break; \
1053 elm = TAILQ_NEXT((elm), linfo); \
1054 } \
1055 } while (0)
1056
1057 /* Find next data packet in history
1058 * args: cb - ccb of receiver
1059 * elm - pointer to element (variable)
1060 * returns: elm points to found packet, otherwise NULL
1061 * Tested u:OK
1062 */
1063 #define TFRC_RECV_NEXTDATAPACKET(cb,elm) \
1064 do { \
1065 if (elm != NULL) { \
1066 elm = TAILQ_NEXT(elm, linfo); \
1067 while ((elm) != NULL && (elm)->type != DCCP_TYPE_DATA && (elm)->type != DCCP_TYPE_DATAACK) { \
1068 elm = TAILQ_NEXT((elm), linfo); \
1069 } \
1070 } \
1071 } while (0)
1072
1073 /*
1074 * Calculate avarage loss Interval I_mean
1075 * args: cb - ccb of receiver
1076 * returns: avarage loss interval
1077 * Tested u:OK
1078 */
1079 long
1080 tfrc_calclmean(struct tfrc_recv_ccb * cb)
1081 {
1082 struct li_hist_entry *elm;
1083 struct fixpoint l_tot;
1084 struct fixpoint l_tot0 = {0,0};
1085 struct fixpoint l_tot1 = {0,0};
1086 struct fixpoint W_tot = {0, 0};
1087 struct fixpoint tmp;
1088 int i;
1089 elm = TAILQ_FIRST(&(cb->li_hist));
1090
1091 for (i = 0; i < TFRC_RECV_IVAL_F_LENGTH; i++) {
1092 #ifdef TFRCDEBUG
1093 if (elm == 0)
1094 goto I_panic;
1095 #endif
1096
1097 /*
1098 I_tot0 = I_tot0 + (elm->interval * tfrc_recv_w[i]);
1099 W_tot = W_tot + tfrc_recv_w[i];
1100 */
1101 tmp.num = elm->interval;
1102 tmp.denom = 1;
1103 fixpoint_mul(&tmp, &tmp, &tfrc_recv_w[i]);
1104 fixpoint_add(&l_tot0, &l_tot0, &tmp);
1105 fixpoint_add(&W_tot, &W_tot, &tfrc_recv_w[i]);
1106
1107 elm = TAILQ_NEXT(elm, linfo);
1108 }
1109
1110 elm = TAILQ_FIRST(&(cb->li_hist));
1111 elm = TAILQ_NEXT(elm, linfo);
1112
1113 for (i = 1; i <= TFRC_RECV_IVAL_F_LENGTH; i++) {
1114 #ifdef TFRCDEBUG
1115 if (elm == 0)
1116 goto I_panic;
1117 #endif
1118 /*
1119 I_tot1 = I_tot1 + (elm->interval * tfrc_recv_w[i - 1]);
1120 */
1121 tmp.num = elm->interval;
1122 tmp.denom = 1;
1123 fixpoint_mul(&tmp, &tmp, &tfrc_recv_w[i-1]);
1124 fixpoint_add(&l_tot1, &l_tot1, &tmp);
1125
1126 elm = TAILQ_NEXT(elm, linfo);
1127 }
1128
1129 /* I_tot = max(I_tot0, I_tot1) */
1130 /*
1131 I_tot = I_tot0;
1132 if (I_tot0 < I_tot1)
1133 I_tot = I_tot1;
1134
1135 if (I_tot < W_tot)
1136 I_tot = W_tot;
1137 return (I_tot / W_tot);
1138 */
1139
1140 l_tot.num = l_tot0.num;
1141 l_tot.denom = l_tot0.denom;
1142 if (fixpoint_cmp(&l_tot0, &l_tot1) < 0){
1143 l_tot.num = l_tot1.num;
1144 l_tot.denom = l_tot1.denom;
1145 }
1146
1147 if (fixpoint_cmp(&l_tot, &W_tot) < 0){
1148 l_tot.num = W_tot.num;
1149 l_tot.denom = W_tot.denom;
1150 }
1151 fixpoint_div(&tmp, &l_tot, &W_tot);
1152 return(fixpoint_getlong(&tmp));
1153
1154 #ifdef TFRCDEBUG
1155 I_panic:
1156 panic("TFRC - Missing entry in interval history! (tfrc_calclmean)");
1157 #endif
1158 }
1159
1160 /*
1161 * Send a feedback packet
1162 * args: cb - ccb for receiver
1163 * Tested u:OK
1164 */
1165 void
1166 tfrc_recv_send_feedback(struct tfrc_recv_ccb * cb)
1167 {
1168 u_int32_t x_recv, pinv;
1169 u_int32_t t_elapsed;
1170 struct r_hist_entry *elm;
1171 struct fixpoint x;
1172 struct timeval t_now, t_temp;
1173 int num;
1174
1175 x.num = 1;
1176 x.denom = 4000000000LL; /* -> 1/p > 4 000 000 000 */
1177 if (fixpoint_cmp(&cb->p, &x) < 0)
1178 /* if (cb->p < 0.00000000025) -> 1/p > 4 000 000 000 */
1179 pinv = 0xFFFFFFFF;
1180 else {
1181 /* pinv = (u_int32_t) (1.0 / cb->p); */
1182 x.num = 1;
1183 x.denom = 1;
1184 fixpoint_div(&x, &x, &(cb)->p);
1185 pinv = fixpoint_getlong(&x);
1186 }
1187
1188 switch (cb->state) {
1189 case TFRC_RSTATE_NO_DATA:
1190 x_recv = 0;
1191 break;
1192 case TFRC_RSTATE_DATA:
1193 /* Calculate x_recv */
1194 microtime(&t_temp);
1195 timersub(&t_temp, &cb->t_last_feedback, &t_temp);
1196
1197 x_recv = (u_int32_t) (cb->bytes_recv * 8 * 1000000) / (t_temp.tv_sec * 1000000 + t_temp.tv_usec);
1198
1199 break;
1200 default:
1201 panic("tfrc_recv_send_feedback: Illegal state!");
1202 break;
1203 }
1204
1205 /* Find largest win_count so far (data packet with highest seqnum so far) */
1206 num = 1;
1207 TFRC_RECV_FINDDATAPACKET(cb, elm, num);
1208
1209 if (elm == NULL)
1210 panic("No data packet in history! (tfrc_recv_send_feedback)");
1211
1212
1213 microtime(&t_now);
1214 timersub(&t_now, &elm->t_recv, &t_now);
1215 t_elapsed = (u_int32_t) (t_now.tv_sec * 100000 + t_now.tv_usec / 10);
1216
1217 /* change byte order */
1218 t_elapsed = htonl(t_elapsed);
1219 x_recv = htonl(x_recv);
1220 pinv = htonl(pinv);
1221
1222 /* add options from variables above */
1223 if (dccp_add_option(cb->pcb, TFRC_OPT_LOSS_RATE, (char *) &pinv, 4)
1224 || dccp_add_option(cb->pcb, DCCP_OPT_ELAPSEDTIME, (char *) &t_elapsed, 4)
1225 || dccp_add_option(cb->pcb, TFRC_OPT_RECEIVE_RATE, (char *) &x_recv, 4)) {
1226 TFRC_DEBUG((LOG_INFO, "TFRC - Can't add options, aborting send feedback (tfrc_send_feedback)"));
1227 /* todo: remove options */
1228 dccpstat.tfrcs_recv_erropt++;
1229 return;
1230 }
1231 cb->pcb->ack_snd = elm->seq;
1232 cb->last_counter = elm->win_count;
1233 cb->seq_last_counter = elm->seq;
1234 microtime(&(cb->t_last_feedback));
1235 cb->bytes_recv = 0;
1236
1237 TFRC_DEBUG_TIME((LOG_INFO, "TFRC - Sending a feedback packet with (t_elapsed %u, pinv %x, x_recv %u, ack=%llu) (tfrc_recv_send_feedback)\n", ntohs(t_elapsed), ntohl(pinv), ntohl(x_recv), elm->seq));
1238
1239 dccpstat.tfrcs_recv_fbacks++;
1240 dccp_output(cb->pcb, 1);
1241 }
1242 /*
1243 * Calculate first loss interval
1244 * args: cb - ccb of the receiver
1245 * returns: loss interval
1246 * Tested u:OK
1247 */
1248 u_int32_t
1249 tfrc_recv_calcFirstLI(struct tfrc_recv_ccb * cb)
1250 {
1251 struct r_hist_entry *elm, *elm2;
1252 struct timeval t_temp;
1253 int temp;
1254 struct fixpoint x_recv, fval, t_rtt, x;
1255 const struct fixpoint *fval2;
1256 int win_count;
1257
1258 temp = 1;
1259 TFRC_RECV_FINDDATAPACKET(cb, elm, temp);
1260
1261 if (elm == NULL)
1262 panic("Packet history contains no data packets! (tfrc_recv_calcFirstLI)\n");
1263 t_temp = elm->t_recv;
1264 win_count = elm->win_count;
1265 elm2 = elm;
1266 TFRC_RECV_NEXTDATAPACKET(cb, elm2);
1267 while (elm2 != NULL) {
1268 temp = win_count - (int) (elm2->win_count);
1269 if (temp < 0)
1270 temp = temp + TFRC_WIN_COUNT_LIMIT;
1271
1272 if (temp > 4)
1273 break;
1274 elm = elm2;
1275 TFRC_RECV_NEXTDATAPACKET(cb, elm2);
1276 }
1277
1278 if (elm2 == NULL) {
1279 TFRC_DEBUG((LOG_INFO, "TFRC - Could not find a win_count interval > 4 \n"));
1280 elm2 = elm;
1281 if (temp == 0) {
1282 TFRC_DEBUG((LOG_INFO, "TFRC - Could not find a win_count interval > 0. Defaulting to 1 (tfrc_recv_calcFirstLI)\n"));
1283 temp = 1;
1284 }
1285 }
1286 timersub(&t_temp, &elm2->t_recv, &t_temp);
1287 t_rtt.num = t_temp.tv_sec * 1000000 + t_temp.tv_usec;
1288 t_rtt.denom = 1000000;
1289
1290 if (t_rtt.num < 0 && t_rtt.denom < 0) {
1291 TFRC_DEBUG((LOG_INFO, "TFRC - Approximation of RTT is negative!\n"));
1292 t_rtt.num = -t_rtt.num;
1293 t_rtt.denom = -t_rtt.denom;
1294 }
1295
1296 TFRC_DEBUG((LOG_INFO, "TFRC - Approximated rtt to "));
1297 PRINTFLOAT(&t_rtt);
1298 TFRC_DEBUG((LOG_INFO, " s (tfrc_recv_calcFirstLI)\n"));
1299
1300 /* Calculate x_recv */
1301 microtime(&t_temp);
1302 timersub(&t_temp, &cb->t_last_feedback, &t_temp);
1303 /*
1304 x_recv = (((double) (cb->bytes_recv)) /
1305 (((double) t_temp.tv_sec) + ((double) t_temp.tv_usec) / 1000000.0));
1306 */
1307 x_recv.num = cb->bytes_recv * 1000000;
1308 x_recv.denom = t_temp.tv_sec * 1000000 + t_temp.tv_usec;
1309
1310 TFRC_DEBUG((LOG_INFO, "TFRC - Receive rate XXX"));
1311 PRINTFLOAT(&x_recv);
1312 TFRC_DEBUG((LOG_INFO, " bytes/s (tfrc_recv_calcFirstLI)\n"));
1313
1314 /* fval = ((double) (cb->s)) / (x_recv * t_rtt); */
1315 fval.num = cb->s;
1316 fval.denom = 1;
1317 fixpoint_div(&fval, &fval, &x_recv);
1318 fixpoint_div(&fval, &fval, &t_rtt);
1319
1320 TFRC_DEBUG((LOG_INFO, "TFRC - Fvalue to locate XXX"));
1321 PRINTFLOAT(&fval);
1322 TFRC_DEBUG((LOG_INFO, " (tfrc_recv_calcFirstLI)\n"));
1323 fval2 = tfrc_flookup_reverse(&fval);
1324 TFRC_DEBUG((LOG_INFO, "TFRC - Lookup gives p= XXX"));
1325 PRINTFLOAT(&fval);
1326 TFRC_DEBUG((LOG_INFO, " (tfrc_recv_calcFirstLI)\n"));
1327 if (fval2->num == 0 && fval2->denom == 0)
1328 return (u_int32_t) 0xFFFFFFFF;
1329 x.num = x.denom = 1;
1330 fixpoint_div(&x, &x, fval2);
1331 return (u_int32_t) (fixpoint_getlong(&x));
1332 }
1333 /* Add packet to recv history (sorted on seqnum)
1334 * Do not add packets that are already lost
1335 * args: cb - ccb of receiver
1336 * packet - packet to insert
1337 * returns: 1 if the packet was considered lost, 0 otherwise
1338 * Tested u:OK
1339 */
1340 int
1341 tfrc_recv_add_hist(struct tfrc_recv_ccb * cb, struct r_hist_entry * packet)
1342 {
1343 struct r_hist_entry *elm, *elm2;
1344 u_int8_t num_later = 0, win_count;
1345 u_int32_t seq_num = packet->seq;
1346 int temp;
1347
1348 TFRC_DEBUG((LOG_INFO, "TFRC - Adding packet (seq=%llu,win_count=%u,type=%u,ndp=%u) to history! (tfrc_recv_add_hist)\n", packet->seq, packet->win_count, packet->type, packet->ndp));
1349
1350 if (TAILQ_EMPTY(&(cb->hist))) {
1351 TAILQ_INSERT_HEAD(&(cb->hist), packet, linfo);
1352 } else {
1353 elm = TAILQ_FIRST(&(cb->hist));
1354 if ((seq_num > elm->seq
1355 && seq_num - elm->seq < TFRC_RECV_NEW_SEQ_RANGE) ||
1356 (seq_num < elm->seq
1357 && elm->seq - seq_num > DCCP_SEQ_NUM_LIMIT - TFRC_RECV_NEW_SEQ_RANGE)) {
1358 TAILQ_INSERT_HEAD(&(cb->hist), packet, linfo);
1359 } else {
1360 if (elm->type == DCCP_TYPE_DATA || elm->type == DCCP_TYPE_DATAACK)
1361 num_later = 1;
1362
1363 elm2 = TAILQ_NEXT(elm, linfo);
1364 while (elm2 != NULL) {
1365 if ((seq_num > elm2->seq
1366 && seq_num - elm2->seq < TFRC_RECV_NEW_SEQ_RANGE) ||
1367 (seq_num < elm2->seq
1368 && elm2->seq - seq_num > DCCP_SEQ_NUM_LIMIT - TFRC_RECV_NEW_SEQ_RANGE)) {
1369 TAILQ_INSERT_AFTER(&(cb->hist), elm, packet, linfo);
1370 break;
1371 }
1372 elm = elm2;
1373 elm2 = TAILQ_NEXT(elm, linfo);
1374
1375 if (elm->type == DCCP_TYPE_DATA || elm->type == DCCP_TYPE_DATAACK)
1376 num_later++;
1377
1378 if (num_later == TFRC_RECV_NUM_LATE_LOSS) {
1379 free(packet, M_TEMP);
1380 TFRC_DEBUG((LOG_INFO, "TFRC - Packet already lost! (tfrc_recv_add_hist)\n"));
1381 return 1;
1382 break;
1383 }
1384 }
1385
1386 if (elm2 == NULL && num_later < TFRC_RECV_NUM_LATE_LOSS) {
1387 TAILQ_INSERT_TAIL(&(cb->hist), packet, linfo);
1388 }
1389 }
1390 }
1391
1392 /* trim history (remove all packets after the NUM_LATE_LOSS+1 data
1393 * packets) */
1394 if (TAILQ_FIRST(&(cb->li_hist)) != NULL) {
1395 num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
1396 TFRC_RECV_FINDDATAPACKET(cb, elm, num_later);
1397 if (elm != NULL) {
1398 elm2 = TAILQ_NEXT(elm, linfo);
1399 while (elm2 != NULL) {
1400 TAILQ_REMOVE(&(cb->hist), elm2, linfo);
1401 free(elm2, M_TEMP);
1402 elm2 = TAILQ_NEXT(elm, linfo);
1403 }
1404 }
1405 } else {
1406 /* we have no loss interval history so we need at least one
1407 * rtt:s of data packets to approximate rtt */
1408 num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
1409 TFRC_RECV_FINDDATAPACKET(cb, elm2, num_later);
1410 if (elm2 != NULL) {
1411 num_later = 1;
1412 TFRC_RECV_FINDDATAPACKET(cb, elm, num_later);
1413 win_count = elm->win_count;
1414
1415 elm = elm2;
1416 TFRC_RECV_NEXTDATAPACKET(cb, elm2);
1417 while (elm2 != NULL) {
1418 temp = win_count - (int) (elm2->win_count);
1419 if (temp < 0)
1420 temp = temp + TFRC_WIN_COUNT_LIMIT;
1421
1422 if (temp > TFRC_WIN_COUNT_PER_RTT + 1) {
1423 /* we have found a packet older than
1424 * one rtt remove the rest */
1425 elm = TAILQ_NEXT(elm2, linfo);
1426
1427 while (elm != NULL) {
1428 TAILQ_REMOVE(&(cb->hist), elm, linfo);
1429 free(elm, M_TEMP);
1430 elm = TAILQ_NEXT(elm2, linfo);
1431 }
1432 break;
1433 }
1434 elm = elm2;
1435 TFRC_RECV_NEXTDATAPACKET(cb, elm2);
1436 }
1437 } /* end if (exist atleast 4 data packets) */
1438 }
1439
1440 return 0;
1441 }
1442 /*
1443 * Detect loss events and update loss interval history
1444 * args: cb - ccb of the receiver
1445 * Tested u:OK
1446 */
1447 void
1448 tfrc_recv_detectLoss(struct tfrc_recv_ccb * cb)
1449 {
1450 struct r_hist_entry *bLoss, *aLoss, *elm, *elm2;
1451 u_int8_t num_later = TFRC_RECV_NUM_LATE_LOSS;
1452 long seq_temp = 0;
1453 long seq_loss = -1;
1454 u_int8_t win_loss = 0;
1455
1456 TFRC_RECV_FINDDATAPACKET(cb, bLoss, num_later);
1457
1458 if (bLoss == NULL) {
1459 /* not enough packets yet to cause the first loss event */
1460 } else { /* bloss != NULL */
1461 num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
1462 TFRC_RECV_FINDDATAPACKET(cb, aLoss, num_later);
1463 if (aLoss == NULL) {
1464 if (TAILQ_EMPTY(&(cb->li_hist))) {
1465 /* no loss event have occured yet */
1466
1467 /* todo: find a lost data packet by comparing
1468 * to initial seq num */
1469
1470 } else {
1471 panic("Less than 4 data packets in history (tfrc_recv_detecLossEvent)\n");
1472 }
1473 } else { /* aLoss != NULL */
1474 /* locate a lost data packet */
1475 elm = bLoss;
1476 elm2 = TAILQ_NEXT(elm, linfo);
1477 do {
1478 seq_temp = ((long) (elm->seq)) - ((long) elm2->seq);
1479
1480 if (seq_temp < 0)
1481 seq_temp = seq_temp + DCCP_SEQ_NUM_LIMIT;
1482
1483 if (seq_temp != 1) {
1484 /* check no data packets */
1485 if (elm->type == DCCP_TYPE_DATA || elm->type == DCCP_TYPE_DATAACK)
1486 seq_temp = seq_temp - 1;
1487 if (seq_temp % DCCP_NDP_LIMIT != ((int) elm->ndp - (int) elm2->ndp + DCCP_NDP_LIMIT) % DCCP_NDP_LIMIT)
1488 seq_loss = (elm2->seq + 1) % DCCP_SEQ_NUM_LIMIT;
1489 }
1490 elm = elm2;
1491 elm2 = TAILQ_NEXT(elm2, linfo);
1492 } while (elm != aLoss);
1493
1494 if (seq_loss != -1) {
1495 win_loss = aLoss->win_count;
1496 }
1497 }
1498 } /* end if (bLoss == NULL) */
1499 tfrc_recv_updateLI(cb, seq_loss, win_loss);
1500 }
1501 /* Updates the loss interval history
1502 * cb - congestion control block
1503 * seq_loss - sequence number of lost packet (-1 for none)
1504 * win_loss - window counter for previous (from the lost packet view) packet
1505 * Tested u:OK
1506 */
1507 void
1508 tfrc_recv_updateLI(struct tfrc_recv_ccb * cb, long seq_loss, u_int8_t win_loss)
1509 {
1510 struct r_hist_entry *elm;
1511 struct li_hist_entry *li_elm, *li_elm2;
1512 u_int8_t num_later = TFRC_RECV_NUM_LATE_LOSS;
1513 long seq_temp = 0;
1514 int i;
1515 u_int8_t win_start;
1516 int debug_info = 0;
1517 if (seq_loss != -1) { /* we have found a packet loss! */
1518 dccpstat.tfrcs_recv_losts++;
1519 TFRC_DEBUG((LOG_INFO, "TFRC - seqloss=%i, winloss=%i\n", (int) seq_loss, (int) win_loss));
1520 if (TAILQ_EMPTY(&(cb->li_hist))) {
1521 debug_info = 1;
1522 /* first loss detected */
1523 TFRC_DEBUG((LOG_INFO, "TFRC - First loss event detected! (tfrc_recv_updateLI)\n"));
1524 /* create history */
1525 for (i = 0; i < TFRC_RECV_IVAL_F_LENGTH + 1; i++) {
1526 li_elm = malloc(sizeof(struct li_hist_entry),
1527 M_TEMP, M_NOWAIT | M_ZERO); /* M_TEMP?? */
1528 if (li_elm == NULL) {
1529 TFRC_DEBUG((LOG_INFO, "TFRC - Not enough memory for loss interval history!\n"));
1530 /* Empty loss interval history */
1531 li_elm = TAILQ_FIRST(&(cb->li_hist));
1532 while (li_elm != NULL) {
1533 li_elm2 = TAILQ_NEXT(li_elm, linfo);
1534 free(li_elm, M_TEMP); /* M_TEMP ?? */
1535 li_elm = li_elm2;
1536 }
1537 return;
1538 }
1539 TAILQ_INSERT_HEAD(&(cb->li_hist), li_elm, linfo);
1540 }
1541
1542 li_elm->seq = seq_loss;
1543 li_elm->win_count = win_loss;
1544
1545 li_elm = TAILQ_NEXT(li_elm, linfo);
1546 /* add approx interval */
1547 li_elm->interval = tfrc_recv_calcFirstLI(cb);
1548
1549 } else { /* we have a loss interval history */
1550 debug_info = 2;
1551 /* Check if the loss is in the same loss event as
1552 * interval start */
1553 win_start = (TAILQ_FIRST(&(cb->li_hist)))->win_count;
1554 if ((win_loss > win_start
1555 && win_loss - win_start > TFRC_WIN_COUNT_PER_RTT) ||
1556 (win_loss < win_start
1557 && win_start - win_loss < TFRC_WIN_COUNT_LIMIT - TFRC_WIN_COUNT_PER_RTT)) {
1558 /* new loss event detected */
1559 /* calculate last interval length */
1560 seq_temp = seq_loss - ((long) ((TAILQ_FIRST(&(cb->li_hist)))->seq));
1561 if (seq_temp < 0)
1562 seq_temp = seq_temp + DCCP_SEQ_NUM_LIMIT;
1563
1564 (TAILQ_FIRST(&(cb->li_hist)))->interval = seq_temp;
1565
1566 TFRC_DEBUG((LOG_INFO, "TFRC - New loss event detected!, interval %i (tfrc_recv_updateLI)\n", (int) seq_temp));
1567 /* Remove oldest interval */
1568 li_elm = TAILQ_LAST(&(cb->li_hist), li_hist_head);
1569 TAILQ_REMOVE(&(cb->li_hist), li_elm, linfo);
1570
1571 /* Create the newest interval */
1572 li_elm->seq = seq_loss;
1573 li_elm->win_count = win_loss;
1574
1575 /* insert it into history */
1576 TAILQ_INSERT_HEAD(&(cb->li_hist), li_elm, linfo);
1577 } else
1578 TFRC_DEBUG((LOG_INFO, "TFRC - Loss belongs to previous loss event (tfrc_recv_updateLI)!\n"));
1579 }
1580 }
1581 if (TAILQ_FIRST(&(cb->li_hist)) != NULL) {
1582 /* calculate interval to last loss event */
1583 num_later = 1;
1584 TFRC_RECV_FINDDATAPACKET(cb, elm, num_later);
1585
1586 seq_temp = ((long) (elm->seq)) -
1587 ((long) ((TAILQ_FIRST(&(cb->li_hist)))->seq));
1588 if (seq_temp < 0)
1589 seq_temp = seq_temp + DCCP_SEQ_NUM_LIMIT;
1590
1591 (TAILQ_FIRST(&(cb->li_hist)))->interval = seq_temp;
1592 if (debug_info > 0) {
1593 TFRC_DEBUG((LOG_INFO, "TFRC - Highest data packet received %llu (tfrc_recv_updateLI)\n", elm->seq));
1594 }
1595 }
1596 }
1597
1598
1599 /* Functions declared in struct dccp_cc_sw */
1600 /* Initialises the receiver side
1601 * returns: pointer to a tfrc_recv_ccb struct on success, otherwise 0
1602 * Tested u:OK
1603 */
1604 void *
1605 tfrc_recv_init(struct dccpcb * pcb)
1606 {
1607 struct tfrc_recv_ccb *ccb;
1608
1609 ccb = malloc(sizeof(struct tfrc_recv_ccb), M_PCB, M_NOWAIT | M_ZERO);
1610 if (ccb == 0) {
1611 TFRC_DEBUG((LOG_INFO, "TFRC - Unable to allocate memory for tfrc_recv_ccb!\n"));
1612 return 0;
1613 }
1614 /* init recv here */
1615
1616 mutex_init(&(ccb->mutex), MUTEX_DEFAULT, IPL_SOFTNET);
1617
1618 ccb->pcb = pcb;
1619
1620 if (ccb->pcb->avgpsize >= TFRC_MIN_PACKET_SIZE && ccb->pcb->avgpsize <= TFRC_MAX_PACKET_SIZE)
1621 ccb->s = (u_int16_t) ccb->pcb->avgpsize;
1622 else
1623 ccb->s = TFRC_STD_PACKET_SIZE;
1624
1625 TFRC_DEBUG((LOG_INFO, "TFRC - Receiver is using packet size %u\n", ccb->s));
1626
1627 /* init packet history */
1628 TAILQ_INIT(&(ccb->hist));
1629
1630 /* init loss interval history */
1631 TAILQ_INIT(&(ccb->li_hist));
1632
1633 ccb->state = TFRC_RSTATE_NO_DATA;
1634 TFRC_DEBUG((LOG_INFO, "TFRC receiver initialised!\n"));
1635 dccpstat.tfrcs_recv_conn++;
1636 return ccb;
1637 }
1638 /* Free the receiver side
1639 * args: ccb - ccb of recevier
1640 * Tested u:OK
1641 */
1642 void
1643 tfrc_recv_free(void *ccb)
1644 {
1645 struct r_hist_entry *elm, *elm2;
1646 struct li_hist_entry *li_elm, *li_elm2;
1647 struct tfrc_recv_ccb *cb = (struct tfrc_recv_ccb *) ccb;
1648
1649 if (ccb == 0)
1650 panic("TFRC - Receiver ccb is null! (free)");
1651
1652 /* uninit recv here */
1653
1654 cb->state = TFRC_RSTATE_TERM;
1655 /* get mutex */
1656 mutex_enter(&(cb->mutex));
1657
1658 /* Empty packet history */
1659 elm = TAILQ_FIRST(&(cb->hist));
1660 while (elm != NULL) {
1661 elm2 = TAILQ_NEXT(elm, linfo);
1662 free(elm, M_TEMP); /* M_TEMP ?? */
1663 elm = elm2;
1664 }
1665 TAILQ_INIT(&(cb->hist));
1666
1667 /* Empty loss interval history */
1668 li_elm = TAILQ_FIRST(&(cb->li_hist));
1669 while (li_elm != NULL) {
1670 li_elm2 = TAILQ_NEXT(li_elm, linfo);
1671 free(li_elm, M_TEMP); /* M_TEMP ?? */
1672 li_elm = li_elm2;
1673 }
1674 TAILQ_INIT(&(cb->li_hist));
1675
1676 mutex_exit(&(cb->mutex));
1677 mutex_destroy(&(cb->mutex));
1678
1679 free(ccb, M_PCB);
1680
1681 TFRC_DEBUG((LOG_INFO, "TFRC receiver is destroyed\n"));
1682 }
1683
1684
1685 /*
1686 * Tell TFRC that a packet has been received
1687 * args: ccb - ccb block for current connection
1688 */
1689 void
1690 tfrc_recv_packet_recv(void *ccb, char *options, int optlen)
1691 {
1692 struct r_hist_entry *packet;
1693 u_int8_t win_count = 0;
1694 struct fixpoint p_prev;
1695 int ins = 0;
1696 struct tfrc_recv_ccb *cb = (struct tfrc_recv_ccb *) ccb;
1697
1698 #ifdef NOTFRCRECV
1699 return;
1700 #endif
1701
1702 if (!(cb->state == TFRC_RSTATE_NO_DATA || cb->state == TFRC_RSTATE_DATA)) {
1703 panic("TFRC - Illegal state! (tfrc_recv_packet_recv)\n");
1704 return;
1705 }
1706 /* Check which type */
1707 switch (cb->pcb->type_rcv) {
1708 case DCCP_TYPE_ACK:
1709 if (cb->state == TFRC_RSTATE_NO_DATA)
1710 return;
1711 break;
1712 case DCCP_TYPE_DATA:
1713 case DCCP_TYPE_DATAACK:
1714 break;
1715 default:
1716 TFRC_DEBUG((LOG_INFO, "TFRC - Received not data/dataack/ack packet! (tfrc_recv_packet_recv)"));
1717 return;
1718 }
1719
1720 mutex_enter(&(cb->mutex));
1721
1722 /* Add packet to history */
1723
1724 packet = malloc(sizeof(struct r_hist_entry), M_TEMP, M_NOWAIT); /* M_TEMP?? */
1725 if (packet == NULL) {
1726 TFRC_DEBUG((LOG_INFO, "TFRC - Not enough memory to add received packet to history (consider it lost)! (tfrc_recv_packet_recv)"));
1727 dccpstat.tfrcs_recv_nomem++;
1728 goto rp_release;
1729 }
1730 microtime(&(packet->t_recv));
1731 packet->seq = cb->pcb->seq_rcv;
1732 packet->type = cb->pcb->type_rcv;
1733 packet->ndp = cb->pcb->ndp_rcv;
1734
1735 /* get window counter */
1736 win_count = cb->pcb->ccval;
1737 packet->win_count = win_count;
1738
1739 ins = tfrc_recv_add_hist(cb, packet);
1740
1741 /* check if we got a data packet */
1742 if (cb->pcb->type_rcv != DCCP_TYPE_ACK) {
1743
1744 switch (cb->state) {
1745 case TFRC_RSTATE_NO_DATA:
1746 TFRC_DEBUG((LOG_INFO, "TFRC - Send an inital feedback packet (tfrc_recv_packet_recv)\n"));
1747 tfrc_recv_send_feedback(cb);
1748 cb->state = TFRC_RSTATE_DATA;
1749 break;
1750 case TFRC_RSTATE_DATA:
1751 cb->bytes_recv = cb->bytes_recv + cb->pcb->len_rcv;
1752 if (!ins) {
1753 /* find loss event */
1754 tfrc_recv_detectLoss(cb);
1755 p_prev.num = cb->p.num;
1756 p_prev.denom = cb->p.denom;
1757
1758 /* Calculate loss event rate */
1759 if (!TAILQ_EMPTY(&(cb->li_hist))) {
1760 cb->p.num = 1;
1761 cb->p.denom = tfrc_calclmean(cb);
1762 }
1763 /* check send conditions then send */
1764
1765 if (fixpoint_cmp(&(cb)->p, &p_prev) > 0) {
1766 TFRC_DEBUG((LOG_INFO, "TFRC - Send a feedback packet because p>p_prev (tfrc_recv_packet_recv)\n"));
1767 tfrc_recv_send_feedback(cb);
1768 } else {
1769 if ((cb->pcb->seq_rcv > cb->seq_last_counter
1770 && cb->pcb->seq_rcv - cb->seq_last_counter < TFRC_RECV_NEW_SEQ_RANGE) ||
1771 (cb->pcb->seq_rcv < cb->seq_last_counter
1772 && cb->seq_last_counter - cb->pcb->seq_rcv > DCCP_SEQ_NUM_LIMIT - TFRC_RECV_NEW_SEQ_RANGE)) {
1773
1774 /* the sequence number is
1775 * newer than seq_last_count */
1776 if ((win_count > cb->last_counter
1777 && win_count - cb->last_counter > TFRC_WIN_COUNT_PER_RTT) ||
1778 (win_count < cb->last_counter
1779 && cb->last_counter - win_count < TFRC_WIN_COUNT_LIMIT - TFRC_WIN_COUNT_PER_RTT)) {
1780
1781 TFRC_DEBUG((LOG_INFO, "TFRC - Send a feedback packet (%i)(win_count larger) (tfrc_recv_packet_recv)\n", (win_count - cb->last_counter + TFRC_WIN_COUNT_LIMIT) % TFRC_WIN_COUNT_LIMIT));
1782
1783 tfrc_recv_send_feedback(cb);
1784 }
1785 } /* end newer seqnum */
1786 } /* end p > p_prev */
1787
1788 }
1789 break;
1790 default:
1791 panic("tfrc_recv_packet_recv: Illegal state!");
1792 break;
1793 }
1794
1795 } /* end if not pure ack */
1796 rp_release:
1797 mutex_exit(&(cb->mutex));
1798 }
1799
1800
1801 /*
1802 * fixpoint routines
1803 */
1804 static void
1805 normalize(long long *num, long long *denom)
1806 {
1807 static const int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 0 };
1808 int i;
1809
1810 if (!*denom) return;
1811 if (*denom < 0) {
1812 *num *= (-1);
1813 *denom *= (-1);
1814 }
1815
1816 if (*num % *denom == 0) {
1817 *num /= *denom;
1818 *denom = 1;
1819 }
1820 for (i = 0; prime[i]; i++)
1821 while (*num % prime[i] == 0 && *denom % prime[i] == 0) {
1822 *num /= prime[i];
1823 *denom /= prime[i];
1824 }
1825 }
1826
1827 struct fixpoint *
1828 fixpoint_add(struct fixpoint *x, const struct fixpoint *a,
1829 const struct fixpoint *b)
1830 {
1831 long long num, denom;
1832
1833 num = a->num * b->denom + a->denom * b->num;
1834 denom = a->denom * b->denom;
1835 normalize(&num, &denom);
1836
1837 x->num = num;
1838 x->denom = denom;
1839 return (x);
1840 }
1841
1842 struct fixpoint *
1843 fixpoint_sub(struct fixpoint *x, const struct fixpoint *a,
1844 const struct fixpoint *b)
1845 {
1846 long long num, denom;
1847
1848 if (!a->denom) {
1849 x->num = -1 * b->num;
1850 x->denom = -1 * b->denom;
1851 return (x);
1852 }
1853 if (!b->denom) {
1854 x->num = a->num;
1855 x->denom = a->denom;
1856 return (x);
1857 }
1858 num = a->num * b->denom - a->denom * b->num;
1859 denom = a->denom * b->denom;
1860 normalize(&num, &denom);
1861
1862 x->num = num;
1863 x->denom = denom;
1864 return (x);
1865 }
1866
1867 int
1868 fixpoint_cmp(const struct fixpoint *a, const struct fixpoint *b)
1869 {
1870 struct fixpoint x;
1871
1872 fixpoint_sub(&x, a, b);
1873 if (x.num > 0)
1874 return (1);
1875 else if (x.num < 0)
1876 return (-1);
1877 else
1878 return (0);
1879 }
1880
1881 struct fixpoint *
1882 fixpoint_mul(struct fixpoint *x, const struct fixpoint *a,
1883 const struct fixpoint *b)
1884 {
1885 long long num, denom;
1886
1887 num = a->num * b->num;
1888 denom = a->denom * b->denom;
1889 normalize(&num, &denom);
1890
1891 x->num = num;
1892 x->denom = denom;
1893 return (x);
1894 }
1895
1896 struct fixpoint *
1897 fixpoint_div(struct fixpoint *x, const struct fixpoint *a,
1898 const struct fixpoint *b)
1899 {
1900 long long num, denom;
1901
1902 num = a->num * b->denom;
1903 denom = a->denom * b->num;
1904 normalize(&num, &denom);
1905
1906 x->num = num;
1907 x->denom = denom;
1908 return (x);
1909 }
1910
1911 long
1912 fixpoint_getlong(const struct fixpoint *x)
1913 {
1914
1915 if (x->denom == 0)
1916 return (0);
1917 return (x->num / x->denom);
1918 }
1919
1920 const struct fixpoint flargex = { 2LL, 1000LL };
1921 const struct fixpoint fsmallx = { 1LL, 100000LL };
1922 const struct fixpoint fsmallstep = { 4LL, 1000000LL };
1923
1924 /*
1925 * FLOOKUP macro. NOTE! 0<=(int x)<=1
1926 * Tested u:OK
1927 */
1928 const struct fixpoint *
1929 flookup(const struct fixpoint *x)
1930 {
1931 static const struct fixpoint y = { 250000, 1 };
1932 struct fixpoint z;
1933 int i;
1934
1935 if (fixpoint_cmp(x, &flargex) >= 0) {
1936 if (x->num == 0)
1937 return NULL;
1938 i = x->denom / x->num;
1939 #ifdef TFRCDEBUG
1940 if (i >= sizeof(flarge_table) / sizeof(flarge_table[0]))
1941 panic("flarge_table lookup failed");
1942 #endif
1943
1944 return &flarge_table[i];
1945 } else {
1946 fixpoint_mul(&z, x, &y);
1947 if (z.num == 0)
1948 return NULL;
1949 i = fixpoint_getlong(&z);
1950 #ifdef TFRCDEBUG
1951 if (i >= sizeof(fsmall_table) / sizeof(fsmall_table[0]))
1952 panic("fsmall_table lookup failed");
1953 #endif
1954
1955 return &fsmall_table[i];
1956 }
1957 }
1958
1959 /*
1960 * Inverse of the FLOOKUP above
1961 * args: fvalue - function value to match
1962 * returns: p closest to that value
1963 * Tested u:OK
1964 */
1965 const struct fixpoint *
1966 tfrc_flookup_reverse(const struct fixpoint *fvalue)
1967 {
1968 static struct fixpoint x;
1969 int ctr;
1970
1971 if (fixpoint_cmp(fvalue, &flarge_table[1]) >= 0) {
1972 /* 1.0 */
1973 x.num = 1;
1974 x.denom = 1;
1975 return &x;
1976 } else if (fixpoint_cmp(fvalue, &flarge_table[sizeof(flarge_table) /
1977 sizeof(flarge_table[0]) - 1]) >= 0) {
1978 ctr = sizeof(flarge_table) / sizeof(flarge_table[0]) - 1;
1979 while (ctr > 1 && fixpoint_cmp(fvalue, &flarge_table[ctr]) >= 0)
1980 ctr--;
1981
1982 /* round to smallest */
1983 ctr = ctr + 1;
1984
1985 /* round to nearest */
1986 return &flarge_table[ctr];
1987 } else if (fixpoint_cmp(fvalue, &fsmall_table[0]) >= 0) {
1988 ctr = 0;
1989 while (ctr < sizeof(fsmall_table) / sizeof(fsmall_table[0]) &&
1990 fixpoint_cmp(fvalue, &fsmall_table[ctr]) > 0)
1991 ctr++;
1992 x = fsmallstep;
1993 x.num *= ctr;
1994 return &x;
1995 }
1996 return &fsmallstep;
1997 }
1998