doc/manual/tcp.texi
author Tom Henderson <tomh@tomh.org>
Fri, 04 Sep 2009 17:23:34 -0700
changeset 4755 04a9a7e9a624
parent 4411 a0b70aae6217
child 5434 81a3858041a8
permissions -rw-r--r--
Manual spelling fixes from Johannes Buchner

@node TCP
@chapter TCP models in ns-3
@anchor{chap:TCP}

This chapter describes the TCP models available in ns-3.

@section Generic support for TCP

ns-3 was written to support multiple TCP implementations.  The 
implementations inherit from a few common header classes in the
@code{src/node} directory, so that user code can swap out implementations
with minimal changes to the scripts.

There are two important abstract base classes:
@itemize @bullet
@item @code{class TcpSocket}:  This is defined in @code{src/node/tcp-socket.@{cc,h@}}.  This class exists for hosting TcpSocket attributes that can be
reused across different implementations.  For instance, 
@code{TcpSocket::SetInitialCwnd()} can be used for any of the implementations
that derive from @code{class TcpSocket}.
@item @code{class TcpSocketFactory}:  This is used by applications to
create TCP sockets.  A typical usage can be seen in this snippet:
@verbatim
  // Create the socket if not already created
  if (!m_socket)
    {
      m_socket = Socket::CreateSocket (GetNode(), m_tid);
      m_socket->Bind (m_local);
      ...
    }
@end verbatim
The parameter @code{m_tid} controls the TypeId of the actual TCP Socket
implementation that is instantiated.  This way, the application can be
written generically and different socket implementations can be swapped out
by specifying the TypeId.
@end itemize  

@section ns-3 TCP

ns-3 contains a port of the TCP model from 
@uref{http://www.ece.gatech.edu/research/labs/MANIACS/GTNetS/index.html,,GTNetS}.  This model is a full TCP, in that it is 
bidirectional and attempts to model the connection setup and
close logic.  In fact, it is a more complete implementation of the TCP
state machine than ns-2's "FullTcp" model.  This TCP model was originally 
written by George Riley
as part of GTNetS and ported to ns-3 by Raj Bhattacharjea.

The implementation of TCP is contained in the following files:
@verbatim
src/internet-stack/tcp-header.{cc,h}
src/internet-stack/tcp-l4-protocol.{cc,h}
src/internet-stack/tcp-socket-factory-impl.{cc,h}
src/internet-stack/tcp-socket-impl.{cc,h}
src/internet-stack/tcp-typedefs.h
src/internet-stack/rtt-estimator.{cc,h}
src/internet-stack/sequence-number.{cc,h}
@end verbatim

@subsection Usage

The file @code{examples/tcp-star-server.cc} contains an example that
makes use of @code{ns3::OnOffApplication} and @code{ns3::PacketSink} 
applications.

Using the helper functions defined in @code{src/helper}, here is how
one would create a TCP receiver:
@verbatim
  // Create a packet sink on the star "hub" to receive these packets
  uint16_t port = 50000;
  Address sinkLocalAddress(InetSocketAddress (Ipv4Address::GetAny (), port));
  PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
  ApplicationContainer sinkApp = sinkHelper.Install (serverNode);
  sinkApp.Start (Seconds (1.0));
  sinkApp.Stop (Seconds (10.0));
@end verbatim

Similarly, the below snippet configures OnOffApplication traffic
source to use
TCP:
@verbatim
  // Create the OnOff applications to send TCP to the server
  OnOffHelper clientHelper ("ns3::TcpSocketFactory", Address ());
@end verbatim

The careful reader will note above that we have specified the TypeId
of an abstract base class @code{TcpSocketFactory}.  How does the
script tell ns-3 that it wants the native ns-3 TCP vs. some other one?
Well, when internet stacks are added to the node, the default
TCP implementation that is aggregated to the node is the ns-3 TCP.
This can be overridden as we show below when using Network
Simulation Cradle.  So, by default, when using the ns-3 helper API,
the TCP that is aggregated to nodes with an Internet stack is the
native ns-3 TCP.

Once a TCP socket is created, you will want to follow conventional
socket logic and either connect() and send() (for a TCP client)
or bind(), listen(), and accept() (for a TCP server).  
@xref{Sockets APIs,,Sockets API} for a review of how sockets are used
in ns-3.

To configure behavior of TCP, a number of parameters are exported through
the @ref{Attributes,,ns-3 attribute system}.  These are documented in the
@uref{http://www.nsnam.org/doxygen/classns3_1_1_tcp_socket.html,,Doxygen} 
for @code{class TcpSocket}.

@subsection Current limitations
@itemize @bullet
@item Only Tahoe congestion control is presently supported.
@item Only IPv4 is supported (IPv6 support will start to be added in ns-3.3).
@item @uref{http://www.nsnam.org/bugzilla/show_bug.cgi?id=198,,Bug 198}:  TcpSocketImpl doesn't send acks with data packets in two-way transfers
@item @uref{http://www.nsnam.org/bugzilla/show_bug.cgi?id=250,,Bug 250}:  Tcp breaks if you set the DelAckCount parameter to be greater than 2
@item @uref{http://www.nsnam.org/bugzilla/show_bug.cgi?id=311,,Bug 311}:  Tcp socket close returns -1 but does not set errno.
@end itemize

@section Network Simulation Cradle

The @uref{http://www.wand.net.nz/~stj2/nsc/,,Network Simulation Cradle (NSC)} 
is a framework for wrapping real-world network
code into simulators, allowing simulation of real-world behavior at little 
extra cost.  This work has been validated by comparing situations using 
a test network with the same situations in the simulator. To date, it has 
been shown that the NSC is able to produce extremely accurate results.
NSC supports four real world stacks: FreeBSD, OpenBSD, lwIP and Linux.
Emphasis has been placed on not changing any of the network stacks by hand. 
Not a single line of code has been changed in the network protocol 
implementations of any of the above four stacks. However, a custom C 
parser was built to programmatically change source code.

NSC has previously been ported to ns-2 and OMNeT++, and recently 
was added to ns-3.  This section describes the ns-3 port of NSC and
how to use it.

@subsection Prerequisites

Presently, NSC has been tested and shown to work on these platforms:
Linux i386 and Linux x86-64.  NSC does not support powerpc at the moment.

NSC requires the packages mercurial, flex, and bison.  

@subsection Configuring and Downloading

NSC is disabled by default and must be explicitly configured in.  To try
this, type
@verbatim
./waf configure --enable-nsc
@end verbatim
the output of the configuration will show something like:
@verbatim
Checking for NSC supported architecture x86_64                           : ok  
Pulling nsc updates from https://secure.wand.net.nz/mercurial/nsc
pulling from https://secure.wand.net.nz/mercurial/nsc
searching for changes
no changes found
---- Summary of optional NS-3 features:
...
Network Simulation Cradle     : enabled
...
@end verbatim 
if successful.  Note that the configure script pulls a recent copy of
NSC from a mercurial repository.  This download will not work if you are not
online.

If everything went OK, you will see a directory called "nsc" in the top-level
directory, with contents like this:
@verbatim
audit.sh            linux-2.6/          openbsd3/           scons-time.py*
ChangeLog           linux-2.6.18/       README              SConstruct 
config.log          linux-2.6.26/       sconsign.py*        sim/
freebsd5/           lwip-1.3.0/         scons-LICENSE       test/
globaliser/         lwip-HEAD/          scons-local-1.0.1/  
INSTALL             ns/                 scons.py*           
LICENSE             omnetpp/            scons-README        
@end verbatim

@subsection Building and validating

Building ns-3 with nsc support is the same as building it without; no
additional arguments are needed for waf.  Building nsc may take some time
compared to ns-3; it is interleaved in the ns-3 building process.

Try running the regression tests: @code{./waf --regression}.  If NSC has
been successfully built, the following test should show up in the results:
@verbatim
PASS test-tcp-nsc-lfn
@end verbatim

This confirms that NSC is ready to use.

@subsection Usage
There are a few example files.  Try
@verbatim
./waf --run tcp-nsc-zoo
./waf --run tcp-nsc-lfn
@end verbatim
These examples will deposit some @code{.pcap} files in your directory,
which can be examined by tcpdump or wireshark.

Let's look at the @code{examples/tcp-nsc-zoo.cc} file for some typical
usage.  How does it differ from using native ns-3 TCP?  There is one
main configuration line, when using NSC and the ns-3 helper API, that needs
to be set:
@verbatim
  InternetStackHelper internetStack;

  internetStack.SetNscStack ("liblinux2.6.26.so");
  // this switches nodes 0 and 1 to NSCs Linux 2.6.26 stack.
  internetStack.Install (n.Get(0));
  internetStack.Install (n.Get(1));
@end verbatim

The key line is the @code{SetNscStack}.  This tells the InternetStack
helper to aggregate instances of NSC TCP instead of native ns-3 TCP
to the remaining nodes.  It is important that this function be called
@strong{before} calling the @code{Install()} function, as shown above.

Which stacks are available to use?  Presently, the focus has been on
Linux 2.6.18 and Linux 2.6.26 stacks for ns-3.  To see which stacks
were built, one can execute the following find command at the ns-3 top level
directory:
@verbatim
~/ns-3.2> find nsc -name "*.so" -type f 
nsc/linux-2.6.18/liblinux2.6.18.so
nsc/linux-2.6.26/liblinux2.6.26.so
@end verbatim
This tells us that we may either pass the library name liblinux2.6.18.so or 
liblinux2.6.26.so to the above configuration step.

@subsection Stack configuration
NSC TCP shares the same configuration attributes that are common
across TCP sockets, as described above and documented in 
@uref{http://www.nsnam.org/doxygen/classns3_1_1_tcp_socket.html,,Doxygen} 

Additionally, NSC TCP exports a lot of configuration variables into the 
ns-3 @ref{Attributes} system, via a @uref{http://en.wikipedia.org/wiki/Sysctl,,
sysctl}-like interface.  In the @code{examples/tcp-nsc-zoo} example, you
can see the following configuration:
@verbatim
  // this disables TCP SACK, wscale and timestamps on node 1 (the attributes represent sysctl-values).
  Config::Set ("/NodeList/1/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_sack", StringValue ("0"));
  Config::Set ("/NodeList/1/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_timestamps", StringValue ("0"));
  Config::Set ("/NodeList/1/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_window_scaling", StringValue ("0"));
@end verbatim
These additional configuration variables are not available to native ns-3
TCP.

@subsection NSC API

This subsection describes the API that NSC presents to ns-3 or any other
simulator.  NSC provides its API in the form of a number of classes that
are defined in @code{sim/sim_interface.h} in the nsc directory.

@itemize @bullet
@item @strong{INetStack}
INetStack contains the 'low level' operations for the operating system 
network stack, e.g. in and output functions from and to the network stack 
(think of this as the 'network driver interface'. There are also functions 
to create new TCP or UDP sockets.
@item @strong{ISendCallback}
This is called by NSC when a packet should be sent out to the network. 
This simulator should use this callback to re-inject the packet into the 
simulator so the actual data can be delivered/routed to its destination, 
where it will eventually be handed into Receive() (and eventually back to the 
receivers NSC instance via INetStack->if_receive() ).
@item @strong{INetStreamSocket}
This is the structure defining a particular connection endpoint (file 
descriptor). It contains methods to operate on this endpoint, e.g. connect, 
disconnect, accept, listen, send_data/read_data, ...
@item @strong{IInterruptCallback}
This contains the wakeup callback, which is called by NSC whenever 
something of interest happens. Think of wakeup() as a replacement of the 
operating systems wakeup function: Whenever the operating system would 
wake up a process that has been waiting for an operation to complete (for 
example the TCP handshake during connect()), NSC invokes the wakeup() callback 
to allow the simulator to check for state changes in its connection endpoints. 
@end itemize

@subsection ns-3 implementation

The ns-3 implementation makes use of the above NSC API, and is implemented
as follows.

The three main parts are:
@itemize @bullet
@item @code{ns3::NscTcpL4Protocol}:  a subclass of Ipv4L4Protocol (and two nsc classes: ISendCallback and IInterruptCallback)
@item @code{ns3::NscTcpSocketImpl}: a subclass of TcpSocket 
@item @code{ns3::NscTcpSocketFactoryImpl}:  a factory to create new NSC
sockets
@end itemize

@code{src/internet-stack/nsc-tcp-l4-protocol} is the main class. Upon 
Initialization, it loads an nsc network stack to use (via dlopen()). Each 
instance of this class may use a different stack. The stack 
(=shared library) to use is set using the SetNscLibrary() method (at 
this time its called indirectly via the internet stack helper). The nsc 
stack is then set up accordingly (timers etc). The 
NscTcpL4Protocol::Receive() function hands the packet it receives (must be 
a complete tcp/ip packet) to the nsc stack for further processing. 
To be able to send packets, this class implements the nsc send_callback 
method. This method is called by nsc whenever the nsc stack wishes to 
send a packet out to the network. Its arguments are a raw buffer, 
containing a complete TCP/IP packet, and a length value. This method 
therefore has to convert the raw data to a Ptr<Packet> usable by ns-3. 
In order to avoid various ipv4 header issues, the nsc ip header is not 
included. Instead, the tcp header and the actual payload are put into the 
Ptr<Packet>, after this the Packet is passed down to layer 3 for sending 
the packet out (no further special treatment is needed in the send code 
path).

This class calls @code{ns3::NscTcpSocketImpl} both from the nsc wakeup() 
callback and from the Receive path (to ensure that possibly queued data 
is scheduled for sending).


@code{src/internet-stack/nsc-tcp-socket-impl} implements the nsc socket 
interface. Each instance has its own nscTcpSocket. Data that is Send() 
will be handed to the nsc stack via m_nscTcpSocket->send_data(). (and not 
to nsc-tcp-l4, this is the major difference compared to ns-3 TCP). The 
class also queues up data that is Send() before the underlying 
descriptor has entered an ESTABLISHED state. This class is called from 
the nsc-tcp-l4 class, when the nsc-tcp-l4 wakeup() callback is invoked by 
nsc. nsc-tcp-socket-impl then checks the current connection state 
(SYN_SENT, ESTABLISHED, LISTEN...) and schedules appropriate callbacks as 
needed, e.g. a LISTEN socket will schedule Accept to see if a new 
connection must be accepted, an ESTABLISHED socket schedules any pending 
data for writing, schedule a read callback, etc.

Note that @code{ns3::NscTcpSocketImpl} does not interact with nsc-tcp 
directly: instead, data is redirected to nsc. nsc-tcp calls the 
nsc-tcp-sockets of a node when its wakeup callback is invoked by nsc. 

@subsection Limitations
@itemize @bullet
@item NSC only works on single-interface nodes; attempting to run it on
a multi-interface node will cause a program error.  This limitation should
be fixed by ns-3.3.
@item Cygwin and OS X PPC are not presently supported
@item The non-Linux stacks of NSC are not supported
@item NSC's integration into the build system presently requires on-line
access and mercurial, and is a slow download.
@end itemize

For more information, see
@uref{http://www.nsnam.org/wiki/index.php/Network_Simulation_Cradle_Integration,, this wiki page}.