doc/manual/internet.texi
author Tom Henderson <tomh@tomh.org>
Mon, 19 Oct 2009 07:54:31 -0700
changeset 5434 81a3858041a8
parent 5426 7b36d173c490
child 6680 0e81f526bd49
permissions -rw-r--r--
additional manual cleanup

@node Internet Stack
@chapter Internet Stack

@section Internet stack aggregation

A bare @code{class Node} is not very useful as-is; other objects
must be aggregated to it to provide useful node functionality.

The ns-3 source code directory @code{src/internet-stack} provides
implementation of TCP/IPv4- and IPv6-related components.  These include IPv4,
ARP, UDP, TCP, IPv6, Neighbor Discovery, and other related protocols.

Internet Nodes are not subclasses of class Node; they are simply Nodes 
that have had a bunch of IPv4-related
objects aggregated to them.  They can be put together by hand, or
via a helper function @code{InternetStackHelper::Install ()} which does the 
following to all nodes passed in as arguments:
@smallformat
@example
void
InternetStackHelper::Install (Ptr<Node> node) const
{
  if (node->GetObject<Ipv4> () != 0)
    {
      NS_FATAL_ERROR ("InternetStackHelper::Install(): Aggregating "
                      "an InternetStack to a node with an existing Ipv4 object");
      return;
    }

  CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol");
  CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3Protocol");
  CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol");
  CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol");
  node->AggregateObject (m_tcpFactory.Create<Object> ());
  Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
  node->AggregateObject (factory);
  // Set routing
  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
  Ptr<Ipv4RoutingProtocol> ipv4Routing = m_routing->Create (node);
  ipv4->SetRoutingProtocol (ipv4Routing);
}
@end example
@end smallformat

Where multiple implementations exist in ns-3 (TCP, IP routing), these
objects are added by a factory object (TCP) or by a routing helper
(m_routing).

Note that the routing protocol is configured and set outside this
function.  By default, the following protocols are added to Ipv4:
@verbatim
InternetStackHelper::InternetStackHelper ()
{
  SetTcp ("ns3::TcpL4Protocol");
  static Ipv4StaticRoutingHelper staticRouting;
  static Ipv4GlobalRoutingHelper globalRouting;
  static Ipv4ListRoutingHelper listRouting;
  listRouting.Add (staticRouting, 0);
  listRouting.Add (globalRouting, -10);
  SetRoutingHelper (listRouting);
}
@end verbatim

By default, IPv4 and IPv6 are enabled.

@subsection Internet Node structure

An IPv4-capable Node (an ns-3 Node augmented by aggregation to have one or more
IP stacks) has the following internal structure.

@subsubsection Layer-3 protocols
At the lowest layer, sitting above the NetDevices, are the "layer 3" 
protocols, including IPv4, IPv6 (in the future), and ARP.  The 
@code{class Ipv4L3Protocol} is an 
implementation class whose public interface is 
typically @code{class Ipv4} (found in src/node directory), but the 
Ipv4L3Protocol public API is also used internally in the 
src/internet-stack directory at present.

In class Ipv4L3Protocol, one method described below is @code{Receive ()}:
@smallformat
@example
 /**
   * Lower layer calls this method after calling L3Demux::Lookup
   * The ARP subclass needs to know from which NetDevice this
   * packet is coming to:
   *    - implement a per-NetDevice ARP cache
   *    - send back arp replies on the right device
   */
  void Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, 
const Address &from, const Address &to, NetDevice::PacketType packetType);
@end example
@end smallformat

First, note that the @code{Receive ()} function has a matching signature
to the ReceiveCallback in the @code{class Node}.  This function pointer
is inserted into the Node's protocol handler when 
@code{AddInterface ()} is called.  The actual registration is done
with a statement such as:
follows:
@verbatim
 RegisterProtocolHandler ( MakeCallback (&Ipv4Protocol::Receive, ipv4),
    Ipv4L3Protocol::PROT_NUMBER, 0);
@end verbatim

The Ipv4L3Protocol object is aggregated to the Node; there is only one
such Ipv4L3Protocol object.  Higher-layer protocols that have a packet
to send down to the Ipv4L3Protocol object can call 
@code{GetObject<Ipv4L3Protocol> ()} to obtain a pointer, as follows:
@verbatim
  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
  if (ipv4 != 0)
    {
      ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
    }
@end verbatim

This class nicely demonstrates two techniques we exploit in
ns-3 to bind objects together:  callbacks, and object aggregation.

Once IPv4 routing has determined that a packet is for the local node, it 
forwards it up the stack.  This is done with the following function:

@smallformat
@example
void
Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
@end example
@end smallformat

The first step is to find the right Ipv4L4Protocol object , based on IP protocol
number.  For instance, TCP is registered in the demux as protocol number 6.
Finally, the @code{Receive()} function on the Ipv4L4Protocol (such as
@code{TcpL4Protocol::Receive} is called.

We have not yet introduced the class Ipv4Interface.  Basically,
each NetDevice is paired with an IPv4 representation of such device.
In Linux, this @code{class Ipv4Interface} roughly corresponds to
the @code{struct in_device}; the main purpose is to provide 
address-family specific information (addresses) about an interface.

The IPv6 implementation follows a similar architecture.

@subsubsection Layer-4 protocols and sockets

We next describe how the transport protocols, sockets, and applications
tie together.  In summary, each transport protocol implementation is
a socket factory.  An application that needs a new socket 

For instance, to create a UDP socket, an application would use a code
snippet such as the following:
@verbatim
      Ptr<Udp> udpSocketFactory = GetNode ()->GetObject<Udp> ();
      Ptr<Socket> m_socket = socketFactory->CreateSocket ();
      m_socket->Bind (m_local_address);
      ...
@end verbatim 
The above will query the node to get a pointer to its UDP socket
factory, will create one such socket, and will use the socket with
an API similar to the C-based sockets API, such as @code{Connect ()}
and @code{Send ()}.  See the chapter on ns-3 sockets for more information.  

We have described so far a socket factory (e.g. @code{class Udp}) and
a socket, which may be specialized (e.g., @code{class UdpSocket}).
There are a few more key objects that relate to the specialized
task of demultiplexing a packet to one or more receiving sockets.
The key object in this task is @code{class Ipv4EndPointDemux}.
This demultiplexer stores objects of @code{class Ipv4EndPoint}.
This class holds the addressing/port tuple (local port, local address, 
destination port, destination address) associated with the socket, 
and a receive callback.  This receive callback has a receive
function registered by the socket.  The @code{Lookup ()} function to
Ipv4EndPointDemux returns a list of Ipv4EndPoint objects (there may
be a list since more than one socket may match the packet).  The
layer-4 protocol copies the packet to each Ipv4EndPoint and calls
its @code{ForwardUp ()} method, which then calls the @code{Receive ()}
function registered by the socket.

An issue that arises when working with the sockets API on real
systems is the need to manage the reading from a socket, using 
some type of I/O (e.g., blocking, non-blocking, asynchronous, ...).
ns-3 implements an asynchronous model for socket I/O; the application
sets a callback to be notified of received data ready to be read, and the 
callback is invoked by the transport protocol when data is available.
This callback is specified as follows:
@verbatim
  void Socket::SetRecvCallback (Callback<void, Ptr<Socket>, 
    Ptr<Packet>, const Address&> receivedData);
@end verbatim
The data being received is conveyed in the Packet data buffer.  An example
usage is in @code{class PacketSink}:
@verbatim
  m_socket->SetRecvCallback (MakeCallback(&PacketSink::HandleRead, this));
@end verbatim

To summarize, internally, the UDP implementation is organized as follows:
@itemize @bullet
@item a @code{UdpImpl} class that implements the UDP socket factory
functionality
@item a @code{UdpL4Protocol} class that implements the protocol logic
that is socket-independent 
@item a @code{UdpSocketImpl} class that implements socket-specific aspects
of UDP
@item a class called @code{Ipv4EndPoint} that stores the
addressing tuple (local port, local address, destination port, destination
address) associated with the socket, and a receive callback for the socket.
@end itemize

@subsection Ipv4-capable node interfaces

Many of the implementation details, or internal objects themselves, 
of Ipv4-capable Node objects are not exposed at the simulator public
API.  This allows for different implementations; for instance, 
replacing the native ns-3 models with ported TCP/IP stack code. 
 
The C++ public APIs of all of these objects is found in the
@code{src/node} directory, including principally:
@itemize @bullet
@item @code{socket.h}
@item @code{tcp.h}
@item @code{udp.h}
@item @code{ipv4.h}
@end itemize 
These are typically base class objects that implement the default
values used in the implementation, implement access methods to get/set
state variables, host attributes, and implement publicly-available methods 
exposed to clients such as @code{CreateSocket}.

@subsection Example path of a packet

These two figures show an example stack trace of how packets flow
through the Internet Node objects.

@float Figure,fig:internet-node-send
@caption{Send path of a packet.}
@image{figures/internet-node-send,5in}
@end float

@float Figure,fig:internet-node-recv
@caption{Receive path of a packet.}
@image{figures/internet-node-recv,5in}
@end float