rtt.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* include rtt1 */
  2. #include "unprtt.h"
  3. int rtt_d_flag = 0; /* debug flag; can be set by caller */
  4. /*
  5. * Calculate the RTO value based on current estimators:
  6. * smoothed RTT plus four times the deviation
  7. */
  8. #define RTT_RTOCALC(ptr) ((ptr)->rtt_srtt + (4.0 * (ptr)->rtt_rttvar))
  9. static float
  10. rtt_minmax(float rto)
  11. {
  12. if (rto < RTT_RXTMIN)
  13. rto = RTT_RXTMIN;
  14. else if (rto > RTT_RXTMAX)
  15. rto = RTT_RXTMAX;
  16. return(rto);
  17. }
  18. void
  19. rtt_init(struct rtt_info *ptr)
  20. {
  21. struct timeval tv;
  22. Gettimeofday(&tv, NULL);
  23. ptr->rtt_base = tv.tv_sec; /* # sec since 1/1/1970 at start */
  24. ptr->rtt_rtt = 0;
  25. ptr->rtt_srtt = 0;
  26. ptr->rtt_rttvar = 0.75;
  27. ptr->rtt_rto = rtt_minmax(RTT_RTOCALC(ptr));
  28. /* first RTO at (srtt + (4 * rttvar)) = 3 seconds */
  29. }
  30. /* end rtt1 */
  31. /*
  32. * Return the current timestamp.
  33. * Our timestamps are 32-bit integers that count milliseconds since
  34. * rtt_init() was called.
  35. */
  36. /* include rtt_ts */
  37. uint32_t
  38. rtt_ts(struct rtt_info *ptr)
  39. {
  40. uint32_t ts;
  41. struct timeval tv;
  42. Gettimeofday(&tv, NULL);
  43. ts = ((tv.tv_sec - ptr->rtt_base) * 1000) + (tv.tv_usec / 1000);
  44. return(ts);
  45. }
  46. void
  47. rtt_newpack(struct rtt_info *ptr)
  48. {
  49. ptr->rtt_nrexmt = 0;
  50. }
  51. int
  52. rtt_start(struct rtt_info *ptr)
  53. {
  54. return((int) (ptr->rtt_rto + 0.5)); /* round float to int */
  55. /* 4return value can be used as: alarm(rtt_start(&foo)) */
  56. }
  57. /* end rtt_ts */
  58. /*
  59. * A response was received.
  60. * Stop the timer and update the appropriate values in the structure
  61. * based on this packet's RTT. We calculate the RTT, then update the
  62. * estimators of the RTT and its mean deviation.
  63. * This function should be called right after turning off the
  64. * timer with alarm(0), or right after a timeout occurs.
  65. */
  66. /* include rtt_stop */
  67. void
  68. rtt_stop(struct rtt_info *ptr, uint32_t ms)
  69. {
  70. double delta;
  71. ptr->rtt_rtt = ms / 1000.0; /* measured RTT in seconds */
  72. /*
  73. * Update our estimators of RTT and mean deviation of RTT.
  74. * See Jacobson's SIGCOMM '88 paper, Appendix A, for the details.
  75. * We use floating point here for simplicity.
  76. */
  77. delta = ptr->rtt_rtt - ptr->rtt_srtt;
  78. ptr->rtt_srtt += delta / 8; /* g = 1/8 */
  79. if (delta < 0.0)
  80. delta = -delta; /* |delta| */
  81. ptr->rtt_rttvar += (delta - ptr->rtt_rttvar) / 4; /* h = 1/4 */
  82. ptr->rtt_rto = rtt_minmax(RTT_RTOCALC(ptr));
  83. }
  84. /* end rtt_stop */
  85. /*
  86. * A timeout has occurred.
  87. * Return -1 if it's time to give up, else return 0.
  88. */
  89. /* include rtt_timeout */
  90. int
  91. rtt_timeout(struct rtt_info *ptr)
  92. {
  93. ptr->rtt_rto *= 2; /* next RTO */
  94. if (++ptr->rtt_nrexmt > RTT_MAXNREXMT)
  95. return(-1); /* time to give up for this packet */
  96. return(0);
  97. }
  98. /* end rtt_timeout */
  99. /*
  100. * Print debugging information on stderr, if the "rtt_d_flag" is nonzero.
  101. */
  102. void
  103. rtt_debug(struct rtt_info *ptr)
  104. {
  105. if (rtt_d_flag == 0)
  106. return;
  107. fprintf(stderr, "rtt = %.3f, srtt = %.3f, rttvar = %.3f, rto = %.3f\n",
  108. ptr->rtt_rtt, ptr->rtt_srtt, ptr->rtt_rttvar, ptr->rtt_rto);
  109. fflush(stderr);
  110. }