Flowgen

Flowgen is a tool for generating network traffic based on a given traffic model. The sender side of flowgen takes input from a config file (packet sizes, burst sizes, burst intervals) and generates appropriate levels of traffic. The receiver side of flowgen receives traffic from several sources, computes loss (for UDP flows) and throughput statistics, and saves the application-level header to a file. Flowgen uses the GNU Scientific Library to allow users to generate traffic flows that have characteristics based on random distributions. A companion tool, flowparse, parses flowgen output files.


Roadmap

Implementation Usage Configuration Files Output Processing Output Performance Issues


Implementation

Flowgen and flowparse are both implemented in C/C++ on FreeBSD-2.2.8. C++ was used solely for the Standard Template Library, which makes building and using dynamic arrays very easy.

Each flow is broken down into a series of bursts, which can be described by either a number of bytes per burst, or a number of packets per burst. Flowgen uses polling to send packets at the desired time. There is a continuous loop that checks each flow to see if a packet is ready to be sent. Every time a packet is sent, the next packet for that flow is computed. By default, if this next packet is part of a burst, it will be sent before checking other flows. In this way, flowgen can generate bursty traffic.

If the sender is unable to send a packet (out of buffer space, for example), flowgen will try sending it again the next time through the main loop. Every time a packet send time is computed, the next packet send time is also computed, so that if a packet cannot be sent before the sending time of the next packet, the current packet will be skipped. The next packet inherits the current packet's application-level sequence number, so that the skipped packet does not show up as a loss on the receiver end. Skipped packets are kept track of and the total number for each flow is reported at the end of an experiment.

By default, flowgen adds a 32-byte header to each packet sent. This header contains the packet size, flow id, sending time, sequence number, burst number, packet in burst, and burst size (in packets). This header is saved in the output file (if specified) on the receiver side.

No matter the packet size, flowgen will send packets as they are specified. When using TCP, large packets are at the mercy of TCP's Max Segment Size. Flowgen will pass packets to the operating system when they are ready to be sent, but makes no guarantees of their actual sending time.


Usage

Usage: flowgen -f config_file [-bcghnpq]
  -b bytes: set socket send/recv buffer size
  -c: force UDP sender to connect
  -g num: debugging level
     level 1 = lost & ooo packets
     level 2 = level 1 + out of buffer space warnings
     level 3 = level 2 + all packet headers
  -h: no app-level header
  -n: non-blocking sockets
  -p: packet-by-packet scheduling
  -q: quit when packets would be skipped

-b: To send high bit-rates of data, the socket send and recv buffer sizes should be sufficiently large. Use this option to increase the default socket buffer size.
-c: When connecting a UDP socket, if the receiver is not available, the sender will report an error and quit. By default, UDP senders do not connect to their remote hosts. If you would like to ensure that your receivers will see the entire run, use the -c option to force the UDP sender to connect.
-g: According to the level, debugging information will be displayed. For level 1, lost and out-of-order packet warnings when using UDP will be displayed by the receiver. For level 2, all level 1 messages, plus out of buffer space warnings will be displayed by the sender. For level 3, all level 2 messages, plus all packet headers will be displayed, by both the sender and receiver.
-h: Flowgen adds a 32-byte application-level header to each packet in order to collect loss and throughput statistics. If you wish to forfeit these statistics in order to have packet sizes less than 32 bytes, invoke flowgen with the -h option.
-n: Flowgen by default uses blocking send() calls. In some instances, non-blocking sockets would result in better perfomance.
-p: By default, flowgen will schedule a burst of packets to be sent at once. Using the -p option, flowgen will send one packet at a time from each available flow.
-q: As described in the implementation section, flowgen skips sending those packets that would have actually been sent more than one burst interval late. If using the -q option, when this occurs, flowgen will report an error and quit.


Configuration Files

Legend

TERMINAL Non_Terminal user input (one or more)+ [optional]

Grammar

Config_File:=[OUTPUT output_file]
(OutFlow)+   |
(InFlow)+

OutFlow:=OUTFLOW Inflow:=INFLOW
(Hdr)+ (Hdr)+
(Traffic)+ [END_TIME seconds]
(Footer)+

Hdr:=[SENDER hostname or IP addr]
RECEIVER hostname or IP addr
PORT port
PROTOCOL (TCP | UDP)

Traffic:=PACKET_SIZE expression   |
BURST_PACKETS expression   |
BURST_BYTES expression   |
BURST_INTERVAL expression

Footer:=START_TIME seconds  |
END_TIME seconds  |
[SEED integer]

Explanation of Terminals

OUTPUT - output file for this experiment (optional)
OUTFLOW - start the description of a new outgoing flow
INFLOW - start the description of a new incoming flow
SENDER - sender's IP address or hostname (optional, ignored by InFlows)
RECEIVER - receiver's IP address or hostname (optional for InFlows)
PROTOCOL - TCP or UDP
PACKET_SIZE - packet size in bytes
BURST_PACKETS - burst size in packets
BURST_BYTES - burst size in bytes
BURST_INTERVAL - seconds between sending the first packet of consecutive bursts
START_TIME - starting time of flow, in seconds from the start of flowgen
END_TIME - ending time of flow, in seconds from the start of flowgen
SEED - seed of random number generator (optional)

Rules

Notes

Example Sender Configuration File

# sender.cfg
#
OUTPUT /tmp/sender.flg           # output file
#
OUTFLOW                          # this is a new outgoing flow
SENDER tyagi                     # sender's address
RECEIVER thurston                # receiver's address
PORT [7003:1:7005]               # receiver's port to send to
                                   # (The range specification says to create
                                   # three flows with port numbers
                                   # 7003, 7004, 7005, respectively.)
PROTOCOL UDP                     # use UDP
PACKET_SIZE 3000                 # constant packet size
BURST_PACKETS 5                  # constant burst size
BURST_INTERVAL poisson ([0.500:.5:1.5]) # burst interval -- poisson distributed
                                   # mu = 0.5, 1.0, 1.5, respectively
START_TIME 0                     # start as soon as flowgen starts
END_TIME 60.75                   # end 60.75 seconds after start
SEED 123456                      # use this specific seed
#
OUTFLOW                          # this is a new outgoing flow
RECEIVER thurston                # receiver's address
PORT 7004                        # receiver's port
PROTOCOL TCP                     # use TCP
BURST_BYTES normal (2900, 100)   # bytes per burst -- normal distributed
                                   # mu = 2900, sigma = 100
BURST_INTERVAL 0.500             # constant burst interval 
START_TIME 15                    # start 15 seconds after flowgen starts
END_TIME 90                      # end 90 seconds after flowgen starts

Example Receiver Configuration File

# recvr.cfg
#
OUTPUT /tmp/recv.flg             # output file
#
INFLOW                           # this is a new incoming flow
RECEIVER thurston                # listen at this address
PORT [7003:1:7005]               # listen on this port
                                   # (3 flows on ports 7003, 7004, 7005)
PROTOCOL UDP                     # listen for UDP
END_TIME 65                      # quit 65 seconds after start
#
INFLOW                           # this is a new incoming flow
PORT 7004                        # listen on port 
PROTOCOL TCP                     # listen for TCP
Note: Make sure there's a newline after the last line in the config files.


Output

Flowgen creates two types of output. The main output file, specified in the configuration file, stores statistics for each flow. First, the host, time, and date of the experiment is saved, followed by the configuration file used. On the sender's end, this information is followed by throughput statistics in text format. On the receiver's side, the configuration file is followed by the application-level packet headers in binary form. Both files can be processed by flowparse. Flowgen also produces status messages to stdout.

Examples

tyagi% flowgen -f sender.cfg

Opened /tmp/sender.flg for output.
[flow 1]:  (9216 byte send buffer, blocking)
[flow 2]:  (9216 byte send buffer, blocking)
[flow 3]:  (9216 byte send buffer, blocking)
[flow 4]:  (16384 byte send buffer, blocking)
[flow 1] -- starting @ 0.000005...
[flow 2] -- starting @ 0.003097...
[flow 3] -- starting @ 0.006091...
[flow 4] -- starting @ 15.037742...
[flow 3] -- DONE @ 60.75
[flow 1] -- DONE @ 60.80
[flow 2] -- DONE @ 60.81
[flow 4] -- DONE @ 90.05

flow #         sent    skipped         sent       duration     tput
[   1]      565 pckts  (     0)      113 bursts    60.75 s    0.223 Mbps
[   2]      300 pckts  (     0)       60 bursts    60.75 s    0.119 Mbps
[   3]      170 pckts  (     0)       34 bursts    60.75 s    0.067 Mbps
[   4]      150 pckts  (     0)      150 bursts    75.00 s    0.046 Mbps
Closed /tmp/sender.flg
thurston% flowgen -f recvr.cfg
Opened /tmp/recv.flg for output.
[flow 1]: (41600 byte recv buffer)
[flow 2]: (41600 byte recv buffer)
[flow 3]: (41600 byte recv buffer)
[flow 1] (1) -- receiving @ 2.346063...
[flow 2] (2) -- receiving @ 2.446094...
[flow 3] (3) -- receiving @ 2.449487...
[flow 4]: (17280 byte recv buffer)
[flow 4] (4) -- receiving @ 17.046145...
[flow 2] (2) -- DONE @ 65.00
[flow 3] (3) -- DONE @ 65.05
[flow 1] (1) -- DONE @ 65.05
[flow 4] (4) -- DONE @ 91.86
All connections closed.

flow #  sender     received       lost       % lost    duration     tput
[   1] (   1)     408 pckts      157 lost   27.788 %    58.59 s    0.167 Mbps
[   2] (   2)     260 pckts       40 lost   13.333 %    58.49 s    0.107 Mbps
[   3] (   3)     168 pckts        2 lost    1.176 %    59.49 s    0.068 Mbps
[   4] (   4)     150 pckts        0 lost    0.000 %    74.30 s    0.047 Mbps
Closed /tmp/recv.flg


Processing Output (flowparse)

Usage

flowparse -f flowgen_file [-ciprs]
  -c flow: print config info for flow      [0 = all]
  -i     : print info on all flows         [default]
  -p flow: print packet headers for flow   [0 = all]
  -r flow: print receiver's stats for flow [0 = all]
  -s flow: print sender's stats for flow   [0 = all]

Examples

thurston% flowparse -f /tmp/recv.flg
Run on thurston at Thu Nov 2 10:42:15 1999
[flow   1] {sender} --> thurston:7003  UDP
[flow   2] {sender} --> thurston:7004  UDP
[flow   3] {sender} --> thurston:7005  UDP
[flow   4] {sender} --> thurston:7004  TCP
thurston% flowparse -f /tmp/recv.flg -c 0
Run on thurston at Tue Nov  2 10:42:15 1999
# recvr.cfg
#
OUTPUT /tmp/recv.flg             # output file
#
INFLOW                           # this is a new incoming flow
RECEIVER thurston                # listen at this address
PORT [7003:1:7005]               # listen on port
                                   # (3 flows on ports 7003, 7004, 7005)
PROTOCOL UDP                     # listen for UDP
END_TIME 65                      # quit 65 seconds after start
#
INFLOW                           # this is a new incoming flow
PORT 7004                        # listen on port 
PROTOCOL TCP                     # listen for TCP
thurston% flowparse -f /tmp/recv.flg -c 1
INFLOW                           # this is a new incoming flow
RECEIVER thurston                # listen at this address
PORT 7003                        # listen on port
PROTOCOL UDP                     # listen for UDP
END_TIME 65                      # quit 65 seconds after start
thurston% flowparse -f /tmp/recv.flg -r 0
flow #  sender     received       lost       % lost    duration     tput
[   1] (   1)     408 pckts      157 lost   27.788 %    58.59 s    0.167 Mbps
[   2] (   2)     260 pckts       40 lost   13.333 %    58.49 s    0.107 Mbps
[   3] (   3)     168 pckts        2 lost    1.176 %    59.49 s    0.068 Mbps
[   4] (   4)     150 pckts        0 lost    0.000 %    74.30 s    0.047 Mbps
thurston% flowparse -f /tmp/recv.flg -p 1
recv_flow sender_flow recv_time size seq_num send_time burst packet_in_burst burst_size
1 1 944766578.121739 3000 1 944766577.573220 1 1 5
1 1 944766578.228574 3000 2 944766577.573426 1 2 5
1 1 944766578.228711 3000 3 944766577.573574 1 3 5
1 1 944766578.228827 3000 4 944766577.573727 1 4 5
1 1 944766578.228937 3000 5 944766577.573872 1 5 5
1 1 944766579.594936 3000 6 944766579.570934 2 1 5
1 1 944766579.595006 3000 7 944766579.571103 2 2 5
1 1 944766579.595058 3000 8 944766579.571244 2 3 5
1 1 944766579.595110 3000 9 944766579.571385 2 4 5
...
thurston% flowparse -f /tmp/sender.flg -s 0
flow #         sent    skipped         sent       duration     tput
[   1]      565 pckts  (     0)      113 bursts    60.75 s    0.223 Mbps
[   2]      300 pckts  (     0)       60 bursts    60.75 s    0.119 Mbps
[   3]      170 pckts  (     0)       34 bursts    60.75 s    0.067 Mbps
[   4]      150 pckts  (     0)      150 bursts    75.00 s    0.046 Mbps


Performance Issues

Flowgen is currently undergoing preliminary performance testing. So far, we've tested TCP and UDP throughput on a 100 Mbps link. UDP maximum throughput is over 95 Mbps, and TCP maximum throughput is almost 70 Mbps. Issues that affect TCP throughput are the TCP window size, socket buffer size, and loss rate. Seemingly negligible loss rates for UDP can cause TCP's throughput to suffer dramatically.


Other DiRT documents
Author: Michele Clark