Flow control vs. congestion control: Flow control mean preventing the source from sending data that the sink will end up dropping because it runs out of buffer space. This is fairly easy with a sliding window protocol--just make sure the source's window is no larger than the free space in the sink's buffer. TCP does this by letting the sink advertise its free buffer space in the window field of the acks. Congestion control means preventing (or trying to prevent) the source from sending data that will end up getting dropped by a router because its queue is full. This is more complicated, because packets from different sources travelling different paths can converge on the same queue. In a connection-oriented network: Admission control and policers can be used to avoid congestion. Before a source starts sending data, it sets up a connection, which requires permission from the routers/switches along the path. If the requested resources are unavailable, the connection is not set up. Once the connection is set up, policers at the edge of the network can make sure the source does not send more than it was allowed to. In a connectionless network: Congestion is unavoidable, because the routers are not warned ahead of time that a source will be sending packets along some path. Congestion can, however, be managed, if sources are informed when their packets encounter congestion and they slow down. Congestion collapse: When a packet is dropped in the network, all the resources that it used on the way from the source to the place where it got dropped are wasted, instead of being used to carry some other packet that actually would have reached its destination. As the number of packets entering the network increases, the number of packets reaching destinations increases at first, but then starts to fall toward zero, because nearly all the network resources are being used to carry packets partway before they get dropped. This is called congestion collapse, and it happened on the Internet in 1987. Because of this resource-wasting effect, the only way to prevent congestion is to prevent too many packets from entering the network. Congestion signals: There are several ways end hosts can learn that the network path they are using is congested: * Lost packets: When there are too many packets trying to use the same path, the network has no choice but to drop some. This is not the only cause of lost packets, but it is the most common cause on the Internet. * Delayed packets: When the traffic load increases, the router queues get more full, causing network delays to increase. * Explicit notification: Congested routers can alter packet headers to notify end hosts of congestion. A recent proposal (Explicit Congestion Notification, RFC 2481) would use two bits of the TOS field in the IP header, one for sources to indicate that they (and the corresponding sink) understand ECN, and one for routers to indicate that they are experiencing congestion. When the sink sees the experience bit set, it sends a signal back to the source (probably by setting a bit in a packet it would have sent anyway, like an ack). TCP congestion control (RFC 2581): Before 1988, the only restriction on the source's window was that it be no more than the receiver's advertised window. That provided flow control, but not congestion control. TCP-Tahoe (1988) included window adjustment algorithms called congestion avoidance and slow-start (developed by Van Jacobson). The new restriction on the source's window is: window <= min(receiver's window, congestion window) The first term is for flow control, the second is for congestion control. Limiting the window limits the rate at which the source can send, because it can send at most one window per round-trip time. congestion avoidance: Every round-trip time, increase the congestion window by one packet (because it takes one round-trip time to learn that no congestion has resulted from the previous increase). Whenever there is a timeout (missing ack), reset the congestion window to one (or two) packets. (This would be sufficient by itself, but slow-start improves efficiency.) slow-start: Start with a window of one (or two) packets, and double it every round-trip time (typically by increasing the window one packet for every received ack) until we reach a threshhold, then switch to congestion avoidance. Whenever there is a timeout, set the threshhold to half the amount of data in flight and do slow start again. (Perhaps this should be called fast-start, because it's much faster than congestion avoidance. But it was called slow-start because it's much slower than sending a whole receiver's-window of data in a burst at the beginning, which is what the older TCP often did.)