49.1.10 Using Streams for Realtime Applications

In addtion to reading from files nam can also read from a stream such as STDIN. Here is a little tutorial on how to send a nam trace stream to nam to make it operate with real-time data. First some background on how nam works internally. Basically, it thinks it is reading from a nam tracefile. The file has a format to it. Each line is a nam event. The first character on the line defines the type of event and is followed by several flags to set options on that event. Each event is terminated by a newline character. A nam tracefile has 2 sections, static configuration events and animation events. All events with -t * in them are configuration events and should be sent to nam in one burst. Lines beginning with a # are comment lines. Currently comments should only be place in the animation section of the file after the first animation event.

First of all you need to pipe your data to nam's stdin and add the '-' flag to the nam command.

For example:

nam will read the information from stdin

Following is a short wireless animation example. The first part of the script has line with -t * which tells nam that these are initial configuration information.

V -t * -v 1.0a5 -a 0
W -t * -x 600 -y 600

The first 2 lines are used in the nam initialization. They need to be the first 2 lines sent to nam from your program. V is the minimum nam version needed to correctly run this script. W means this is script contains wireless nodes which will be within the canvas size of width x and height y.

n -t * -s 0 -x 0.0 -y 0.0 -z 20 -v circle -c black -w
n -t * -s 1 -x 0.0 -y 200.0 -z 20 -v box -c black -w

Next is the network layout information. The first line n creates a wireless (-w) circular (-v circle) node with id 0 (-s 0) at position 0.0,0.0 (-x 0.0 -y 0.0). It's size (-z) is 20 and it's color (-c) is black. The second is a wireless square (-v box) node with id 1 (-s 1) at 0.0,200.0. Each node has to have a unique id number given by the -s flag.

A -t * -n 1 -p 0 -o 0xffffffff -c 31 -a 1
A -t * -h 1 -m 2147483647 -s 0

The A event line has to do with setting up hierarchical addressing in nam. It is necessary in wireless nam because packets are treated as broadcast to every node.

Now we are done with the configuration part of the nam file. Next are the animation events. In order for nam to operate in a close to real-time mode it needs to constantly receive updates. As it is playing it will keeps reading lines from the nam trace and playing them back. The sequence of events must be in chronological order. For example the following lines change the color of node 1 from black to green back to black and then to black again.

n -t 0.0 -s 1 -S COLOR -c green -o black
n -t 0.01 -s 1 -S COLOR -c black -o green
n -t 0.02 -s 1 -S COLOR -c black -o black

Notice that the "-t <time>" flags are always increasing. You cannot issue one event at -t 0.2 and then another later on at -t 0.1. Nam has an internal counter of time and it executes an event once it's time counter passes that event time. It will execute events in chronological order but only if they are given to it in chronological order. So the following WILL NOT work.

n -t 0.0 -s 1 -S COLOR -c black -o black
n -t 0.02 -s 1 -S COLOR -c green -o black
n -t 0.01 -s 1 -S COLOR -c black -o green

Since nam has its own internal representation of time which is different than current real world time you have to try and synchronize them. There is no explicit and totally accurate way to do this but you can have a rough synchronization of time by having you application periodically send nam events even if nothing has happened. We have created a dummy or "no-op" event (T) for this purpose.

T -t 0.5

As described above, you MUST feed events to nam in non-decreasing timestamp order. Successive events at the same time are OK. Before animating to a given time, nam needs to know that it's got all the events for that time, and so it actually has to read an event AFTER that time. Therefore if you're driving nam from an external process in real-time it will refuse to animate time t until it sees an event at time t+i (for any i > 0). To make nam play out events smoothly, you may therefore need to generate dummy events with intermediate timestamps (so that nam knows it can advance). Events of type "T" are dummy events, so this stream would produce jerky animatation:

n -t 1.0 -s 1 -S COLOR -c green -o black
n -t 2.0 -s 1 -S COLOR -c black -o green
n -t 3.0 -s 1 -S COLOR -c black -o black

while this would be animatated much smoother:

T -t 0.0
T -t 0.5
n -t 1.0 -s 1 -S COLOR -c green -o black
T -t 1.5
n -t 2.0 -s 1 -S COLOR -c black -o green
T -t 2.5
n -t 3.0 -s 1 -S COLOR -c black -o black
T -t 3.5
T -t 4.0

If nam ever gets to the end of an event stream it will block and the program will appear as if it has frozen. The screen will not be updated until it can read another event so you must be sure to feed events to nam faster than or as fast as it can read them. This technique works pretty well and allows nam to look as if it is running in real-time although in reality there will be a slight delay which is usually acceptable.

One other thing to remember is that your application should send these events based on it's representation of time from when the application started. Also, when sending events to nam they should be unbuffered so you will want to fflush(stdout); after each event.

Another event which you can keep sending to nam would be an note which will show a the bottom of the nam window.

v -t 0.08 -e sim\_annotation 0.08 1 Time is 0.08
v -t 0.09 -e sim\_annotation 0.09 2 Time is 0.09
v -t 0.10 -e sim\_annotation 0.08 3 Time is 0.10

The 'v' event means that you will execute a tcl script at time -t, everything after -e is the script to execute. sim_annotation writes a note at the bottom of the screen. The numbers after it are the time to write and a unique note id. Notice how I incremented the note id with each successive note. The remaining is what is written to the screen. For example "Time is 0.08" followed by "Time is 0.09", etc...

That is the basic idea behind making nam work in a real-time fashion. Following are two examples on how to generate wireless packet animations when using nam. To make a wireless broadcast which is shown as quickly expanding circle you can use the following.

+ -t 0.16 -s 0 -d -1 -p AODV -e 100 -c 2 -a 0 -i 0 -k MAC
- -t 0.16 -s 0 -d -1 -p AODV -e 100 -c 2 -a 0 -i 0 -k MAC
h -t 0.16 -s 0 -d -1 -p AODV -e 100 -c 2 -a 0 -i 0 -k MAC

'+' event puts the packet onto the transmission queue '-' event remove the packet from the queue and makes it ready to broadcast 'h' send the packet to the next hop which actually causes the animation Here are the meanings of the flags -t time -s transmitting node id -d destination node id (-1 indicates broadcast to world) -e size of transmission -c ultimate destination of the packet

To show a packet being send from one particular node to another use the following

r -t 0.255 -s 1 -d -1 -p MAC -e 512 -c 0 -a 0 -i 0 -k MAC
+ -t 0.255 -s 1 -d 0 -p AODV -e 512 -c 0 -a 0 -i 0 -k MAC
- -t 0.255 -s 1 -d 0 -p AODV -e 512 -c 0 -a 0 -i 0 -k MAC
h -t 0.255 -s 1 -d 0 -p AODV -e 512 -c 0 -a 0 -i 0 -k MAC
r -t 0.255 -s 0 -d 1 -p AODV -e 512 -c 0 -a 0 -i 0 -k MAC

First the packet is received ('r') from the wireless broadcast to node 1. It is then added to the outgoing queue ('+') on node 1. Next, it is removed from the queue('-') and ready to be sent to node 0. Then the packet is sent to the next hop ('h') node 0. This will trigger an animation of a line the length of the packet size moving from node 1 to node 0. Finally it is received ('r') by node 0 from node 1.

For more nam events you can look at the nam section in the ns manual

Also, you can save a copy of the trace from a realtime source using the unix 'tee' command. For example:

Sometimes it is a bug in nam and sometimes it is a problem with the way your tracefile is formatted. You may expect nam to do something that it won't do. Part of the philosophy in the design of nam is that the detail of an animation is handled by the tracefile which makes nam more flexible but pushes some of the animation complexity on to the programmer generating the tracefile.

Tom Henderson 2011-11-05