dummynet - Creating network delay and loss

dummynet is a FreeBSD system facility that simulates network delay and loss by manipulating the IP queue inside the kernel. Dummynet makes use of ipfw which supports various types of IP filters for system network interfaces. For more detailed information in both dummynet and ipfw, see the FreeBSD man pages.

The dummynet features we're interested in are delay and loss simulation. To make dummynet a little easier to use, we've provided some wrapper utilities in the directory /usr/local/bin/. They include:


The general idea is to create a "pipe" object and configure it with the desired delay and loss parameters. The pipe gets added to a list of filtering "rules" which are used by dummynet to modify the treatment of IP packets in desired ways.

dummynet_show can be used to list all pipes (and other ipfw rules) currently active in the system. You can use it on the command line without any arguments like this:

65535     227889   48313672 allow ip from any to any

The rule shown is a default rule that is always on the system. It is rule number 65535 (they're numbered 0 to 65535), and says to allow IP packets to be forwarded from any address to any other address without special filtering. Note that rules are processed in the order that they are listed. This probably will not be much of an issue for us since we will be using only one or two at a time. But should it be the case that more than one rule applies to a giving packet, the first will be applied first, then the second, and so on. The number in the second column shows the number of packets seen that have matched this rule. The third column shows the total number of bytes contained in those packets.

To create delays and/or losses, we first need to create a pipe. This is done using dummynet_create in the following manner:

pepe167[/usr/local/bin]>dummynet_create -p ip -s any -d any -c in 100
00000 pipe 100 ip from any to any in

The 100 is an arbitrary number between 0 and 999 chosen by the user executing the script. Using dummynet_show, we can view the result:

00100         58       3664 pipe 100 ip from any to any in
65535     227930   48317287 allow ip from any to any

The usage message for dummynet_create shows the full set of options available to you when creating a pipe mechanism:

usage: dummynet_create [switches] <pipe id #>

         -p <protocol>  --> ip|udp|tcp|icmp      [def: ip]
         -s <src>       --> any|ip addr|hostname [def: any]
         -d <dst>       --> any|ip addr|hostname [def: any]
         -c             --> in|out               [def: in] 
Optional (Use with tcp and udp only):
         -S <src port>  --> #|#-#|#,#,...        [def: (none)]
         -D <dst port>  --> #|#-#|#,#,...        [def: (none)]
         pipe id # is an integer between 0 and 999

Port numbers can be used with tcp and udp protocols only. They can be expressed as a single number (ex. 80), a range of numbers (ex. 80-85), or a list of numbers (ex. 80,81,82,83,84,85).

Now we can use dummynet_set to configure the pipe for delays and/or losses:

pepe167[/usr/local/bin]>dummynet_set -d 30 -l .05 100
ipfw pipe 100 config delay 30ms plr 0.050000

Here we have set the delay to 30 msec (verify by pinging pepe167 from another machine on the COMP 249 net) and the loss rate to 5 percent. Running dummynet_show does not give any details on the configuration (unfortunately).

Here's the usage message for dummynet_set:

usage: dummynet_set [switches] <pipe id #>

         -d <delay> --> delay in millisec                    [def: 0]
         -l <loss>  --> loss factor (float: 0.0 <= n <= 1.0) [def: 0.0]
pipe id # must correspond to an existing pipe

The last utility, dummynet_flush, allows you to remove all pipes (or other ipfw rules) with the exception of the default rule shown earlier. You should run this command without any arguments whenever you'd like to correct an error, start things over, etc. It's also good to run this at the beginning of your session in case someone else left pipes on the system, and at the end to free someone else from having problems who might be logging in remotely.

A good way to add pipes and configure them, incidently, is by putting the commands in a shell script and then just running the script at the command like. This will save a lot of unpleasant retyping. For example:

#! /bin/csh

# create pipe
/usr/local/bin/dummynet_create -p udp -s mayberry167 -S 15890 -d any -c in 10 

# configure pipe
/usr/local/bin/dummynet_set -d 30 -l .05 10

By the way, I've included one more command as a "just in case" emergency measure: reboot249 (also in /usr/local/bin/ on each COMP 247 machine). Type this command without any arguments and the machine will reboot and come back with its original network configuration. I don't believe this command will ever be necessary, but I'm giving you avenue to use it just in case. Always use reboot249 instead of power cycling the machine (ie. using the reset or on/off button). Power cycling a machine may result in damage or inconsistencies to the file system.

D. Ott 10/4/99