Programmers Manual For TCP/IP Over ATM Simulator

Introduction

This document is intended for a those who want to change this simulator or add any new component to this simulator. It is essential to understand how different functionalities of the simulator are achieved by various classes. Not only will this ensure a valid addition to the design, but can also ease the programming effort by using the predefined classes. We believe that the source code is the best guide to understanding a program but for a simulator of this nature, knowing the basics of the design greatly enhance the understanding of the program. So we have included both the description of the classes and parts of their code. If you have not read the "Basic Design Document" then read it first. The following is a detailed description of the classes. For every class we first brifly describe the class, then its individual members and functions.

TclObject

TclObject is the highest class in the object hierarchy. All the major classes are derived from this class. The advantage of using this common base class is that objects of all kinds can be stored in the same list .

Variables

id_ A static integer that assigns unique names to all the TclObjects
all_ A static list of all the TclObjects. Every object that is inherited from TclObject will be inserted in this list.
name_ This is the unique name of the object. For user defined objects the name is "_on" where n is the unique number sequentially assigned by id_. For other objects i.e. command objects, the names can be specified by the programmer. e.g. "ns-at"
class_name_ This contains the class names as identified by the Matcher classes. If it belongs to a hierarchy of classes then it will contain both of them seperated by slash. For e.g. "link/atm" for atmlinks.
next_ This is for maintaining the linked list of the objects.

This class contains a static list of all the objects created by the user. Each object is assigned a unique name and these are used to identify the object when used by the user. It also records the name of the class to which the object belongs. The function using the object knows how to treat the object and simply typecasts it for its own use. The series of command objects are declared as static. Thus you can have only one such object which is identified by its special name. For e.g. the AtCommand object is identified by the "ns-at" name which is called internally by the ns at command. These command functions are used for converting user input to different types of TclObjects. The class NsObject is not static and from it almost all the other main classes are derived.

Class Handler

This is the base class for all event handlers. When the scheduled time of an event arrives, it is passed to its handle function, which consumes it i.e. if it needs to be freed it is freed by the handler.

Class Event

This class is the basic unit of a list of events. Each event contains a pointer to itself, i.e. it forms a linked list of events. It also contains a pointer to the Handler class, in order to give the event to the handler when the event is ready. It also contains the time as one of its attributes, which gives the time at which the event is ready. Every event also has a unique user identifier.

Class Scheduler

The Schedule function takes the reference to an event, a handler and a delay in time units into the future when the event is to be generated. The user id for the event is generated and the event is dispatched to the specified handler. The event is assigned a time at which it is supposed to take place. The event is then assigned to the priority queue of events in which they are in ascending order of their times of generation. This function handles the events in the Event queue, moves the pointer forward, updates the time and gives the event to the handler class to handler. Every object of any class if needs to generate an event calls the scheduler. The scheduler also creates new user id.

The Cancel function cancels the event. It is an error to invoke this routine when teh event is not actually in the queue. The caller must free the event if necessary, this routine only removes it from the scheduler queue.

void Scheduler::run()
{
        while (queue_ != 0) {
                Event* p = queue_;
                queue_ = p->next_;
                clock_ = p->time_;
                p->handler_->handle(p);
        }
}

The Run function is actually responsible for running of the simulation. It checks the queue and if there is an event in it that needs to be executed at that time, it gives it to the handler.

The init() creates an instance of class Scheduler, since this is a static declaration this happens only once in the whole program.

void Scheduler::schedule(Handler* h, Event* e, double delay)
{ 
        e->uid_ = uid_++;
        e->handler_ = h;
        double t = clock_ + delay;
        e->time_ = t;
        /* XXX replace this code with Sugih's calendar queue */
        Event** p;
        for (p = &queue_; *p != 0; p = &(*p)->next_)
                if (t < (*p)->time_)
                        break;
        e->next_ = *p;
        *p = e;
}

lookup This function returns the pointer to the event if the it is given its user id. It looks up the event and returns it. Most probably it is used for debugging.

Special Commands (misc.cc)

int AtCommand::command(int argc, const char*const* argv)
{
        Tcl& tcl = Tcl::instance();
        if (argc == 2) {
                Scheduler& s = Scheduler::instance();
                Event* p = s.lookup(atoi(argv[1]));
                if (p != 0) {
                        /*XXX make sure it really is an a
tevent*/
                        s.cancel(p);
                        AtEvent* ae = (AtEvent*)p;
                        delete ae->proc_;
                        delete ae;
                }
                return (TCL_OK);
        } else if (argc == 3) {
                double t = time_atof(argv[1]);
                const char* proc = argv[2];
        
                AtEvent* e = new AtEvent;
                int n = strlen(proc);
                e->proc_ = new char[n + 1];
                strcpy(e->proc_, proc);
                Scheduler& s = Scheduler::instance();
                double delay = t - s.clock();
                if (delay < 0) {
                        tcl.result("ns-at: can't schedule
 command in past");
                        return (TCL_ERROR);
                }
                s.schedule(&at_handler, e, delay);
                sprintf(tcl.buffer(), "%u", e->uid_);
                tcl.result(tcl.buffer());
                return (TCL_OK);
        }
        return (TclObject::command(argc, argv));
}

Command This function does the following. If an event is to be scheduled at the specific time the user can give something like the following command in the input file. e.g at 0.0 "$ftp start". This command is then interpreted by the ns {cmd} function in the ns-default file, which invokes the the ATCommand function. This in turn generates the time when the event is supposed to take place and gives it to the schedular to handle. The event hence generated is handled by the handler.

static class NowCommand : public TclObject {
public:
        NowCommand() : TclObject("ns-now") { }
        virtual int command(int argc, const char*const* a
rgv);
} now_cmd;

<

The Ns-now command at the input file, is interpreted by the ns -cmd funtion. This invokes the NowCommand which in turn returns the current time.

int RunCommand::command(int argc, const char*const* argv)
{
        /* set global to 0 before calling object reset me
thods */
        Scheduler& s = Scheduler::instance();
        s.reset();
        TclObject::reset_all();
        s.run();
        return (TCL_OK);
}

RunCommand::command When the user types ns run in the input file it is interpreted by the ns-default file through the ns cmd function as a result of which the RunCommand function gets executed. This function creates the pointer to the scheduler class, and calls its run function which executes the particular test. This function ultimately runs the particular test required to be run by the user.

//Have to write about the 'lookup' function

ATM Commands (atmcmd.cc)

int ATMCommand::command(int argc, const char*const* argv)
{
        TclObject* temp[3];
        Tcl & tcl=Tcl::instance();
        char obj_name[30];
        int i=0,k;
        for(int j=0;j<3;j++)
        {
                for(k=0;argv[1][i]!=' ' && argv[1][i]!='\
0';i++,k++)
                        obj_name[k]=argv[1][i];
                obj_name[k]=0;
                while(argv[1][i]!='\0' && argv[1][i]==' '
)i++;
                temp[j]=lookup(obj_name);

                if(!temp[j])
                {
                        tcl.result("connect: Unable to fi
nd object"); 
                        return (TCL_ERROR);
                }
        }

        //Check here that the class_names match.
        //Also that temp[2] has been added to the atmnetw
ork

        ((ATMNetwork*)temp[1])->attach((Node*)temp[0], (A
TMNode*)temp[2]);
        return (TCL_OK);
}

The Command function gets invoked as a result of ns connect command, it connects the corresponding node in the ATM network. Implying that an incoming packet from the tcp node gets on the corresponding port on the ATM network.

AddCommand: After an ATM source or switch is created it has to be associated with the ATM network using the ns command. We maintain the invariant that this structure is read-only to all modules except link.c ( but the node field is writable by the nodes ).This function gets invoked as a result of the add-node command. As a result of this the command function of AddNodeCommand gets executed and the function is performed i.e. a node is added to the ATMNetwork. It gets the pointer to the Network object and the object itself. It invokes the lookup function to find whether the object exists or not. If the object exists it is added to the Network using the add_node routine.

Link (link.h, link.cc)

This class is the representation of the output link. A node can have multiple output lines i.e. a router or a single output line ( the source ). The link class inherits from the Handler and NsObject classes. The main attributes of the link class are the source src and destination dest . The integer qnp gives the number of packets currently stored in the queue.The maximum number of packets allowed in the queue is given by the qlim parameter. The state of the queue is given by the busy parameter, which is 1 if the link is busy and 0 if it is idle.The next neighbor at the other end of the link is given by the Node* neighbour. The bandwidth of the underlying link is given by an attribute as well. The latency in the link delay is given by delay. The total time for which the link is busy is given by the busytime_ attribute, which is actually the utilization of that particular link. The number of bytes currently in the queue are given by The Lossy link eventually inherit from the link class. There is a separate Queue class, which is incorporated into the link. Hence the Link is implemented as a queue. The enqueue, dequeue, and qlen functions are declared as being virtual implying that all the classes inheriting from the link class will have to make their own functions regarding the above mentioned operations.

link.cc

The constructor for the link, looks up the ns_default file and initializes the parameters such as the bandwidth, delay, queue limit, for the link with the values in the default file.

link::update This function is called every time the queue size changes and updates the vital statistics of the queue.

link::send This function dequeues the packet from the link queue, calculates its transmission time, adds the delay it has to go through on the link, updates the utilization. and eventually an event is generated for that packet to get off the link. It also sets the busy attribute to 1.

link::handle This function verifies whether the link is busy or not, if it is, it marks it idle ( not busy ), and then it calles the send function to handle this event ( as described above ). Since the link class is the base class for all other link classes, so an object of this class can never get formed. Hence it implies that this particular handle function never gets called, so we can say that whenever this function is called it can only be through an interrupt.

link::send(Pkt ) //this is different from the previous send function as it takes the packet as an argument. This function accepts a packet for transmission on the link. The node class calls this method. The log-packet arrival and departure functions update statistics for the queue such as size in terms of bytes and also the number of packets and updates them and output them in a file. These functions also invoke the plot function.

link::command This function takes commands from the tcl script ( input file ) and executes them. The commands have something like the following format e.g. $link $insert $src $dst.This can execute all the operations that can be defined on the link. Since the link class inherits from the NsObject class, so this is virutal function that Link had to define on its own. So for the cases which Link cannot handle, it passes over ( i.e. returns to ) the NsObject class making it responsible for further handling. The commands having the above mentioned syntax are handled by this function. First the arguments are checked and then the strings are matched and appropriate action is taken. The following comands can be executed using this function. reset, integral, qsize, qlen, queue-trace, flow-mgr,install, stat,packets, bytes, drops,mean-qlen, mean-qsize,mean-qdelay, The reset function basically resets all the variables to zero.

link::remove This function is used to remove the link when it has been dropped or something.

link::log_packet_arrival/departure These functions are related to the statistics gathering functions of link. When a packet is put on a link the arrival statistics qnb etc need to be updated, similar is the case with departure statistics. But these functions are invoked only when the trace mode is on and the network communication traffic is being monitored.

link::reset This function is used to reset the link statistics that the user might be interested in. So that after reseting them and running the simulation, they can monitor the actual statistics gathered.

LossyLink (lossy.cc)

void LossyLink::enque(Packet* p)

This inherits from the basic link class. The only functions that are different are the enqueue and dequeue functions. The enqueue functions takes in the packet as an argument. It invokes the enqueue function and inserts the packet in the queue. It then invokes the log_packet_arrival function and passes it the packet. Then it invokes the loss_policy function which generates a random number to decide whether the packet is to be discarded or not ( against a certain loss probability ). It then calls the remove function to remove the packet if the loss-policy allows for it. otherwise it lets it go.

Packet* p LossyLink::deque()

This simply dequeues the packet from the link when it is time for it to get off it and go to some other link, switch or node.

This class too inherits from the link class and implements the lossy link algorithm. This algorithm has to maintain less than a given percentage of loss limit.


DropTailLink (drop-tail.cc)

This class inherits from the Link class. The functions that were declared as virtual in the Link class i.e. the enqueu and dequeue functions are defined separately for this DropTail Link class. The DropTail Matcher class inherits from the main Matcher class ( as is obvious from the name ). This class is necessary when taking input from tcl script ( i.e. the input file ) since it verifies and matches the string and creates the new droptail link. So it is necessary when there is need to create a droptail link. The enqueue function for the DropTail Link inserts the packet into the queue and invokes the update log function for the link. If the size of the link of the queue is exceeding its limit it removes the packet and updates the statistics again. The dequeue function just removes the packet from the queue ( link ) when it is time to be removed. In all the above casese the relevant functions for updating the packet arrival, drop and departure statistics are updated.

Drop-tail.cc

The droptail link class inherits from the base link class. There are separate enqueue and dequeue functions in this class in order for it to implement the drop-tail algorithm.

DropTailMatcher This class inherits from the main matcher class. It basically matches the declaration of the drop-tail type link in the input file test-suite.tcl It converts the user of the input into a TCL object of type DropTailLink and returns it. It is basically invoked from the ns_default.tcl.

DropTailLink::enqueue( packet* p)

This function invokes the enqueue function of the queue class. It also checks to see if the total number of packets currently in the queue qnp in the queue is exceeding the limit qlim assigned to the queue or not. If it is exceeding the limit then, it is removed from the queue and also the log-packet departure statistics are also updated. ( This is actually the drop-tail algorithm ).

DropTailLink::dequeue()

This function is invoked when the packet is supposed to get off the link to get onto the destination node, the switch buffer or possibly another link. It simply dequeues the first packet in the queue that needs to be dequeued according to the time. It then hands it over to the log-packet-departure function which updates the statistics.

REDQueue (red.cc)

This type of a link implemented the RED algorithm also inherits from the main link class. IT only has those functions that have been mentioned to be virutal in the link class. It also has its own reset function which overrides that of the basic class. For further details on this class it is necessary to understand the algorithm of which this is an implementation. So in order to gain knowledge of the algorithm refer to the following paper Sally Floyd and Van Jacobson " Random Early Detection Gateways for Congestion Avoidance" http://www-nrg.ee.lbl.gov/nrg-papers.html

CBQueue (cbq.cc)

cbq simulations can be run from "test-all-cbq" or from "test-suite-cbq.tcl". The CBQ class uses packet-by-packet and round-robin queueing.

Node (node.h, node.cc)

This class node.h inherits from the NsObject and Hanlder classes. Every node in the network contains a list of link lists containing the links connected to it. The static_int_cnt maintains the total number of nodes in the network ( excluding those of the ATM network ), only one node is representative of the whole ATM network. Since this is a static attribute it is declared only once, so every node in the network has the count of the total number of nodes in the whole network. The addr_ attribute contains the address of the node in terms of the network. The nport_ contains the total number of sessions of traffic on a particular node. Link route** is the routing table. This contains the linked list of all the outgoing links from node. maxport contains the total number of ports the node can support. maxagent contains the table of the types of traffics that can be supported by the port. //Link State and Group Entity structures have not been done as yet. Since there is no next pointer in the link class, so in order to maintain the List of links attatched to a node. The Link State structure is the basic unit of this linked list of links.

node.cc

static class NodeMatcher This class inherits from the parent Matcher class. The matcher function takes input from the input file and creates the object. It basically matches the required result from the input file and verifies whether the input is correct or not.

Node::Node() The Node constructor initializes the variables. It assigns the next count number as an address to the newly created node. It also initializes the maximum number of ports that is 64 ( preset ). It also adds an entry in the table of maxagents and initializes them as well.

Node::~Node()The destructor function deallocates the memory assigned to the routing table and the table containing the traffic descriptions.

Node::free(AgentList* p) The free function is invoked when a traffic has completed its duration and is stopped. So this function deletes its entry from the list of Agents. The add_link function is inserting the newly created link at the beginning of the linked list. It then makes an entry for this in the LinkState List.

The setroute function is invoked by the route-logic class. It returns the route of the given link and tells which link the packet is supposed to be routed to if it comes destined for a certain destination. The add_agent function adds the agent in the table of agents and returns the port number that it has assigned to the new agent. In case the number exceeds the total number of agents allowed ( maxport ) the array is doubled ( maxport is also doubled ) and then the very same procedure as above is applied. send-graft, add-group,send-grafts, record-prune, send-prune are functions that facilitate multicasting of TCP in ns i.e. to send messages to a group ( if required ).

The unicast_forward function is required for normal transmission of packets as compared to the multicast_forward. It takes in the packet as an argument and checks whether it is destined for itself ( i.e. the particular node that calls this function ), if it is so it takes the destination port from the packet ( an attribute of it ) and assigns it to the port. Then it finds out the agent from the reference of port number. If there is an error condition i.e. the agent doesn't exist it is freed and appropriate actions are taken. If not, the packet is handed over to the receive function of the agent which takes appropriate action and the function returns. If not, it is routed to the appropriate link on which it is supposed to be routed given the destination of the packet ( refering from the routing table ). and then the packet is handed over to the send function of the link which handles it. This function is invoked by the handle function which is supposed to handle the event as required, either multicast forward or unicastforward.

Node::Command This function is used to get input from the ns_default.tcl file. It takes in the address of the node and the agent in the ns_connect function. The command function basically handles input from the test_suite.tcl file when it returns the agent to the particular node.


RouteLogic (route.cc)

This implements the RouteLogic class that inherits from the TclObject class.

RouteLogicMatcher is the class that inherits from the Matcher class. This class reads in the input from the ns_default.tcl file, when it sees the route-logic word, it matches it and upon finding it creates a TclObject and returns it. It actually given a destination gives the link and hence implements the minimum hops routing logic. Whenver a new node is created the routelogic object is created and is assigned to the node and the routing table is built up once again.

RouteLogic::command This function is used for picking up the commands from the default input file i.e. ns_default.tcl. This first of all matches the insert command and inserts the node in the list of nodes representative of the network. It basically creates a pointer to that node. Then it matches with the 'compute-route' command and computes the routing table again with this node in the network by invoking the compute-routes() function.

RouteLogic::compute-routes() This function actually implements the min-hops algorithm. i.e. by looking at the destination it calculates the minimum path from the particular node to the destination. Every time a node is added this function is invoked to update the routing table.

Packet (packet.h)

The packet.h file includes the scheduler.h and config.h files. This class inherits from the Event class. This is so because it is initially generated as an event, if the link is to handle the function it automatically converts it into the packet. The qtime_ gives the time put on queue on current hop. u_char type gives the type of the data packet. u_char class_ gives the class for the stats and/ or cbq. u_short flags_ gives the various flags that are there for indication and debugging purposes. u_short lsrc_ this gives the link level source address for the last hop. u_short ldst_ gives the link level destination address for the last hop. u_short sport_ gives the source port number. u_short dst gives the destination node for the routers. u_short src gives the source node for routers. u_short dport_ gives the destination port. size gives the size of the packet in terms of bytes. seqno gives the sequence number of the packet. uid_ gives the unique user id assigned to the packet. body bd_ is a union that is a union of type specific fields.

Var (object.h, object.cc)

This class contains the objects of the default variables declared in the input file. It contains things like the name of the variable its characteristics etc. Whenever an object is created its default values can be set by searching for the appropriate variables and class name. The readonly_ variables in ns_default cannot be altered while other default variables can be altered during the simulation. All the network default variables belong to one of these classes. There are basically two types of classes inheriting from the base class Var. VarReal and VarInt.

VarReal

This class inherits directly from the VarReal class. The VarReal class handles the real numbered values e.g float, double etc. This class takes in the values assigned to real numbered variables and creates the VarReal object for them. It also takes in the names of these variables and assigns the types whether they are read only or not.

VarBandwidth

This class inherits from the VarReal class. THis is because it takes in real numbers for the bandwidth of links etc.

link_bw("ns_link", "bandwidth", &bandwidth_, 0);

VarTime

This class too inherits from the VarReal class. It takes in the default values assigned to variables recording different time parameters regarding the simulation. These variables are for example the interval, the delay on the link, the time at which the simulation is going to start etc. Eventually when the constructor is called these values are initialized, the names of the variables are also stored and their characterisitcs such as readonly etc.

EXAMPLE
A piece of ns_default.tcl
set ns_sink(packet-size) 40
set ns_delsink(interval) 100ms
set ns_sacksink(max-sack-blocks) 3
set ns_cbr(interval) 3.75ms
set ns_cbr(random) 0
set ns_cbr(packet-size) 210
set ns_rlm(interval) 3.75ms
set ns_rlm(packet-size) 210
Values being initialized in the constructor in link.cc
 Link::Link() : busy_(0), neighbor_(0), qnp_(0), qnb_(0), qtrace_(0),
    flowmgr_(0)
{
        Tcl& tcl = Tcl::instance();
        link_bw("ns_link", "bandwidth", &bandwidth_, 0);
        link_time("ns_link", "delay", &delay_, 0);
        link_int("ns_link", "queue-limit", &qlim_, 0);

        link_int(0, "queue-length", &qnp_, 1);
        link_int(0, "queue-size", &qnb_, 1);

        ncs_ = 10;
        cs_ = new classStat[ncs_];
}

VarInt

This class also inherits from the Var class. It takes care of the whole number ( integer ) or boolean values that are assigned to default variables.

VarBool

This class inherits from the VarInt class. As must be evident from the name it takes care of the default boolean values that are assigned to different variable e.g true or false.

e.g From the ns_default.tcl

set ns_red (bytes) false
set ns_red (set-bit) false
set ns_red (drop-tail) false
set ns_red (doubleq) false
set ns_red (wait) true

This class also inherits from the Var class.

The corresponding constructor in red.cc
REDQueue::REDQueue()
{
        Tcl& tcl = Tcl::instance();

        link_bool("ns_red", "bytes", &edp_.bytes, 0);
        link_real("ns_red", "thresh", &edp_.th_min, 0);
        link_real("ns_red", "maxthresh", &edp_.th_max, 0);
        link_int("ns_red", "mean_pktsize", &edp_.mean_pktsize, 0);
        link_real("ns_red", "q_weight", &edp_.q_w, 0);
        link_bool("ns_red", "wait", &edp_.wait, 0);
        link_real("ns_red", "linterm", &edp_.max_p_inv, 0);
        link_bool("ns_red", "setbit", &edp_.setbit, 0);
        link_bool("ns_red", "drop-tail", &drop_tail_, 0);

        link_bool("ns_red", "doubleq", &doubleq_, 0);
        link_int("ns_red", "dqthresh", &dqthresh_, 0);
} 

NsObject (object.h, object.cc)

This class includes the tcl.h class as well. It contains the NsObject class which inherits from the TclObject class. The Var pointer of the var class is also defined. This is responsible for handling the inputs from the ns_default.tcl file.

Object.cc

This file includes the tcl.h, object.h, and trace.h files.

NsObject::NsObject()

The NsObject constructor sets the default values for the var and trace variables equal to 0.

void NsObject::insert(Var* p)

This object inserts the variable that is declared to the list of variables of the particular NsObject hence created. It takes in the pointer to the variable as an argument and returns nothing.

int NsObject::command(int argc, const char*const* argv)

This command function interprets the command in ns_default.tcl file. Then it matches it with the lowest class in the TclObject hierarchy. It does not match with any of the cases in the link::command function so it is passed to the upper class in the object hierarchy i.e. the NsObject command function. Here it gets the match in the form of the set function and the get function. The set case sets the values for the particular variable. The get case returns the value. The trace case switches on the trace mode set for connections.

$link0 set bandwidth $bw
$link0 set delay $delay
int Link::command(int argc, const char*const* argv)
int NsObject::command(int argc, const char*const* argv)

Var* NsObject::varlookup(const char*var ) const

As must be evident from the very name of this function. Given the reference to the name of the variable, it searches the name in the list and returns a pointer to the variable. In case it is not found it returns that the particular object is not found. //How is this function invoked???

Int NsObject::get(const char*var )

This function is invoked from the Command function ( described above ) after looking at the "set" keyword in the ns_default.tcl file. It invokes the varlookup function ( described above as well ) which matches the name whether it is there or not and returns the var object. The get function then eventually returns the tcl instance of this variable and its value. If the varlookup returns a null i.e. it did not find the name in the list it returns an error.

Int NsObject::set(const char*var, const char*val)

This function too is invoked by the Command function described earlier after matching with the "get" keyword in the ns_default.tcl file. It takes in two arguments, the name of the function and the value that is supposed to be set. It invokes the varlookup routine first to see whether the variable name exists in the list of variables or not. If yes then it checks to see whether its value is readonly or not, if it is readonly it does not set the value and prompts that it is readonly and hence cannot be modified. On the other hand if the value is not readonly it sets the value attribute of the variable.

void NsObject::link_real(const char* a, const char* name, double* val, int readOnly)

This function gets invoked from the different link files. For example in the file red.cc. It invokes the VarReal function which declares a variable that can take in real numbers. It also sets the values of the name and characteristics of that particular TclInstance belonging to the variable.

link_real ("ns_red", "thresh", &edp_.th_min, 0);

link_real ("ns_red", "maxthresh", &edp_.th_max, 0);

void NsObject::link_bw(const char* a, const char* name, double* val, int readOnly)

This function gets invoked from the link files. For example the link.cc file. It inovkes the VarBandwidth function in return ( which inherits from the VarReal function ). This function returns the variable of type VarBandwidth. Then the set function is invoked which sets the name and value of that particular variable to the TclObject. Eventually the insert function is called which adds it to the list of variables.

link_bw("ns_link", "bandwidth", &bandwidth_, 0);

void NsObject::link_time(const char* a, const char* name, double* val, int readOnly)

This function gets invoked as a result of the following commands in the link.cc files. This function declares an object of type VarTime which inherits from the Class VarReal. This variable in turn is given to the set function which sets the name of the function and its value i.e. ns_link and delay values. It then invokes the insert function which inserts this variable in the list of variables.

link_time("ns_link", "delay", &delay_, 0)

void NsObject::link_int(const char* a, const char* name, double* val, int readOnly)

This function gets invoked as a result of the following commands in link.cc. This function declares an object of type VarInt which inherits from the class Var. This variable is turn is given to the set function which sets the name of the function and its values. It then invokes the insert function which inserts this variables in the list of variables.

link_int("ns_link", "queue-limit", &qlim_, 0);
link_int(0, "queue-length", &qnp_, 1);
link_int(0, "queue-size", &qnb_, 1);

void NsObject::link_bool(const char* a, const char* name, double* val, int readOnly)

This function gets invoked as a result of the following commands in red.cc. This function declares an object of type VarBool which inherits from the class VarInt. This variable is turn is given to the set function which sets the name of the function and its values. It then invokes the insert function which inserts this variables in the list of variables.

link_bool("ns_red", "bytes", &edp_.bytes, 0);

double bw_atof(const char*s )

This function converts the input at the ns_default.tcl file

e.g

set ns_link(bandwidth) 1.5Mb

It takes it in and converts it into its reall units i.e., 1.5 million bits.

double time_atof(const char* s)

It takes the input time in the units and conversts it into the appropriate number. There are various case options available for it. m millisecod, u microsecond, n nanoseconds, p pecosecond.

set ns_link(delay) 100ms

Agent (agent.h, agent.cc)

The object.h and scheduler.h are the headers included in the header of agent.h. The class agent inherits from the Handler and NsObject classes. This is the base Agent class, those classes inheriting from this class have to add the functions declared as virtual on their own. For examples all the classes that will inherit from the agent class will have to make their own destructor and receive functions. Some of its private members are as follows: Node* node gives the local node of the agent. sport_ gives the local node, i.e. the address within the node. daddr_ gives the destination address. dport_ gives the destination port. seqno_ gives the current sequence number. size_ gives the fixed packet size. type_ gives the type to place in the packet header. class_ gives the class to place in the packet header. uid_ gives the id of the user.

agent.cc

static class NullAgentMatcher

This is the matcher class for this agent. It inherits from the base Matcher class. It invokes the constructor from the keyword agent. The NullAgent is not an agent of a particular type it is an ordinary agent inheriting from the Agent class.

Agent::Agent ( int pkttype)

It sets the default values for different variables required to be set. It calls the memset function that sets the pending and sizeof pending values. It also invokes the link_int function it initializes the class variable and its values.

int Agent::command(int arg, const char*const* argv)

This file gets the input from the ns_default.tcl file. It matches the address adr of the sink and the source src. This files takes input and interprets and accepts the input. There are two types of arguments, either a function is get ( i.e. with arg 2 ), which returns a value.

For the cases where argc == 3 this sets the values for the variables.

$agent node $node

This command function matches the node keyword and assigns the value of the variable node to the given value. Commands of this form such as "leave" " join" etc set values for these for multcast-forward routing. etc.

If it sees such a command in the ns_default.tcl file it returns the node corresponding to that particular agent.

proc ns_connect { src sink } {
        $src connect [$sink addr] [$sink port]
        $sink connect [$src addr] [$src port]
}

When for example this line is read by the command function, it associates the addresses with the corresponding sink and src agents with the sink agent and source agents respectively. It also returns the port numbers at the appropriate input commands.with the sink ( agent ) and the source address to the source. It also attatches the port as well.

The command $agent dst-addr will be interpreted by this function so as to return the address of the destination node.

The command $agent seqno will be interpreted by this function so as to return the sequence nmber of the node agent.

void Agent::handle(Event* e)

The timer can handle two types of events, it can either be a packet to be handled or it can be a timer interrupt. If it is a packet, it sends it to another function Agent::recv(p) to handle. If the program is working well the packet should not come to the base class NullAgent, it ought to have been handled by the source or sink agents. This NullAgent only frees the packet. It only sets the Timeout timer since it is the base class.

Packet* Agent::allocpkt(int seqno) const

This function allocates a packet using the Packet::alloc() function. Then it initalizses all its generic attributes and returns the packet. It only takes in the sequence number of the packet as an argument.

This function is invoked for example whenever a packet needs to be generated. e.g in the tcp.cc file void TcpAgent::output(int seqno ) it calls this allocpkt function to get a packet with the given sequence number.

Trace (trace.h, trace.cc)

This class inherits from the NsObject class. It actually outputs the results of the simulation into an output file..So it actually gets attatched to the file in the tes-suite.tcl file, it opens the file in which it is supposed to flush the output of the simulation.

void Trace::format(int tt, int s, int d, Packet* p)

This function formats the output in the form of a string. The dump function eventually dumps it into the output file. This is the sample of the input file, test-suite.tcl. Which activates the trace. It opens the traceFile out.tr w. It is also given the time at which the trace is supposed to begin.

proc openTrace { stopTime testName } {
        exec rm -f out.tr temp.rands
        global r1 k1    
        set traceFile [open out.tr w]
        ns at $stopTime \
                "close $traceFile ; finish $testName"
        set T [ns trace]
        $T attach $traceFile
        return $T
}

loss-policy.cc

NS Defaults (ns_default.tcl)

This file contains the default values for parameters required for different tcp algorithms. Apart from this it also contains default values for different link characteristics such as bandwidth and delay. It also specifies values for default source types such as bursty, telnet etc.

proc ns_connect{ srck link }

{ $src connect [$sink addr] [$sink port]

$sink connect [$src addr] [$src port] }

ns connect{sink src}

proc ns_duplex { n1 n2 bw delay type } {
        set link0 [ns link $n1 $n2 $type]
        $link0 set bandwidth $bw
        $link0 set delay $delay
        set link1 [ns link $n2 $n1 $type]
        $link1 set bandwidth $bw
        $link1 set delay $delay
        return "$link0 $link1"
}

This function is invoked by the ns_create_connection function, it basically establishes a tcp connection between a certain source and sink. The address gives the address of the source ( whether source or sink ) and its port corresponds to the connection originating from that source/sink . ns_duplex This function creates a full duplex link ( i.e. implements it as two links either way between two nodes ). The user only gives specifications of delay, bandwidth and type ( drop tail...etc ) and this function makes a full duplx link corresponding to these specifications.

proc ns_create_connection { srcType srcNode sinkType sinkNode class } {
        set src [ns agent $srcType $srcNode]
        set sink [ns agent $sinkType $sinkNode]
        $src set class $class
        $sink set class $class
        ns_connect $src $sink
        return $src
}

This function takes in the type and address of the source and sink nodes and returns the source. It sets the source and sink types and establishes the connection using the ns_connect function. ns_create_reno This function creates a Reno Tcp connection with a Source/Sink pairs. It also sets the default values for maximum window size, the start time of the connection and the class algortihm being used. ns_create_cbr This function creates the source sink cbr connection pair and returns the source agent.

proc ns { cmd args } {
        global ns_compat

#Added for ATM to TCP connection
        if { $cmd == "connect" } {
                if { [llength $args] == 3 } {
                        connect $args
                        return
                }
                else {
                puts stderr "ns: Syntax 'ns $cmd tcp_node atm_network at
m_node'"
                }
        }
        if { $cmd == "add-link" } {
                if { [llength $args] == 2 } {
                        add-link $args
                        return
                }
        }
        if { $cmd == "add-node" } {
                if { [llength $args] == 2 } {
                        add-node $args
                        return
              }
        }
#       if { $cmd == "atm-node" } {
#               if { [llength $args] == 2 } {
#                       atm-node $args
#                       return
#               }
#       }
#       if { $cmd == "atm-link" } {
#               if { [llength $args] == 3 } {
#                       atm-link $args
#                       return
#               }
#       }
        if { $cmd == "node" } {
                if { [llength $args] == 2 } {
        #If the node is an atm-network then treat just like an ordinary 
node
                        if { [lindex $args 0] == "atm-network" } {
                                set node [new atm-network]
                                set routelogic [new [lindex $args 1]]
                                $node route $routelogic
                        }
                        if { [lindex $args 0] == "atm-switch" } {
                                set type [lindex $args 1]
                                set node [new atm-switch $type]
                                return $node          
                      }
                }
                if { [llength $args] == 1 } {
                        if { [lindex $args 0] == "atm-network" } {
                                set node [new atm-network]
                                set routelogic [new min-hop]
                                $node route $routelogic
                        }
                #If the node is an atm-source or a switch then do not ad
d to 
                        #the original NS routing.
                        if { [lindex $args 0] == "atm-source" } {
                                set node [new atm-source]
                                return $node
                        }
                }
                if { [llength $args] == 0 } {
                        set node [new node]
                }
                if ![info exists ns_compat(route-logic)] {
                        set ns_compat(route-logic) [new route-logic]
                }
                $ns_compat(route-logic) insert $node
                return $node
        }
        if { $cmd == "link" } {
                if { [llength $args] == 3 } {
                        set src [lindex $args 0]
                        set dst [lindex $args 1]
                        set type [lindex $args 2]
                        set L [new link $type]
                        $L install $src $dst
                        if { $type != "atm" } {
                                set ns_compat(link:$src:$dst) $L
                        }
                        return $L
                }
                if { [llength $args] == 2 } {
                        set src [lindex $args 0]
                        set dst [lindex $args 1]
                        return $ns_compat(link:$src:$dst)
                }
                if { $args == "" } {
                        set L ""
                        foreach v [array names ns_compat] {
                                if [string match link:* $v] {
                                        lappend L $ns_compat($v)
                                }
                        }
                        return $L
                }
        }
        if { $cmd == "agent" } {
                if { [llength $args] == 2 } {
                        set type [lindex $args 0]
                        set node [lindex $args 1]
                        set agent [new agent $type]
                        $agent node $node
                        return $agent
                }
        }
        if { $cmd == "trace" } {
                set trace [new trace]
                return $trace
        }
        if { $cmd == "at" } {
                eval ns-at $args
                return
        }
        if { $cmd == "now" } {
                return [ns-now]
        }
        if { $cmd == "random" } {
                return [eval ns-random $args]
        }
        if { $cmd == "run" } {
                $ns_compat(route-logic) compute-routes
                ns-run
                return
        }
        puts stderr "ns: backward compat doesn't handle 'ns $cmd $args'"
        exit 1
}

This function matches with and executes all the commands starting with the keyword ( ns ). If the string following 'ns' matches the given string, it computes whether it is accompanying the right number of arguments required for that command and executes the required statement, other wise it returns the standard error output.

proc ns_connect { src sink } {
        $src connect [$sink addr] [$sink port]
        $sink connect [$src addr] [$src port]
}

This gets executed if the connect string is matched after the ns keyword, and it is followed by three arguments, the atm-node, the source and the sink, if all are matched the function connect $args is called which ns add-node Given an ATM node and a TCP sink, it associ