As a result of a previous question I was informed that Tiger finally has dummynet support in the kernel. What this means to you is that now you can do traffic shaping with no additional software.
Here’s how the idea works: you create several pipes that have a set bandwidth and other properties for all packets that get filed into them; you then add queues to those pipes that determine what priority certain requests will get in that pipe; then you add actual firewall rules to identify packets and file them into queues.
So let’s say you create a pipe with 1Mbit/s of allowed traffic. Within this you would setup three queues: one for high-priority services like incoming mail, DNS requests, and such; one for medium priority services like web and FTP; then one for low-priority services like file sharing and other network “noise”. With this setup you would, on a saturated pipe have a large amount of traffic coming in and going out for web and FTP, giving it priority over the noise, and when someone wanted to talk about mail or DNS those would have a higher chance of getting handled quickly. It’s a good boost in chance, but keep in mind that traffic shaping is not Quality of Service (QoS). Traffic shaping introduces delays in lower-priority packets so that higher-priority packets get in faster, but it offers no advanced logic or guarantees on delivery. If you want QoS, use either a userspace filter that does this or another kernel (like Linux) that has this built-in. For home and moderate server use, shaping is more than acceptable.
Okay, some demonstrations are in order here. Let’s take a typical example, such as the one from the question given, and say that you’re on DSL and your upload is 384k (this is mine) and you want email uploads to only take up 300k of that so you can actually do other things. So, we create a pipe with a 300kbit/s limit for all traffic I send to it:
The hash symbol means you’ll need to be root.
# ipfw pipe 1 config bw 300kbit/s
We have a pipe now. Now we need to setup some queues for priority in this pipe. Because we set the pipe to be lower than the actual upload bandwidth, any traffic that isn’t caught by this will go through on that extra 84kbit/s of bandwidth, so we don’t need a queue for this example as nothing will be sharing this pipe; we only need one rule to catch this traffic:
# ipfw add pipe 1 dst-port smtp
This catches inbound SMTP traffic, too, if you run an SMTP server. But, of course, that’s the point: we don’t want mail to take over.
Now, of course, if you wanted to limit POP/IMAP traffic to the same queue, you could:
# ipfw add pipe 1 dst-port pop3
# ipfw add pipe 1 dst-port pop3s
# ipfw add pipe 1 dst-port imap
# ipfw add pipe 1 dst-port imaps
Now every mail-related transaction will be filed into the limited pipe causing the system to have some leftover upstream bandwidth for browsing.
Of course, within this one could see some problems. Sending a large mail will not affect web browsing, but would affect mail retrieval since they’re in the same pipe, so we need a queue for incoming and one for outgoing so that there’s some control over that share of bandwidth. You could do this with multiple pipes, but then you’re cutting out a swath of bandwidth for incoming that outbound can’t use (presuming you make two 150k pipes).
So, one would do this:
# ipfw pipe 1 config bw 300kbit/s
# ipfw queue 1 config pipe 1 weight 50
# ipfw queue 2 config pipe 1 weight 50
Now we have an equal weight between the two services. You can go from 1 to 100 on the weights if you like, but for this I’d like an even traffic stream on each. When one is finished, the other will get the full pipe. So, we add the rules in:
# ipfw add queue 1 dst-port smtp
# ipfw add queue 2 dst-port pop3
# ipfw add queue 2 dst-port pop3s
# ipfw add queue 2 dst-port imap
# ipfw add queue 2 dst-port imaps
All inbound mail goes through queue 2 and all outbound mail goes through queue 1. Each is given a high chance of getting half the bandwidth allotted to pipe 1.
You can, obviously, have a lot of fun with this, but there’s also some serious fun to be had. Web designers: ever wonder what it’s like to load your site at 56k, or 33, 28, 14, or even 9600? Do this:
# ipfw pipe 1 config bw 56kbit/s
# ipfw add pipe 1 dst-port http
Now browse the web like a modem user. This, obviously, only works for sites served on port 80, but it does work. For the record, MG should be very usable on a modem. 
If you’ve had fun playing, or locked yourself out at some point, just flush the rules:
# ipfw flush
All of this requires Mac OS X 10.4 or a FreeBSD with dummynet support. Anything else will laugh at you and order Yanni CDs from Amazon and send them to all of your friends for Christmas right before erasing the data on your computer in a spectacular flash of light that will blind you and your progeny. Best not to try. Specifically, it’ll either error out or appear to work and drop packets. The Yanni fate might be worse, so don’t risk it.
Hi there!
That’s a nice article but it has one minor flaw:
What you call priority really isn’t a priority. It only divides up the bandwidth and
does not guarantee prioritization of packets. OpenBSD has that, but OS X doesn’t.
It’s a shame, but that’s life…:(
Regards,
Kay
Right, which is why I mention a few times that this only increases the chances of a particular queue getting more time. Mac OS X has zero QoS support as far as I can tell.
—
cp
“ipfw flush” – it’s funny ;DDD
maybe “ipfw pipe flush”?
can you tell please how to exactly use this?
where do i write this, terminal? i want the sample to limit my bandwidth to test my site on localhost with MAMP. i have port 8888.
i’ve tried:
“ipfw pipe 1 config bw 16kbit/s” and it says “ipfw: socket: Operation not permitted”
i’ve tried:
“su ipfw pipe 1 config bw 16kbit/s” and it says “su: Sorry” (don’t know what password is asking for, i have only one)
Leopard.
thanks.
Great article. One thing I found while trying to do the 'modem testing' you explained, is that the commands you have listed are not enough to really test the bandwidth-limited world of 56kbps modems. You need to run ipfw three times:
# ipfw pipe 1 config bw 56kbit/s# ipfw add pipe 1 dst-port http# ipfw add pipe 1 src-port httpThat last one makes sure that data coming from the web server is also limited. Otherwise, only your outgoing data is bandwidth-limited. And, of course, web browsing is mostly (99%+) downloading.
@cristi:
use the `sudo` command. That should get you past the access controls.
So you should say
HTH,
Per
so can I use this command to shape traffic or slow down access to a particular website, (say facebook) on an employees imac
I could do this at the router, but I want my clients to still have full access
Post new comment