One of the more annoying things about Apple’s wireless routers is that there’s no way to shape the bandwidth. With two of us in the house, commonly using the Internet at the same time, and a limited 43 KB/s bandwidth, we wind up stepping on each other’s use fairly often. One bandwidth limiting tool is the Unix command trickle which allows you to control bandwidth on individual, command line programs. Something like:
trickle -u 20 -d 20 wget http://bigfiles.com/bigfile.mp3would limit the file download to 20 KB/second, about half our our bandwidth. Many commands like wget and rsync have bandwidth limiting built in, making trickle unnecessary for those programs.
These techniques don’t work when the programs don’t include limiting internally, and when you can’t run them from the command line. The program I use to download music from eMusic (eMusicJ) is an example. With my downloads refreshing in a couple days, I wanted to find a way to get my downloads in, without ruining the network for the next day and a half.
Since OS X is built on BSD, it comes with a super-sophisticated firewall, ipfw, that has traffic shaping built in. So here’s how I was able to consume only half of our bandwidth downloading music:
Start the download and use netstat -an to find the IP address of the download site (or do netstat -an before and after you’ve started the download to identify the new download IP Address):
$ netstat -an | less Active Internet connections (including servers) Proto Recv-Q Send-Q Local Address Foreign Address (state) tcp4 0 0 10.0.1.198.54176 220.127.116.11.80 ESTABLISHED tcp4 0 0 10.0.1.198.54175 18.104.22.168.80 ESTABLISHED tcp4 0 0 10.0.1.198.54142 22.214.171.124.80 ESTABLISHED tcp4 0 0 10.0.1.198.54136 126.96.36.199.80 ESTABLISHED
Set up a pipe for data coming from that site:
$ sudo ipfw add pipe 10 ip from 188.8.131.52 to any 00100 pipe 10 ip from 184.108.40.206 to any
Configure the pipe to limit bandwidth:
$ sudo ipfw pipe 10 config bw 20KBytes/s queue 10KBytes
After you're done, delete the pipe:
$ sudo ipfw list 00100 pipe 10 ip from 220.127.116.11 to any 65535 allow ip from any to any $ sudo ipfw del 00100