home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / email / vanj.88feb23.txt < prev    next >
Internet Message Format  |  1997-09-26  |  13KB

  1. Path: kinetics!zehntel!varian!ptsfa!ames!eos!aurora!labrea!decwrl!decvax!ucbvax
  2. !LBL-CSAM.ARPA!van
  3. From: van@LBL-CSAM.ARPA (Van Jacobson)
  4. Newsgroups: comp.protocols.tcp-ip
  5. Subject: more on tcp congestion control
  6. Message-ID: <8802230539.AA24469@lbl-csam.arpa>
  7. Date: 23 Feb 88 05:39:37 GMT
  8. Sender: daemon@ucbvax.BERKELEY.EDU
  9. Organization: The Internet
  10. Lines: 257
  11.  
  12. Phil -
  13.  
  14. Thanks for correcting the CUTE reference (I've got to start
  15. putting JSAC and COM in separate piles) and thanks for your
  16. interesting message on changes to the ka9q package.  You
  17. bring up a lot of things that I should have covered so I'm
  18. cc'ing this reply to the tcp/ip list (in the unlikely event
  19. that anyone else is interested).
  20.  
  21. > I suggest rounding your computed RTO values up to the next
  22. > highest number of ticks when setting the timer. This is
  23. > especially important when you calculate retransmission timeouts
  24. > based on mean deviations, since they can be very small.
  25. > Otherwise it's possible for truncation effects to set the timer
  26. > LESS than the current SRTT.
  27.  
  28. Good point.  I should have edited that timer msg I inserted
  29. because it contained several rounding errors.  The line
  30.  
  31.     rto = (Avg >> 3) + (Mdev >> 1);
  32.  
  33. should have read
  34.  
  35.     rto = ((Avg >> 2) + Mdev + 3) >> 1;
  36.  
  37. which is how things read in the timer rfc & the bsd code -- Avg
  38. could also be rounded but it doesn't make much practical
  39. difference.  The mysterious "+ 3" is half a tick for rounding
  40. plus one tick because the send is phased randomly with respect
  41. to the clock (i.e., there's a +-1/2 tick uncertainty in when
  42. the timer goes off).  Also, because of the timer uncertainty, the
  43. minimum value for rto should be two ticks.  You can save a
  44. "if (rto < 2) rto = 2" step, at the cost of a half-tick bias
  45. in rto, if you make the above
  46.  
  47.     rto = ((Avg >> 2) + Mdev + 4) >> 1;
  48.  
  49. > 3. When you refer to "packets" in the context of setting the
  50. > congestion window in TCP, what do you mean? One MSS?
  51.  
  52. Yes, by "packet" without a qualifier (such as "arbitrary size
  53. packet") I always mean a one MSS sized packet.
  54.  
  55. > I tried that first, but I ran into problems. When I have an
  56. > entire SLIP link to myself, the mean deviation sits at a very
  57. > low value.  Thus the RTO sits just above the SRTT.  But when
  58. > slowstart opens up the window to send more, the round trip time
  59. > immediately increases beyond the retransmission timeout and an
  60. > unnecessary retransmission occurs.  The congestion window
  61. > oscillates rapidly, with an unnecessary retransmission in each
  62. > cycle.
  63.  
  64. I think I understand the problem (although I think you're
  65. confusing the slowstart & congestion control algorithms -- more
  66. on that in the next section) but I'm not sure I agree with the
  67. analysis.  I run tcp stuff, bind & NFS over a 2400 baud slip
  68. link from home to work and I've spent a bit of time
  69. investigating the link's behavior (waiting for the damn slow
  70. link gave me a lot of time when I couldn't do anything but
  71. investigate the link behavior :-).
  72.  
  73. Having the rtt variance in addition to the rtt is a big help
  74. when you're trying to start a bandwidth-limited link.  Since
  75. errors in the variance decay quickly, you can afford to pump it
  76. up whenever you're uncertain about how long a send is going to
  77. take.  In particular, when starting we set the variance to a
  78. `big number' (default is 3 sec but this can be overridden on a
  79. per-route basis) and the rtt to either our best estimate (also
  80. kept in the route) or zero.  After the syn packet, we'll know
  81. the rtt for a zero length packet and rttvar will get decayed by
  82. at most 25%.  As long as the the rtt for the first data packet
  83. changes by < 2*.75*bigNumber, we won't get a spurious timeout.
  84. We're free to overestimate bigNumber initially because even a
  85. factor of 10 error will be `forgotten' in 8 packet exchanges.
  86.  
  87. The same scheme applies for the 2nd and future packet exchanges.
  88. If the link is delay limited, increasing the window from one to
  89. two packets will have no effect.  If the link is bandwidth
  90. limited, doubling the window size will double the rtt.  In
  91. general, given that we know the rtt, R(W), for a window size of
  92. W, the worst case rtt change for a window size of W+dW is
  93. R(W)*dW/W.  We don't know if we'll see the worse case but the
  94. above reflects our "uncertainty" in the rtt of the next packet
  95. if we increase the window size.  Thus it should get lumped into rttvar:
  96.  
  97.     rttvar += rtt * dW/W;
  98.  
  99. During slowstart, dW is the max segment size, mss, and W is
  100. snd.cwnd so the above becomes
  101.  
  102.     rttvar += rtt * mss/snd.cwnd
  103.  
  104. before each snd.cwnd change.  (The above needs appropriate
  105. scaling and rounding but they're implemenatation dependent.
  106. Also, it overestimates the possible rtt change when snd.cwnd is
  107. small but that turns out to be desirable.)
  108.  
  109. > So I'm trying something else. I initialize the congestion window
  110. > at one MSS, but then I increase the congestion window by the
  111. > actual amount of data acked each time an ACK comes in.  This
  112. > effectively slows the slow-start algorithm so the timer can have
  113. > more time to adapt.  Or at least the congestion window
  114. > oscillation occurs at a much lower rate. What do you think?
  115.  
  116. If you mean open cwnd by MIN(amount.acked, mss), that's a real
  117. interesting idea and I'm going to think about it.  The above
  118. timer hacking takes care of spurious retransmits but there's
  119. another problem:  Slowstart is designed to prevent hitting a
  120. gateway with bursts of packets.  If you send a few small packets
  121. when the connection starts, their acks will open the window so
  122. that if you suddenly decide to send a bunch of data, you'll hit
  123. the gateway with a burst.  This small/large switch is exactly
  124. what happens in an SMTP conversation & it looks like your mod
  125. will cure the problem.
  126.  
  127. But, if you mean what you said, I don't think it's a good idea.
  128. Consider what happens when you send 1,2,3,4 and 1 is dropped.
  129. 2-4 are cached on the other side so when you retransmit 1 and
  130. fill the hole in the sequence space, all four packets will be
  131. acked.  If you increment by the amount acked, cwnd will get
  132. fully opened and you'll blast out a window's worth of
  133. back-to-back packets, almost guaranteeing another drop.
  134. (I've shown the IETF lots of pictures of this kind of stable
  135. failure mode.)
  136.  
  137. > 4. I'm confused by the modified slow-start algorithm you
  138. > described, the one that uses a threshold to change the amount
  139. > the congestion window is increased. Again, what does it mean to
  140. > increase the congestion window by 1/cwind? Is cwind in packets
  141. > (what size?) or bytes (increase the window by fractions of a
  142. > byte?)
  143.  
  144. We found it was important to distinguish startup behavior from
  145. steady-state behavior.  (It sounds as if you're lumping the two
  146. together.)  The thing we call "slow start" just has to do with
  147. starting data flowing.  The algorithm has a very short lifetime
  148. -- it typically runs for the first 3-5 rtt after you first start
  149. sending on a connection or restart after a drop.  When slow
  150. start shuts down, the link is in equilibrium (the pipe is full
  151. and you've exchanged a full window of data so you know the ack
  152. "clock" is working).  At this point another algorithm,
  153. congestion avoidance, takes over.  This algorithm is responsible
  154. for estimating how much data is needed to fill the pipe under
  155. the current (time-varying) load.  The congestion avoidance &
  156. slowstart are separate algorithms with completely different
  157. objectives.  They just happen to run consecutively and just
  158. happen to accomplish their individual objectives by twiddling
  159. the same state variable (cwnd).
  160.  
  161. The congestion avoidance algorithm is described well in DEC
  162. technical report DEC-TR-506, "Congestion Avoidance in Computer
  163. Networks with a Connectionless Network Layer" by Raj Jain, K. K.
  164. Ramakrishnan, Dah-Ming Chiu, August, 1987.  The idea is that when
  165. you try to use a window larger than the bandwidth*delay of the
  166. network path, the excess window won't fit in the pipe so it
  167. must show up in a queue somewhere.  In the usual case, "somewhere"
  168. will be the outbound queue of the slowest link in the path.
  169. That link will probably be a bottleneck for a lot of other
  170. conversations and it's likely its queue will fill up and overflow.
  171. We treat this as a signal that our window is too large and
  172. reduce it (Jain doesn't wait for an overflow -- his signal is
  173. a bit in packet that the gateway can set to say its congested.)
  174.  
  175. But the `bandwidth' in the delay-bandwidth product is *your
  176. share* of the fixed link bandwidth and your share can change as
  177. conversations using the same path come and go.  The gateway
  178. tells you when you're using too much but says nothing when
  179. you're using too little.  To find out if someone has shut down
  180. and your share is now larger, you continuously test by slowly
  181. increasing your window size until the gateway says you're using
  182. too much.  (Thus the window will oscillate around some mean
  183. value.  The algorithm is designed to do this.  But we've tried
  184. to set the adjustable parameters that determine the oscillation
  185. so that the bandwidth lost to testing the path is at most 1%.)
  186.  
  187. >From a linear system argument, you can show that best probe
  188. policy is to make your bandwidth vs. time obey dB/dt = C for
  189. some constant C.  Since B = W / R, where W is the window size
  190. and R is the round trip time, and R is constant, this says you
  191. want dW/dt = c for some other c.  In other words, in one rtt we
  192. want the window to go smoothly from size W to size W+c.  I want
  193. the algorithm to be "self clocked" so we go looking for how to
  194. do the above change using acks rather than time to drive the dW.
  195. If the max packet size is mss and we have decent silly window
  196. code, a window of W will generate at most W/mss acks and it will
  197. generate them spread out over one rtt.  Thus if we increment by
  198. c/(W/mss) = c*mss/W per ack, we will have opened the window by c
  199. after one rtt.  An appropriate c for current arpanet conditions
  200. turns out to be one mss so the increment part of the congestion
  201. avoidance turns into
  202.  
  203.     snd.cwnd += mss*mss / snd.cwnd;
  204.  
  205. (you might have to worry about the the fixed-point in this if you
  206. were trying to send small packets over a net with a large bandwidth
  207. delay product but it's not a problem in any net I know of.)
  208.  
  209. > 5. You didn't specifically mention ICMP source quench, but I
  210. > assume you mean that the congestion window should be cut in half
  211. > each time you get one.  To make this meaningful I also limit the
  212. > congestion window to be no more than the offered window. One
  213. > question: should the congestion window be allowed to decrease
  214. > below one MSS? I would say yes, but I'd like to hear your
  215. > opinion.
  216.  
  217. I didn't mention source quench because it's a disaster and I keep
  218. hoping it will go away.  There must be at least one rtt of hysteresis
  219. or "dead time" for any control algorithm to be stable.  By using
  220. packet drops and timeouts to drive things, we get this automatically.
  221. But it's very, very hard to get the right kind of hysteresis with
  222. source quench.  It's also possible to show that source quench leads
  223. to a very unfair bandwidth allocation -- SQ is preferentially 
  224. delivered to the hosts using the smallest windows (I have lots of
  225. trace data showing this and can explain why it happens but the
  226. explanation is mathematical and quite involved).
  227.  
  228. So, since SQ currently happens only when one or more packets has
  229. been dropped, all we do is close snd.cwnd down to one packet (so
  230. no more will get dropped) but we don't touch snd.ssthresh
  231. (because the slowstart time is short, ssthresh is the crucial
  232. window control, not cwnd).  Ssthresh and the rest of the
  233. congestion control stuff will get handled correctly, and with
  234. the right "time constants", when we eventually take the timeout
  235. for the lost packet.
  236.  
  237. We limit cwnd to be at most the offered window (you violate
  238. rfc793 if you ever send more than the offered window).  I don't
  239. think it's a good idea to let cwnd get below one mss.  Dropping
  240. cwnd below mss forces you to send small packets, increasing the
  241. overhead per data byte xferred.  Thus you are using the network
  242. less efficiently at a time it's heavily loaded and you really
  243. want to make the most efficient possible use of it.  This is an
  244. unstable positive feedback that can lead to collapse.  If mss is
  245. set correctly, it never makes sense to send a smaller packet.
  246.  
  247. > 6. It's interesting to note that the "set the congestion window
  248. > to one packet after a timeout" rule automatically implies the
  249. > "first-only retransmission" rule, thus simplifying my code
  250. > somewhat.  In effect, a timeout is just a very drastic source
  251. > quench.
  252.  
  253. Yes, there were several sort-of ad-hoc pieces of code, like the
  254. first-only rexmit and all the source quench handling, that were
  255. taken out because their job was handled in a more unified way by
  256. the slowstart/cong. avoidance framework -- it was very
  257. satisfying.  We removed something like 15 lines and replaced
  258. them with 6.  Of course, we then stuck in your clamped
  259. retransmit backoff algorithm, a fast retransmit algorithm (that
  260. got described at one of the IETF meetings) and a few more
  261. goodies, and ended up +3 lines from the original 4.3 code
  262. instead of the -9 we expected (not including, of course, dozens
  263. of lines of bug fixes).
  264.  
  265. I prefer to think of source quench as a poorly considered, ill
  266. behaved timeout :-).
  267.  
  268.  - Van
  269.