In TCP/IP terms, how does a download speed limiter in an office work?

Assume an office of people, they want to limit HTTP downloads to a max of 40% bandwidth of their internet connection speed so that it doesn't block other traffic.

We say "it's not supported in your firewall", and they say the inevitable line "we used to be able to do it with our Netgear/DLink/DrayTek".

Thinking about it, a download is like this:

HTTP GET request
Server sends file data as TCP packets
Client acknowledges receipt of TCP packets
Repeat until download finished.

The speed is determined by how fast the server sends data to you, and how fast you acknowledge it.

So, to limit download speed, you have two choices:

1) Instruct the server to send data to you more slowly - and I don't think there's any protocol feature to request that in TCP or HTTP.

2) Acknowledge packets more slowly by limiting your upload speed, and also ruin your upload speed.

How do devices do this limiting? Is there a standard way?


Solution 1:

TCP itself implements the congestion control.

These rate limiters will simply throw packets away over the limit. TCP handles this, ensuring that the packets all arrive and all arrive in order; the client doesn't ACK for the dropped packets, and they are resent by the server.

The server's TCP stack will resend the packets, and it will also dial back a bit on its send rate because it figures there's congestion between it and the client. It'll speed back up until the rate limiter drops packets again, and so on.

Solution 2:

The best description I've ever heard that made sense of TCP's inherent throttling method was off a recent Security Now podcast. To quote Steve Gibson:

So by universal agreement, TCP being this very clever protocol, it does something called a "slow start." It's generally given permission to send some number of packets without acknowledgment. So the idea being, let's just get things moving here. And typically that number is two. And so when TCP starts, it can send two packets off, one after the other. Without having the first one acknowledged, it'll send the second. But then it waits. And then the rule for throttling is we allow the number of unacknowledged packets to increase by one for every acknowledgment we receive.

So let's think about that. We allow the number of unacknowledged packets to be increased by one for every acknowledgment we receive. So we first send off two packets as our agreed-upon start. They get acknowledged. So we have our first acknowledgment. We were allowing ourselves to send two. Now, with the receipt of this first acknowledgment, we increase that by one to three. So we can now send three more packets off without any further acknowledgment. When an acknowledgment comes back for whatever we've sent before, we increase that to four. This is known as the "congestion window." It's not a window that's ever sent on the line, that is, it's not like the receive window, which is 16 bits of the TCP header that tells us how much data we're able to send ahead. This one is - it's a window. It's basically a counter maintained by the TCP stack for the purpose of avoiding connection, the idea being that at some point this is going to break.

If we keep increasing the number of unacknowledged packets we're allowed to send by one every time we receive an acknowledgment, at some point we're going to reach a limit. And the beauty of this system is that it will, as we start trying to send packets faster than the weakest link, literally link, between routers, at some point we find the point where the weakest link breaks. It drops the packets we're trying to send because we're trying to send them too fast. So acknowledgments from the other end stop because the data is no longer getting through.

And what TCP does is, if it has failed to receive - and this varies in strategies. Over time, the strategy, the actual congestion avoidance strategy has varied a lot. There's names like Tahoe and Reno, and a whole bunch of other ones that you'll see if you do some Googling and Wikipediaing, which specific exactly what the behavior is. But the idea is that, when the sender realizes that its data is no longer getting through because it's missing acknowledgments, it cuts back its sending rate quickly. Typically, it divides it in half. So it dramatically scales it back, and then goes back to increasing it.

So essentially what this means is that losing packets is the signaling function for "We can't send the data any faster," and that the TCP senders at each end of a connection, all over the Internet, are always sort of - they're trying to go faster than the maximum speed that is available between the two endpoints, that is, that weakest link, wherever that is, and they're always pushing it to the limit. So given that there is a point somewhere that is weaker than their ability to send packets, they're going to find it because they will pump packets out. As long as there's data to be sent and they've got a high bandwidth connection, the sender will increase the rate of sending, that is, the number of outstanding packets, the packets that are allowed to be out there on the fly as acknowledgments come back, aggressively keeps moving that number upwards until it pushes it too far. Then it backs off a lot, and then again moves forward.

So this is what's actually going on between TCP connections which are, like, probably, I don't know what percentage, but the vastly greatest percentage of traffic on the Internet are over TCP connections. All of our operating systems down in the kernel, in the so-called TCP stack, have these counters. And when we're sending a file, when we're uploading a big file or we're receiving a web page, the server at the other end is doing the same thing. It's pushing, on an individual connection basis, as many packets that have not yet been acknowledged out as it can, increasing the packet rate until it hits the point where it starts to fail or stutter. Then it backs off, to sort of allow things to recover, and then starts working back up again.

And so that ends up being a sort of a self-throttling system which, given the constraints, I mean, it really seems kind of funky and crude."

Solution 3:

So, to limit download speed, you have two choices:

1) Instruct the server to send data to you more slowly - and I don't think there's any protocol feature to request that in TCP or HTTP.

2) Acknowledge packets more slowly by limiting your upload speed, and also ruin your upload speed.

3) You router / firewall device puts incoming data into a QoS bucket and only empties that bucket at the rate you requested. Incoming data will adapt to that speed as computers inside will only see acknowledge receipt at that speed. Also, the occasional (purposefully) dropped packet works really well for slowing down a connection.

When trying to find a device that handles this, look for QoS (Quality of Service) in the configuration / documentation. Linux (or BSD) boxes are also handy for this.