Enhancement to FullTcpAgent in ns2

Overview

Simulating application data transfers in ns2 is often complicated by the gap between the ns2 implementation of TCP and the real-world socket interfaces provided by most operating systems.

First of all, the ns2 TCP implementation FullTcpAgent and its derivatives do not embody the important TCP flow control mechanism--the receiver advertised window. It also assumes that TCP receiving is never limited by the applications. We develop a subclass of FullTcpAgent, called AdvwTcpAgent, that implements the flow control and limited receiving application.

The second problem of FullTcpAgent is that it does not transfer real payload (user data), although the receiver knows the size of the payload when it receives a TCP packet. This prevents many application layer protocols from being implemented. FullTcpAgent is also not compatible with the behavior of a real TCP socket in that it does not spawn new connection dynamically as TCP connection requests arrive, and that it assumes unlimited TCP send buffer such that the applications are never blocked for sending. The SocketTcp class is a TCP agent that does real payload transfer, spawns new connections dynamically and has limited sender buffer.

Finally, most application developers are used to the socket interfaces provided by most operating systems. To facilitate the development of application simulations in ns2, we build a socket interface, NSSocket, to the TCP transport service. Notice that due to the sequential nature of discrete-event network simulations, we cannot have blocking socket operations. All changes of the socket status should be conveyed to the upper layer through upcalls. The rest of this document describes the APIs to the three classes.

TCP Agent with receiver advertised window (AdvwTcpAgent)

Applications of AdvwTcpAgent use the same interfaces to send certain amount of user data as the applications of FullTcpAgent. Additional interfaces between AdvwTcpAgent and its applications are defined:

Upcalls (AdvwTcpAgent to Application):
  virtual int upcall_recv(Packet *);                     //packet available
  virtual int upcall_recv(int nbytes) { return nbytes;}    //nbytes available for
  virtual void upcall_send();                              //TCP ready for sending
  virtual void upcall_closing() ;                          //socket being closed

Downcalls (Application tp AdvwTcpAgent):
    void tcp_command_nonblock_recv(int num_bytes);    //nonblocking receive
    void tcp_command_block_recv(int num_bytes);        //blocking receive, may fail

TCP Agent with real payload transfer (SocketTcp)

Downcalls:
    int sendmsg(PacketData *, int len);        //send a message with certain data and length
    void listen(int max);                               //listen for at most _max_ number of connection requests

Socket interface to SocketTcp (NSSocket)

Downcalls (APIs to user application):
    void connect(NodeAddr_t, Port_t);
    virtual int send(int len, PacketData *data);
    void bind(NodeAddr_t, Port_t);
    virtual void recv();
    int blocked(int op);
    void connect();
    void listen(int max);
    void close();
   
Upcalls (from SocketTcp to NSSocket):
    virtual void upcall_send();
    virtual int upcall_recv(PacketData *);
    void upcall_connected(Packet *);
    void upcall_passconn();
    void upcall_closing();
    void upcall_accept(Packet *);

Sample Script

(A simple tcl sample script can be obtained here)

1. it is necessary to create an SocketApp (or its subclasses) before you create a socket
       set app1 [new SocketApp]

2. create a socket with the node address, application, port number (-1 if the socket does not have to be bound to a specific port)
       set sock1 [$ns create-sock $nodeaddr1 $app1 6436]

3. attach the application to the socket
       $app1 attach $ssock

4. server listen, client connect
       $sock1 listen 10

        $ns at 2.0 "$sock2 connect nodeaddr1 6436"

5. applications on both side of the connection can initiate data transfer after the connection is established
        $ns at 5.0 "$app2 send 1000"

*Notice that SocketApp is a placeholder for applications that use NSSocket. It only implements very simple send/recv operations.
       

Getting the Code

The ns2 TCP enhancement code is included in the GnutellaSim package. It is also available separately here. Notice that if you have made changes to the agent.cc and agent.h from the original ns-2.1b7a package, you should extract the tarball to another directory temporarily so that you do not overwrite your own changes. Look for "Qi" in our agent.cc and agent.h files and make appropriate changes to yours.

mv tcpenh.tgz ~/ns-allinone-2.1b7a/ns-2.1b7a
tar xvfz tcpenh.tgz
(add tcp-advw.o and tcp-sock.o to the OBJ definition in the Makefile)
make