doc/tutorial/other.texi
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu, 17 Apr 2008 15:40:25 -0700
changeset 2971 75780f899be3
parent 2683 f55be8cf4fa8
child 3090 bb5c9e8041cd
permissions -rw-r--r--
output the initial value of the attributes

@c ========================================================================
@c Other Network Topologies
@c ========================================================================

@node Other-network-topologies
@chapter Other Network Topologies
@cindex topology
@cindex Channel
@cindex NetDevice
@cindex topology!bus
@cindex topology!point-to-point
@cindex PointToPointChannel
@cindex PointToPointNetDevice

@emph{Network topology} is the study of the arrangement of of the elements
(in @command{ns-3} represented by the classes @code{Channel} and @code{Node})
of a network.  Two fundamental types of physical topologies are the 
@emph{point-to-point} and @emph{bus} topologies.  We have already been exposed
to the @command{ns-3} channel specialization named @code{CsmaChannel}.  This is
a simulation of a bus network.  We also provide a simulation of a 
point-to-point channel with associated net devices.  As described previously,
the associated C++ classes specialize the @command{ns-3} base classes
@code{NetDevice} and @code{Channel} and are called @code{PointToPointNetDevice}
and @code{PointToPointChannel} respectively.

We will use combinations of these bus and point-to-point topology elements
to show how to create several commonly seen network topologies.

@section A Point-to-Point Network
We're going to take what might be seen as a step backward and look at a simple
point-to-point network.  We will be building the simplest network you can 
imagine.  A serial link (point to point) between two computers.  When you
see this point-to-point network, you can think of an RS-422 (or RS-232 for 
you old-timers) cable.  This topology is shown below.

@sp 1
@center @image{pp,,,,png}

@cindex CreateObject
@cindex InternetNode
We have provided a file for you in the @code{tutorial}
directory called @code{tutorial-point-to-point.cc}.  You should now be
familiar enough with the system to pick out fairly easily what has been
changed.  Let's focus on the following lines:

@verbatim
  Ptr<Node> n0 = CreateObject<InternetNode> ();
  Ptr<Node> n1 = CreateObject<InternetNode> ();

  Ptr<PointToPointChannel> link = PointToPointTopology::AddPointToPointLink (
    n0, n1, DataRate (38400), MilliSeconds (20));

  PointToPointTopology::AddIpv4Addresses (link, n0, "10.1.1.1",
    n1, "10.1.1.2");
@end verbatim

You can see that we created two @code{InternetNode} objects in the usual way.
Then, instead of creating a @code{CsmaChannel} we create a 
@code{PointToPointChannel}.  This point-to-point channel, which we call
@code{link}, connects node zero (@code{n0}) and node one (@code{n1}) over a
simulated link that runs at 38400 bits per second and has a 20 millisecond
simulated speed-of-light delay.  This call also creates appropriate net devices
and attaches them to nodes zero and one.

We then add IP addresses to the net devices we just created using the topology
helper @code{AddIpv4Addresses}.  Node zero gets the IP address 10.1.1.1 and
node one gets the IP address 10.1.1.2 assigned.  

The alert tutorial user may wonder what the network number or prefix is of
those IP addresses.  The point-to-point topology assumes that you want a
@code{/30} subnet and assigns an appropriate net mask for you.  It then then
@emph{asserts} that the network numbers of the two net devices match.  So there
is an implicit network mask created down in the topology code that looks like,

@verbatim
  Ipv4Mask netmask("255.255.255.252");
@end verbatim

The rest of the code you should recognize and understand.  We are just going
to echo one packet across the point-to-point link.  You should be now be able
to build and run this example and to locate and interpret the ASCII trace 
file.  This is left as an exercise for you.

The file @code{tutorial-point-to-point.cc} is reproduced here for your 
convenience:

@verbatim
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "ns3/log.h"
#include "ns3/ptr.h"
#include "ns3/internet-node.h"
#include "ns3/point-to-point-channel.h"
#include "ns3/mac48-address.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/point-to-point-topology.h"
#include "ns3/udp-echo-client.h"
#include "ns3/udp-echo-server.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include "ns3/ascii-trace.h"
#include "ns3/pcap-trace.h"
#include "ns3/global-route-manager.h"

NS_LOG_COMPONENT_DEFINE ("PointToPointSimulation");

using namespace ns3;

// Network topology
//
//                       point to point
//                      +--------------+
//                      |              |
//                     n0             n1
//
int 
main (int argc, char *argv[])
{
  LogComponentEnable ("PointToPointSimulation", LOG_LEVEL_INFO);

  NS_LOG_INFO ("Point to Point Topology Simulation");

  Ptr<Node> n0 = CreateObject<InternetNode> ();
  Ptr<Node> n1 = CreateObject<InternetNode> ();

  Ptr<PointToPointChannel> link = PointToPointTopology::AddPointToPointLink (
    n0, n1, DataRate (38400), MilliSeconds (20));

  PointToPointTopology::AddIpv4Addresses (link, n0, "10.1.1.1", 
    n1, "10.1.1.2");

  uint16_t port = 7;

  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2", 
    port, 1, Seconds(1.), 1024);

  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);

  server->Start(Seconds(1.));
  client->Start(Seconds(2.));

  server->Stop (Seconds(10.));
  client->Stop (Seconds(10.));

  AsciiTrace asciitrace ("tutorial.tr");
  asciitrace.TraceAllQueues ();
  asciitrace.TraceAllNetDeviceRx ();

  Simulator::Run ();
  Simulator::Destroy ();
}
@end verbatim

@section A Star Network
A point-to-point network is considered a special case of a star network.  As
you might expect, the process of constructing a star network is an extension
of the very simple process used for a point-to-point link.  We have provided
a file for you in the @code{tutorial} directory called @code{tutorial-star.cc}
that implements a simple star network as seen below.

@sp 1
@center @image{star,,,,png}

In order to create a star network, we need to be able to instantiate some
number (greater than one) of net devices on a node.  In the name of simplicity
of use, the @code{PointToPointTopology} topology helper does not allow one to
do this.  We provided a separate topology helper class, the 
@code{PointToPointIpv4Topology} helper class that provides the slightly finer
granularity we need to accomplish a star network.  In order to use this new
helper we have to load the definitions by including the appropriate file.

@verbatim
  #include "ns3/point-to-point-ipv4-topology.h"
@end verbatim

The star that we're going to create has a node in the center (@code{n0}) with
six nodes surrounding (@code{n1} - @code{n6}).  You should be able to easily
find and understand the code that creates these nodes.

@verbatim
  Ptr<Node> n0 = CreateObject<InternetNode> ();
  Ptr<Node> n1 = CreateObject<InternetNode> ();
  Ptr<Node> n2 = CreateObject<InternetNode> ();
  Ptr<Node> n3 = CreateObject<InternetNode> ();
  Ptr<Node> n4 = CreateObject<InternetNode> ();
  Ptr<Node> n5 = CreateObject<InternetNode> ();
  Ptr<Node> n6 = CreateObject<InternetNode> ();
@end verbatim

Next, we get into the differences between the @code{PointToPointTopology}
helper and the @code{PointToPointIpv4Topology} helper.  The
@code{PointToPointIpv4Topology} helper looks and feels a little like the 
@code{CsmaIpv4Topology} helper.  Just like you created a CSMA channel 
previously, you need to create a point-to-point channel.  The following
code creates a @code{PointToPointChannel} and calls it @code{link01}.  You can
interpret this name as being the channel (or @emph{link}) from node zero to 
node one.  

@verbatim
  Ptr<PointToPointChannel> link01 =
    PointToPointIpv4Topology::CreateChannel (DataRate (38400),
    MilliSeconds (20));
@end verbatim

You need to provide a data rate for the channel which we set at 38400 bits 
per second.  You must also provide a speed-of-light delay which we set at
20 milliseconds.

Just as you added a net device to the nodes in the CSMA tutorial section, you
do the same here but with a point-to-point net device.  The following code
illustrates how we do that:

@verbatim
  uint32_t nd01 = PointToPointIpv4Topology::AddNetDevice (n0,
    link01);
@end verbatim

We call the @code{PointToPointIpv4Topology} helper and ask it to add a net
device to node zero (@code{n0}) and connect it to the appropriate 
point-to-point link (@code{link01}) which you will recall is the serial link
from node zero to node one.

If you look at the following code, you will see the same calls are repeated
to create the remaining five point-to-point channels and connect them
to net devices on node zero.

The next new code is found after the ``spokes'' of the star have been created.
It looks like the following:

@verbatim
  uint32_t nd1 = PointToPointIpv4Topology::AddNetDevice (n1, link01);
  uint32_t nd2 = PointToPointIpv4Topology::AddNetDevice (n2, link02);
  uint32_t nd3 = PointToPointIpv4Topology::AddNetDevice (n3, link03);
  uint32_t nd4 = PointToPointIpv4Topology::AddNetDevice (n4, link04);
  uint32_t nd5 = PointToPointIpv4Topology::AddNetDevice (n5, link05);
  uint32_t nd6 = PointToPointIpv4Topology::AddNetDevice (n6, link06);
@end verbatim

Here we are creating the net devices on the nodes surrounding the center node.
In the first call, we are adding a net device on node one (@code{n1}) and
connecting that net device to the channel named @code{link01}.  Remember that
we created the channel @code{link01} as the channel connecting node zero and
node one.  We previously created a net device on node zero and attached that
device to @code{link01}.  Here we are connecting the other side of that link
to node one.  The return value from this call is the net device index of the
created net device.

The next section of code adds addresses to the net devices we just created.
The first call adds the IP address 10.1.1.1 to the net device going from 
node zero to node one.  Recall that we first created a node named @code{n0}
and a channel called @code{link01}.  We added a net device to @code{n0} and
remembered the net device index as the @code{uint32_t nd01}.  This meant
the net device @emph{nd} on node @emph{0} that we connected to node @emph{1}. 
We call @code{AddAddress} to add an IP address (10.1.1.1) to the net device
on node zero identified by the net device index @code{nd01}.  We provide a
net mask suitable for a point to point network.  This is typically a /30 
address but we don't force that in this API.

After setting up the address on node zero, we do the same for the node on
the other end of the ``spoke'' --- in this case node one, with its single
net device.  Note that the network number is the same on both sides of this
network.

@verbatim
  PointToPointIpv4Topology::AddAddress (n0, nd01, "10.1.1.1",
    ``255.255.255.252'');

  PointToPointIpv4Topology::AddAddress (n1, nd1, "10.1.1.2",
    ``255.255.255.252'');
@end verbatim

The following code repeats this pattern assining similar IP addresses to the
remaining net devices.  Note that there are no @code{Mac48Address} address
assignments --- they are not required.

The rest of the code you should recognize and understand.  We are just going
to echo one packet across the point-to-point link.  You should be now be able
to build and run this example and to locate and interpret the ASCII trace 
file.  This is left as an exercise for you.

The file @code{tutorial-star.cc} is reproduced here for your convenience:

@verbatim
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "ns3/log.h"
#include "ns3/ptr.h"
#include "ns3/internet-node.h"
#include "ns3/point-to-point-channel.h"
#include "ns3/mac48-address.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/point-to-point-ipv4-topology.h"
#include "ns3/udp-echo-client.h"
#include "ns3/udp-echo-server.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include "ns3/ascii-trace.h"
#include "ns3/pcap-trace.h"
#include "ns3/global-route-manager.h"

NS_LOG_COMPONENT_DEFINE ("StarSimulation");

using namespace ns3;

// Network topology
//
//                  n3    n2
//                   |   /
//                    | /
//              n4 --- n0 --- n1
//                    /  |
//                   /    |
//                  n5    n6

int 
main (int argc, char *argv[])
{
  LogComponentEnable ("StarSimulation", LOG_LEVEL_INFO);

  NS_LOG_INFO ("Star Topology Simulation");

  Ptr<Node> n0 = CreateObject<InternetNode> ();
  Ptr<Node> n1 = CreateObject<InternetNode> ();
  Ptr<Node> n2 = CreateObject<InternetNode> ();
  Ptr<Node> n3 = CreateObject<InternetNode> ();
  Ptr<Node> n4 = CreateObject<InternetNode> ();
  Ptr<Node> n5 = CreateObject<InternetNode> ();
  Ptr<Node> n6 = CreateObject<InternetNode> ();

  Ptr<PointToPointChannel> link01 = 
    PointToPointIpv4Topology::CreateChannel (DataRate (38400), 
    MilliSeconds (20));

  uint32_t nd01 = PointToPointIpv4Topology::AddNetDevice (n0,
    link01);

  Ptr<PointToPointChannel> link02 = 
    PointToPointIpv4Topology::CreateChannel (DataRate (38400), 
    MilliSeconds (20));

  uint32_t nd02 = PointToPointIpv4Topology::AddNetDevice (n0,
    link02);

  Ptr<PointToPointChannel> link03 = 
    PointToPointIpv4Topology::CreateChannel (DataRate (38400), 
    MilliSeconds (20));

  uint32_t nd03 = PointToPointIpv4Topology::AddNetDevice (n0,
    link03);

  Ptr<PointToPointChannel> link04 = 
    PointToPointIpv4Topology::CreateChannel (DataRate (38400), 
    MilliSeconds (20));

  uint32_t nd04 = PointToPointIpv4Topology::AddNetDevice (n0, 
    link04);

  Ptr<PointToPointChannel> link05 = 
    PointToPointIpv4Topology::CreateChannel (DataRate (38400), 
    MilliSeconds (20));

  uint32_t nd05 = PointToPointIpv4Topology::AddNetDevice (n0,
    link05);

  Ptr<PointToPointChannel> link06 = 
    PointToPointIpv4Topology::CreateChannel (DataRate (38400), 
    MilliSeconds (20));

  uint32_t nd06 = PointToPointIpv4Topology::AddNetDevice (n0, link06);

  uint32_t nd1 = PointToPointIpv4Topology::AddNetDevice (n1, link01);
  uint32_t nd2 = PointToPointIpv4Topology::AddNetDevice (n2, link02);
  uint32_t nd3 = PointToPointIpv4Topology::AddNetDevice (n3, link03);
  uint32_t nd4 = PointToPointIpv4Topology::AddNetDevice (n4, link04);
  uint32_t nd5 = PointToPointIpv4Topology::AddNetDevice (n5, link05);
  uint32_t nd6 = PointToPointIpv4Topology::AddNetDevice (n6, link06);

  PointToPointIpv4Topology::AddAddress (n0, nd01, "10.1.1.1", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n1, nd1, "10.1.1.2", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n0, nd02, "10.1.2.1", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n2, nd2, "10.1.2.2", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n0, nd03, "10.1.3.1", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n3, nd3, "10.1.2.2", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n0, nd04, "10.1.4.1", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n4, nd4, "10.1.4.2", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n0, nd05, "10.1.5.1", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n5, nd5, "10.1.5.2", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n0, nd06, "10.1.6.1", 
    "255.255.255.252");

  PointToPointIpv4Topology::AddAddress (n6, nd6, "10.1.6.2", 
    "255.255.255.252");

  uint16_t port = 7;

  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2", 
    port, 1, Seconds(1.), 1024);

  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);

  server->Start(Seconds(1.));
  client->Start(Seconds(2.));

  server->Stop (Seconds(10.));
  client->Stop (Seconds(10.));

  AsciiTrace asciitrace ("tutorial.tr");
  asciitrace.TraceAllQueues ();
  asciitrace.TraceAllNetDeviceRx ();

  Simulator::Run ();
  Simulator::Destroy ();
}
@end verbatim

@subsection Routing
If you are really excited about this simulator you may have already tried to
modify the scripts outside the tutorial.  I know that one of the first things
that would have occurred to me when I saw the star network would have been to
start trying to add applications to echo packets from nodes other than zero.
If you tried, for example, to start the echo client on node one instead of
node zero, you would have found an empty trace file.  The reason for this
is that you have now created an internetwork.  This means you will need to 
enable internetwork routing.

We have provided a file for you in the @code{tutorial} directory called 
@code{tutorial-star-routing.cc} to show you how this is done.  This extremely
tricky and difficult change is shown below:

@verbatim 
 GlobalRouteManager::PopulateRoutingTables ();
@end verbatim

This one-line addition, located just before the simulation runs, tells the 
@command{ns-3} @emph{global route manager} to walk the topology you created and 
build internetwork routing tables for all of the nodes in the simulation.
We changed the client application so that it runs on node four:

@verbatim
  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n4, "10.1.1.2", 
    port, 1, Seconds(1.), 1024);
@end verbatim

Now if you build and run @code{tutorial-star-routing.cc} you can examine the
@code{tutorial.tr} file and see that your UDP echo packets are now correctly
routed through the topology.

@section A Dumbbell Network
One of the most interesting simple topologies (from a phenomenological point of
view) is commonly called a dumbbell network.  The name derives from a 
superficial similarity in form to a piece of exercise equipment.

The dumbbell model is typically composed of two bus or star network elements
connected via a point-to-point link.  The point-to-point link is usually 
configured with a lower bandwidth than the bus elements to provide a 
@emph{choke point}.

The following is a representation of the topology.

@sp 1
@center @image{dumbbell,,,,png}

We have provided a file that constructs this dumbbell network and creates 
enough data flowing across the choke point that some packets will be dropped.
The file is called @code{tutorial-linear-dumbbell.cc} and is located in the 
@code{tutorial} directory.  We have already covered all of the code used to
create this network, so we will just quickly go over the main sections of the
script.

The first section creates a CSMA lan that will become the left side of the
dumbbell network.  This code should be very familiar since we used the same
process to create our first example.

@verbatim
//
// Create the lan on the left side of the dumbbell.
//
  Ptr<Node> n0 = CreateObject<InternetNode> ();
  Ptr<Node> n1 = CreateObject<InternetNode> ();
  Ptr<Node> n2 = CreateObject<InternetNode> ();
  Ptr<Node> n3 = CreateObject<InternetNode> ();

  Ptr<CsmaChannel> lan1 = 
    CsmaTopology::CreateCsmaChannel (DataRate (10000000), MilliSeconds (2));

  uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan1, 
    "08:00:2e:00:00:00");

  uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan1, 
    "08:00:2e:00:00:01");

  uint32_t nd2 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan1, 
    "08:00:2e:00:00:02");

  uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan1, 
    "08:00:2e:00:00:03");

  CsmaIpv4Topology::AddIpv4Address (n0, nd0, "10.1.1.1", "255.255.255.0");
  CsmaIpv4Topology::AddIpv4Address (n1, nd1, "10.1.1.2", "255.255.255.0");
  CsmaIpv4Topology::AddIpv4Address (n2, nd2, "10.1.1.3", "255.255.255.0");
  CsmaIpv4Topology::AddIpv4Address (n3, nd3, "10.1.1.4", "255.255.255.0");
@end verbatim

The code to generate the CSMA lan on the right side is similar; only the names
have been changed.
 
@verbatim
//
// Create the lan on the right side of the dumbbell.
//
  Ptr<Node> n4 = CreateObject<InternetNode> ();
  Ptr<Node> n5 = CreateObject<InternetNode> ();
  Ptr<Node> n6 = CreateObject<InternetNode> ();
  Ptr<Node> n7 = CreateObject<InternetNode> ();

  Ptr<CsmaChannel> lan2 = 
    CsmaTopology::CreateCsmaChannel (DataRate (10000000), MilliSeconds (2));

  uint32_t nd4 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n4, lan2, 
    "08:00:2e:00:00:04");

  uint32_t nd5 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n5, lan2, 
    "08:00:2e:00:00:05");

  uint32_t nd6 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n6, lan2, 
    "08:00:2e:00:00:06");

  uint32_t nd7 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n7, lan2, 
    "08:00:2e:00:00:07");

  CsmaIpv4Topology::AddIpv4Address (n4, nd4, "10.1.2.1", "255.255.255.0");
  CsmaIpv4Topology::AddIpv4Address (n5, nd5, "10.1.2.2", "255.255.255.0");
  CsmaIpv4Topology::AddIpv4Address (n6, nd6, "10.1.2.3", "255.255.255.0");
  CsmaIpv4Topology::AddIpv4Address (n7, nd7, "10.1.2.4", "255.255.255.0");
@end verbatim

Next, we create a point to point link to connect the two lans.  We connect
the point-to-point channel between nodes three (on the left lan) and four
(on the right lan).  You should recoginze this as substantially similar to
the link setup from the @code{point-to-point} example.

@verbatim
//
// Create the point-to-point link to connect the two lans.
//
  Ptr<PointToPointChannel> link = PointToPointTopology::AddPointToPointLink (
    n3, n4, DataRate (38400), MilliSeconds (20));

  PointToPointTopology::AddIpv4Addresses (link, n3, "10.1.3.1", 
    n4, "10.1.3.2");
@end verbatim

Then we configure data flows.  We create four echo clients that send UDP 
packets from the left side lan to servers created on the right side lan.
Notice that we send 100 packets with an inter-packet gap of ten milliseconds
instead of the single packet we have previously used.  This data rate is
sufficient to saturate the point-to-point link and will cause packets to be
dropped when the queue on the link net devices overflows (the default maximum
queue depth is 100 packets).  Note that we stagger the start of the echo 
clients to slowly bring up the data rates.

@verbatim
//
// Create data flows across the link:
//   n0 ==> n4 ==> n0
//   n1 ==> n5 ==> n1
//   n2 ==> n6 ==> n2
//   n3 ==> n7 ==> n3
//
  uint16_t port = 7;

  Ptr<UdpEchoClient> client0 = CreateObject<UdpEchoClient> (n0, "10.1.2.1", 
    port, 100, Seconds(.01), 1024);
  Ptr<UdpEchoClient> client1 = CreateObject<UdpEchoClient> (n1, "10.1.2.2", 
    port, 100, Seconds(.01), 1024);
  Ptr<UdpEchoClient> client2 = CreateObject<UdpEchoClient> (n2, "10.1.2.3", 
    port, 100, Seconds(.01), 1024);
  Ptr<UdpEchoClient> client3 = CreateObject<UdpEchoClient> (n3, "10.1.2.4", 
    port, 100, Seconds(.01), 1024);

  Ptr<UdpEchoServer> server4 = CreateObject<UdpEchoServer> (n4, port);
  Ptr<UdpEchoServer> server5 = CreateObject<UdpEchoServer> (n5, port);
  Ptr<UdpEchoServer> server6 = CreateObject<UdpEchoServer> (n6, port);
  Ptr<UdpEchoServer> server7 = CreateObject<UdpEchoServer> (n7, port);

  server4->Start(Seconds(1.));
  server5->Start(Seconds(1.));
  server6->Start(Seconds(1.));
  server7->Start(Seconds(1.));

  client0->Start(Seconds(2.));
  client1->Start(Seconds(2.1));
  client2->Start(Seconds(2.2));
  client3->Start(Seconds(2.3));

  server4->Stop (Seconds(10.));
  server5->Stop (Seconds(10.));
  server6->Stop (Seconds(10.));
  server7->Stop (Seconds(10.));

  client0->Stop (Seconds(10.));
  client1->Stop (Seconds(10.));
  client2->Stop (Seconds(10.));
  client3->Stop (Seconds(10.));
@end verbatim

The remainder of the file should be quite familiar to you.  Go ahead and 
run @code{tutorial-linear-dumbbell}.  Now take a look at the trace 
(@code{tutorial.tr}) file.  You will now see trace lines that begin with 
@code{d}.  Alternatively you can search for the string ``queue-drop'' which
is the expansion of the drop code ('d').

Interpretation of a dropped packet is straightforward.  We have expanded
the first @code{queue-drop} trace for you below.  See the section on ASCII 
tracing for details.

@verbatim
  00 d 
  01 2.40938 
  02 nodeid=3 
  03 device=1 
  04 queue-drop 
  05 pkt-uid=124 
  06 LLCSNAP(type 0x800) 
  07   IPV4(
  08     tos 0x0 
  09     ttl 63 
  10     id 20 
  11     offset 0 
  12     flags [none] 
  13     length: 1052) 10.1.1.3 > 10.1.2.3 
  14     UDP(length: 1032) 
  15       49153 > 7 
  16       DATA (length 1024)
@end verbatim

We leave it as an exercise to examine the trace files in more detail.

@c ========================================================================
@c Nonlinear Thinking
@c ========================================================================

@node Nonlinear-Thinking
@chapter Nonlinear Thinking

One thing that all of our examples so far have in common is that they are
composed of a linear collection of calls into the @command{ns-3} system.  The
programmers among the readers may have wondered why there is not as much
as a for-loop in all of the examples.  The answer is that we wanted to 
introduce you to @command{ns-3} scripting with a minimum of conceptual 
overhead.  We're going to remedy that situation shortly.

We have written a number of @command{ns-3} scripts in C++.  Although we have 
been perfectly linear in our script implementations, just like any other C++ 
program, an @command{ns-3} script can use any features of the language you
desire.  If you will look back at the @code{tutorial-linear-dumbbell.cc}
example, you may notice that the code to create the left and right sides of
the dumbbell is operationally identical --- only the names change.  An obvious
improvement of this program would be to use subroutines to create the sides.
Since we are working with C++, we should probably do this in an 
object-oriented way.  Since object-oriented design is somewhat of a black art
to some people, we'll take some time here and outline a simple methodology 
you can follow.

@section Object Design 101 --- Class Ipv4BusNetwork
If you are a master of object oriented design, feel free to skip or skim this
section, in which we derive a simplistic but fully operational bus network 
class.

So you want to create a BusNetwork class.  Often the biggest hurdle in a 
design is figuring out how to get started.  One of the simplest and most 
straightforward ways to do an object decomposition of a problem is to simply 
write down a description of the problem and take a look at the words 
you used.  Let's take some time and do that, first at a very high level.

@example
A bus network is an implementation of a particular network topology that
contains some number of nodes.  Each of these nodes is attached to a single 
multi-drop channel.  The network itself has some attributes independent of
the topology such as a network mask, network number (prefix) and base IP
address.
@end example

The first thing to do is to focus on the nouns and adjectives.  These will
give you a starting point for required classes and member variables.

Immediately we can notice that at the highest level we are talking about the
noun @emph{network}.  This probably won't surprise you.  We also have an 
adjective that modifies the noun --- @emph{bus}.  This should lead us to our 
first class defintion.  Usually class names are constructed in the same way
as an English language sentence would be spoken.  For example, one would speak
of a @emph{bus network} in conversation, so we would normally create a
@code{class BusNetwork} to represent it.  

One thing to note is that we have used two words in our description quite 
naturally: @emph{is} and @emph{has}.  When you see these words should should
immediately think of the object-oriented concepts of @emph{ISA} (inheritance)
and @emph{HASA} (containment) respectively.  We wrote that a bus network
@emph{is} an implementation of a particular network topology.  Perhaps you 
will agree that there is a natural base class called @code{Network} that 
@emph{has} the attributes discussed above.  The fact that a @code{BusNetwork}
@emph{ISA} kind of @code{Network} suggests inheritance.  Let's capture that 
thought right away remembering that we're focused on IP version four here:

@verbatim
  class Ipv4Network
  {
  public:
    Ipv4Address m_network;
    Ipv4Mask m_mask;
    Ipv4Address m_baseAddress;
  };

  class Ipv4BusNetwork : public Ipv4Network
  {
  };
@end verbatim

Let's take a look at the @emph{HASA} relationships of the bus network.  Clearly
it will @emph{have} a reference to the underlying channel that implements the
actual communications medium.  We use smart pointers for those references, so 
one member variable is obvious:

@verbatim
  Ptr<CsmaChannel> m_channel;
@end verbatim

A bus network will also need to contain references to all of the nodes we
eventually want to create.  If you are working in C++ and see the words contain
or container, you should immediately think of the Standard Template Library
or STL.  A quick search of the available containers there will probably lead
you to consider the vector class.  A vector is a container that looks like an
array.  This is just what we need here.  Again, we want to use smart pointers
to reference our nodes, so the declaration of the vector would look like,

@verbatim
  std::vector<Ptr<Node> > m_nodes;
@end verbatim

It will save you headaches in the future if you notice that the space between
the two right brackets is required to differentiate this situation from a
right-shift operator.  So we have a pretty good start already after just a
little work.  Now we need to turn our attention to actions.  Let's write 
another little description of the things you consider doing to a Bus network.

@example
We need to be able to create a bus network.  We need to be able to delete a
bus network.  We need to be able to get a handle to a node in order to add
applications.  We need to be able to set the network, mask and base address
somehow, specify how many nodes to create and provide the underlying channel
its required bandwidth and delay parameters.
@end example

We now look at the @emph{verbs} in that sentence.  These will give a good 
starting point for the methods of the classes.  For example, the verbs 
@emph{create} and @emph{delete} should suggest @emph{constructor} and 
@emph{destructor}.  The verb @emph{get} leads us to providing a method called
@code{GetNode}.  We have to provide a number of parameters so we can either
provide @emph{setters} or we can simply pass them in as parameters to our
constructors.  Since this is a simple example, we won't bother to implement
getters and setters (methods to get and set member variables to enhance data
hiding).  Let's use this guidance to finish up our class declarations:

@verbatim
  class Ipv4Network
  {
  public:
    Ipv4Network (Ipv4Address network, Ipv4Mask mask, Ipv4Address address);
    virtual ~Ipv4Network ();

    Ipv4Address m_network;
    Ipv4Mask m_mask;
    Ipv4Address m_baseAddress;
  };

  class Ipv4BusNetwork : public Ipv4Network
  {
  public:
    Ipv4BusNetwork (
      Ipv4Address   network, 
      Ipv4Mask      mask, 
      Ipv4Address   startAddress, 
      DataRate      bps, 
      Time          delay, 
      uint32_t      n);

    virtual ~Ipv4BusNetwork ();

    Ptr<Node> GetNode (uint32_t n);

  private:
    std::vector<Ptr<Node> > m_nodes;
    Ptr<CsmaChannel> m_channel;
  };
@end verbatim

That's it.  We have actually already walked through almost all of the code
required to construct a bus network in our @code{tutorial-csma-echo.cc} 
example, so let's just jump forward and take a look at an implementation
of this thing.  We provide an implementation for you in the files 
@code{ipv4-bus-network.h} and @code{ipv4-bus-network.cc} located in the
@code{tutorial} directory.  We also provide an example that uses the new
class in the file @code{tutorial-bus-network.cc}.

The interesting method from our current perspective is the Ipv4BusNetwork
constructor, shown below:

@verbatim
  Ipv4BusNetwork::Ipv4BusNetwork (
    Ipv4Address   network, 
    Ipv4Mask      mask, 
    Ipv4Address   baseAddress, 
    DataRate      bps, 
    Time          delay, 
    uint32_t      n)
  : 
    Ipv4Network (network, mask, baseAddress)
  {
    Ipv4AddressGenerator::SeedNetwork (mask, network);
    Ipv4AddressGenerator::SeedAddress (mask, baseAddress);
  
    m_channel = CsmaTopology::CreateCsmaChannel (bps, delay);
  
    for (uint32_t i = 0; i < n; ++i)
      {
        Ptr<Node> node = CreateObject<InternetNode> ();
        uint32_t nd = CsmaIpv4Topology::AddIpv4CsmaNetDevice (node, m_channel, 
          Mac48Address::Allocate ());
        Ipv4Address address = Ipv4AddressGenerator::AllocateAddress (mask, 
          network);
        CsmaIpv4Topology::AddIpv4Address (node, nd, address, mask);
        m_nodes.push_back (node);
      }
  }
@end verbatim

Notice that we do the simple and straightforward thing and pass all of our
parameters to the constructor.  For those unfamiliar with C++, the line after
the colon and before the opening brace (shown below),

@verbatim
  : 
    Ipv4Network (network, mask, baseAddress)
  {
@end verbatim

Passes the appropriate parameters to the constructor of the base class
@code{Ipv4Network}.  There are two new calls that we haven't seen immediately
after this initialization.  They are:

@verbatim
    Ipv4AddressGenerator::SeedNetwork (mask, network);
    Ipv4AddressGenerator::SeedAddress (mask, baseAddress);
@end verbatim

We provide an IP address generator class to allow us to programatically 
allocate IP addresses.  The first call to @code{SeedNetwork} gives the
address generator a starting network number to use when generating addresses.
The second call to @code{SeedAddress} gives the address generator a starting
IP address to use.  There is a starting network and starting address for each
of the 32 possible network masks.  Later in the for loop, you will see a
call to @code{AllocateAddress} in which the IP address for each node created
in the loop is actually generated.  

The only unfamiliar call in the reset of the constructor will be:

@verbatim
  m_nodes.push_back (node);
@end verbatim

This is the STL code to add the newly created node to the vector of nodes
attached to the bus.  

For your convenience, we reproduce the entire bus network implementation below:

@verbatim
  /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
  /*
   * Copyright (c) 2007 University of Washington
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation;
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
  #include "ns3/mac48-address.h"
  #include "ns3/csma-net-device.h"
  #include "ns3/csma-topology.h"
  #include "ns3/csma-ipv4-topology.h"
  
  #include "ipv4-bus-network.h"
  #include "ipv4-address-generator.h"
  
  namespace ns3 {
  
  Ipv4Network::Ipv4Network (
    Ipv4Address   network, 
    Ipv4Mask      mask, 
    Ipv4Address   address)
  : 
    m_network (network), m_mask (mask), m_baseAddress (address)
  {
  }
  
  Ipv4Network::~Ipv4Network ()
  {
  }
  
  Ipv4BusNetwork::Ipv4BusNetwork (
    Ipv4Address   network, 
    Ipv4Mask      mask, 
    Ipv4Address   baseAddress, 
    DataRate      bps, 
    Time          delay, 
    uint32_t      n)
  : 
    Ipv4Network (network, mask, baseAddress)
  {
    Ipv4AddressGenerator::SeedNetwork (mask, network);
    Ipv4AddressGenerator::SeedAddress (mask, baseAddress);
  
    m_channel = CsmaTopology::CreateCsmaChannel (bps, delay);
  
    for (uint32_t i = 0; i < n; ++i)
      {
        Ptr<Node> node = CreateObject<InternetNode> ();
        uint32_t nd = CsmaIpv4Topology::AddIpv4CsmaNetDevice (node, m_channel, 
          Mac48Address::Allocate ());
        Ipv4Address address = Ipv4AddressGenerator::AllocateAddress (mask, 
          network);
        CsmaIpv4Topology::AddIpv4Address (node, nd, address, mask);
        m_nodes.push_back (node);
      }
  }
  
  Ipv4BusNetwork::~Ipv4BusNetwork ()
  {
  }
  
    Ptr<Node>
  Ipv4BusNetwork::GetNode (uint32_t n)
  {
    return m_nodes[n];
  }
  
  }; // namespace ns3
@end verbatim

@section Using Ipv4BusNetwork
If all you ever want to do with a bus network can be captured in a topology
with four nodes on the bus, the preceeding section may seem like a colossal
waste of time.  This is probably not the case, though.  Now that we have a
relatively abstract bus class, we can create bus networks with 4, 40 or 4000
nodes with no additional effort.

A use of the bus network class is shown in the file 
@code{bus-netowrk.cc} located in the @code{tutorial} directory.  The
interesting code is,

@verbatim
  Ipv4BusNetwork bus ("10.1.0.0", "255.255.0.0", "0.0.0.3",
    DataRate(10000000), MilliSeconds(20), 10);
@end verbatim

Here we create a bus network with the network number ``10.1.0.0'' and the 
network mask ``255.255.0.0'' that completes the IP network definition.  You 
can consider these together as ``10.1.0.0/16'' if you prefer.  The next 
parameter tells the bus to start numbering IP addresses of contained nodes at
``10.1.0.3'' (remember the network number will be combined).  We provided a
data rate of 10 megabits per second and a latency of 20 milliseconds.  
Finally, we ask the @code{Ipv4BusNetwork} object to create ten nodes in the
network.

If you are feeling brave, go ahead and change the number of nodes to be 100,
1000, 10,000 or more to generate larger and larger networks.  Before you go 
too far, remember that a trace file will be generated when you run your 
resulting program and ee asked the trace facility to trace all net device 
receive events.  This will include the reception of the broadcast ARP request 
by all of the nodes in the simulation, so this can add up quickly.

@c ========================================================================
@c Summary
@c ========================================================================

@node Summary
@chapter Summary

This concludes the first part of the tutorial.  We have focused on
using the @command{ns-3} system to construct various network topologies and to
simulate sendng data across the networks; and we've shown you how to use the 
trace facility to get access to simulation results.

We now encourage you to play with the system a little.  Experiment with what
we have provided.  Build a hierarchical network simulation.  Perhaps exercise
your object design skills and create a new @code{Ipv4DumbbellNetwork} class 
to create dumbbell networks using the Ipv4BusNetwork class we just created.
Hint:  An Ipv4DumbbellNetwork @emph{has} two @code{Ipv4BusNetwork} objects; 
a left side and a right side.

In the next part of the tutorial we are going to drop down a level and begin
examining the lower levels of the system in more detail.  We are going to
explain how to change the behavior of the system and eventually how to write
new models and applications.  This is a good time to make sure that you
thorougly understand what we've gone over so far.

@c ========================================================================
@c Object Model
@c ========================================================================

@node Object-Model
@chapter Object Model

@cindex Object Model
There are two distinctly different meanings associated with the term Object
Model.  The first speaks to the implementation of an object system --- a system
view; and the second speaks to the application programming interface (classes
or objects) one uses to access some service or system --- an application view.

As an example of the system view sense of the term, the C++ language has an
associated object model that describes how objects are laid out in memory,
how virtual functions work, how inheritance is implemented, constructor and
destructor execution ordering, template instantiation, etc.

@cindex API
@cindex DOM
@cindex Document Object Model
In the case of the application view, the Document Object Model is a good
example.  In the words of W3C, the Document Object Model (DOM) is an
application programming interface (API) for HTML and XML documents. It defines
the logical structure of documents and the way a document is accessed and
manipulated.

@cindex API
@cindex COM
@cindex Component Object Model
The Component Object Model (COM) from Microsoft actually spans both meanings
of the term and extends further into policy statements.  From a system
perspective, COM specifies an interface definition language, the layout of
objects virtual function tables, the formats of Globally Unique Identifiers
and also specifies lifetime management mechanisms for objects via reference
counting.  From the point of view of the API, COM specifies a number of
Interfaces as well as functions such as CoCreateInstance and various
threading models.  The COM specification extends to policy by disallowing
implementation inheritance.

@cindex Feynman
The @command{ns-3} object model takes the C++ language (system level) object 
model as its basis, and extends that model by providing an API for software
componentry.  You may find terms like Component, Interface and QueryInterface
in the following discussion, or used informally in other discussions about 
@command{ns-3}.  It is important to understand from the outset that this is
the @command{ns-3} object model, and not any other object model.
Richard Feynman (an American physicist) once described the behavior of matter 
and light on a very small scale in the following way,

@quotation
``They do not behave like waves, they do not behave like particles, they do
not behave like clouds, or billiard balls, or weights on springs, or like
anything that you have ever seen.''
@end quotation

Just as students of quantum mechanics must rid themselves of preconceptions
regarding the behavior of matter at small scales, you should rid yourself of
any preconceptions you may have about components, interfaces and APIs for
software componentry before continuing.  To paraphrase Feynman, @command{ns-3}
components do not behave like COM Components, or Java Beans, or CORBA
objects, or clouds or weights on springs, or like anything that you have 
ever seen --- they are @command{ns-3} components.

@section The C++ Object Model is the Root of all Things
@command{Ns-3} is primarily a C++ system.  The system is written in C++ and
one can use standard C++ mechanisms for creating and using ns-3 objects.  We 
do not change this at all, nor do we make any pronouncements about the 
superiority of one mechanism or another.  What we will do is provide 
convenience functions that we think will make creating and managing simulation
objects easier.
  
@cindex CreateObject
Previously, you have seen objects created using the template function 
@code{CreateObject} as in the following example:

@verbatim
  Ptr<Node> n0 = CreateObject<InternetNode> ();
@end verbatim

This line of code, while it may be unfamiliar to some, is pure C++.  If you
were to look in the header file ptr.h, you would find the following definition
of the @code{CreateObject} template.

@verbatim
  template <typename T>
  Ptr<T> CreateObject (void)
  {
    Ptr<T> p = Ptr<T> (new T (), false);
    p->SetTypeId (T::GetTypeId ());
    return p;
  }
@end verbatim

@cindex template
As you can see, this template creates objects of type @code{T} using the
operator @code{new}.  Its a little harder to find the corresponding delete ---
it's in the file @code{object.cc} inside the method @code{Object::MaybeDelete},
but when that @code{Ptr} which you see above goes out of scope it will call
@code{Unref} and ultimately the C++ @code{delete} operator will be called.

@cindex new
@cindex delete
The ns-3 system uses the C++ @code{new} and @code{delete} operators, so there
is really no reason that you as a user of the ns-3 system are forbidden from
using these or any other C++ mechanism.  If you so desire, you can take on
the responsibility for managing object lifetime (i.e., do not use the 
@code{Ptr} smart pointer), work directly with the @code{new} and @code{delete}
operators and call methods like any C++ object as in the following example:

@verbatim
  MyClass *obj = new MyClass ();
  obj->Method();
  delete obj;
@end verbatim

@cindex model
You, as a competent model author, are encouraged to use whatever methods you
think are appropriate in your private code.  Remember, however, that the
public ns-3 APIs do use smart pointers to pass objects around in an effort to
reduce the burden of object lifetime management.  If you do intend to export
an API publicly, you should use the same object lifetime management approaches
as those found in the ns-3 public API if only for consistency.

These APIs are there for convenience and consistency, but do not change the
fact that in ns-3 all of the objects are really just C++ objects, ultimately
created using the C++ new operator with C++ constructor semantics and are
ultimately deleted using the C++ delete operator, following C++ destructor
semantics.  Although it may sometimes appear so, there is really no system-
level magic going on in ns-3.  Ns-3 components and interfaces are C++ objects
just like any other object and our object model is simply a collection of APIs
built on the normal C++ object model.

@cindex Interface
@cindex Abstract Data Type
@cindex ADT
@cindex Abstract Base Class
@cindex ABC
@section Interface
There are many different ideas floating around of what exactly the term
@emph{interface} means.  Originally an interface just meant a communication
boundary between two entities.  As the concepts of object oriented programming
(OOP) were surfacing in the 1980s, the term interface was applied to the
collection of access methods for the modular entities that were being defined.

@cindex OOP
@cindex Object Oriented Programming
Two distinct approaches developed regarding specifying access mechanisms for
objects.  The OOP purists were very concerned about object reuse and were led
to Abstract Data Types (ADT).  These were eventually implemented in the case
of C++, as pure virtual methods in Abstract Base Classes (ABC).  Another group
of folks was more interested in simply specifying object access methods in one
place and using inheritance as the primary reuse mechanism.

Bjarne Stroustroup, the creator of C++, embraced both approaches.  He makes
the following interesting observation:

@quotation
``Many classes [@dots{}] are useful both as themselves and also as bases for
derived classes. [@dots{}] Some classes, such as class @strong{Shape},
represent abstract concepts for which objects cannot exist.''
@end quotation

@cindex PIMPL
@command{Ns-3} does not pick and enforce a particular approach.  In 
@command{ns-3} an interface is determined completely by a class declaration
just as any C++ object interface is declared.  If you think of an object as
an abstract concept that should be implemented by derived classes, by all
means, use the Abstract Base Class approach to interface declaration.  If you
think that an object should be completely concrete and you foresee no need
to ever modify its behavior, feel free to avoid declaring any methods virtual.
If you think that an object could be useful as a base class, feel free to
declare its methods virtual.  If you like to use the PIMPL idiom, again, feel
free.  If you want to use any combination of these techniques, feel free.  
We make no restrictions.

@cindex API
When we speak of an ns-3 interface, we do not worry about interface definition
languages, or pure virtual classes, or registries  we just think about C++
object declarations and their associated methods.  We tend to think of 
interfaces to objects as simply a private or public API.  When we instantiate
an @command{ns-3} interface, it is the C++ object model that dictates how that
object is brought into existence.  When a method is called on an @command{ns-3}
Interface, it is the C++ object model that dictates how that method is 
dispatched.

We do, however, provide a base class that endows vanilla C++ objects with 
capabilities that can be seen as conceptually similar to those provided by
Microsoft Component Model @emph{Interfaces}.

@section The Ns-3 Object and GetObject
@cindex Component Object Model
One thing that Microsoft arguably got right in the Component Object Model was
the idea of Interface aggregation and discovery via QueryInterface.  We have 
embraced these ideas in @command{ns-3}.  This was done primarily to address a 
common problem in large software systems.  A good example of this problem 
happens in the @command{ns-3} Node class.

@cindex OOP
@cindex weak base class
@cindex base class bloat
@cindex Swiss Army Knife class
@cindex Node
If one were to take the standard OOP view of specializing a @code{Node} into
an internet host, for example, one would typically inherit from the @code{Node}
base class and include functionality to implement such things as internet
routing and a TCP/IP protocol stack.  Other types of @code{Node}s might 
inherit from the node class and specialize in different ways, or further
specialize the internet host class, treating it as a base class.  This can
result in a complicated inheritance tree in which some specializations are
simply not available to other branches of the tree which can make reuse
difficult or impossible.  This is known as the @emph{weak base class} problem
and creates pressure to drive functionality up the inheritance tree into the
base classes.  This, in turn, results in @emph{base class bloat} and the 
resulting @emph{swiss army knife} base classes which end up trying to do
everything in one place.

Even if one successfully avoided these swiss army knife base classes, one
would also want to be able to treat new specializations of @code{Node}
generically in the system.  This means one would pass references to the base
class (@code{Node}) across public APIs.  This introduces @emph{upcasts} prior
to passing across public APIs and corresponding @emph{downcasts} on the other
side in order to gain access to required specialized functions.  As the
inheritance tree becomes more complicated, this approach can cause another
related problem known as the @emph{fragile base class} problem.  This happens
when changes to the base class cause unexpected problems in the various and 
sundry subclasses.  

These effects seem always to result in a positive feedback loop driving
everything into the base class and destroying much of the encapsulation which
is a hallmark of the object oriented approach.

@subsection Interface Composition
@cindex Node
There is a completely different way to address the Node specialization
problem.  Instead of approaching the situation using inheritance, one can
look at the problem as one of composition.  We can look at the @code{Node}
class as a container of sorts that holds other objects.  In this case, the
objects would be instances of the classes implementing the internetwork
routing code, or the TCP/IP protocol stack described above.  This approach
preserves the encapsulation and solves the weak base class, base class bloat
and fragile base class problems; but the question of method dispatch 
immediately comes to mind.

@cindex delegation
In many systems, @emph{delegation} is used.  The base class, @code{Node},
in this approach would provide methods that simply forward to the objects
implementing the desired functionality.  This situation clearly does not
address the base class bloat problem since dispatch methods must be added
to the base class.  The situation is mitigated somewhat by pushing the
implementation of the dispatch methods to contained objects, but the
fundamental problems are still present.  What is really needed is a way
to compose objects but at the same time keep the interfaces to those
objects separated.

@cindex aggregation
Composition, usually called @emph{aggregation}, along with runtime Interface
discovery is the solution that Microsoft originally championed and that 
@command{ns-3} has adopted --- albeit with many simplifications and a few name
changes.

@subsection Objects and Interfaces
@cindex COM
@cindex QueryInterface
Now that we have mentioned Microsoft COM and are almost obligated to mention 
the terms Interface and QueryInterface.  For those familiar with COM, loosely
speaking, QueryInterface is to COM as GetObject is to @command{ns-3}.
The analogy, while good conceptually, is superficial from an implementation 
point of view.

@cindex Node
Addressing our current example of a @code{Node}, generically speaking, each
node needs to aggregate an object that will implement internetwork routing 
and TCP/IP.  The system will need to provide a mechanism for locating the
aggregated objects and allow a client to discover them.  

@cindex aggregation
@cindex Object
These aggregated objects have interfaces in the C++ sense of collections of
method signatures.  In @command{ns-3}, when objects are capable of 
participating in this aggregation process, they are called @command{ns-3} 
@code{Objects}.  @code{Objects} receive the functionality required for this
 participation by inheriting from the @command{ns-3} base class @code{Object}.

Note well that when we write the word @code{Object} (note the uppercase 'O' in
the spelling and the change of font) we are referring to a kind of C++ object
that has inherited the capability of participating in an aggregation.  The 
@command{ns-3}-specific word @code{Object} can have a significantly different
meaning than that of a vanilla C++ object outside the aforementioned 
inheritance tree, and the difference is only readily apparent via context.
In this tutorial we will always write the @command{ns-3}-specific kind of 
@code{Object} in a fixed font; and will write the vanilla C++ term object in
normal font.  In conversation, you will need to be careful to understand which
term is meant:  object or @code{Object}.

Once an object has inherited from class @code{Object} it has the ability to
@emph{host} an aggregation.  This means that it has the ability to add other
@code{Objects} to its aggregation via the method @code{AggregateObject}.  It
also means that it can provide a service to @emph{discover} other objects in
its aggregation via the method @code{GetObject}.

@cindex base class
Technically, the class named @code{Object} is simply a base class that you
will inherit from if you want your @code{Objects} to support aggregation and
discovery.  Many systems have a base class that implements common 
functionality and these base classes are typically called somthing like 
Object.  The @command{ns-3} version of this base class relates primarily to
@code{Object} aggregation and discovery, although it does also provide methods
to help with intrusive reference counting and tracing as well.

When a C++ object inherits from the ns-3 Object base class, it is conceptually
promoted to an ns-3 @code{Object} irrespective of how the object was declared
(e.g., as an abstract base class, concrete class, with virtual methods, etc.).
In ns-3, you should associate inheritance from the class named @code{Object}
with promotion of an object to the status of some locatable @code{Object}
rather than with the form of the class declaration.

@cindex COM
@cindex CORBA
@cindex ORBit
For those of you unfamiliar with Microsoft COM, CORBA or ORBit, this might 
sound obvious.  For those of with such a background, the point we are making 
is that there is no such thing in @command{ns-3} as a separate Interface
declaration, no such thing as an Interface Definiition Language, no such thing
as a UUID or GUID, etc.  In @command{ns-3} we just work with C++ objects that
may be given some very useful abilities by inheriting from the @command{ns-3}
base class @code{Object}.  @command{Ns-3} @code{Objects} are not required to
inherit from classes composed of pure virtual methods in order to define an
Interface.  It's all really just ``plain old C++.''

To summarize, when you instantiate an object that inherits from the 
@code{Object} class, you will have a C++ object that has four important 
properties:  

@cindex AggregateObject
@cindex GetObject
@itemize @bullet
@item The @code{Object} has a C++ interface defined by the collection of method signatures in its inheritance tree; 
@item The @code{Object} has some way to identify its underlying class uniquely;
@item The @code{Object} is a kind of container that has the ability to aggregate other @code{Objects} using the method @code{AggregateObject};
@item The @code{Object} exports a method called @code{GetObject} that allows for discovery of other aggregated @code{Objects}.
@end itemize

@cindex base class
@cindex Object
It is crucially important to understand what we have described here
(especially for those coming from other systems that provide similar 
functionality).  A given C++ class has an object access interface that is
essentially the collection of method signatures specified in its inheritance
tree.  This is a C++ object model thing.  Ns-3 provides a base class from 
which the class in question can inherit and be promoted to the status of
@code{Object}.  Once a class becomes an @code{Object} it has inherited the
ability to aggregate and search for other @code{Objects} that are added to
its aggregation.

That last detail is important.  In @command{ns-3} @code{Objects} are both
containers and specifications for a object method access.  We have previously
mentioned that the @code{Node} class acts as a container.  In fact, the 
@code{Node} class inherits from @code{Object} and is itself an @command{ns-3} 
@code{Object}.  So, when the @code{Node} object is created it is really an 
aggregation of one @code{Object} and you can call @code{AggregateObject} or
@code{GetObject} on the resulting @code{Node} object.  Along with being an
aggregation, the @code{Node} class also describes a public interface.  THis
public interface (API) is declared just as any C++ object is declared, via its
class methods as specified in the inheritance tree.  For those steeped in 
COM or CORBA, this is where the concept of Interface works in @command{ns-3}.
Remember that it is generally true that @code{Objects} are both aggregations
and APIs.

@subsection Aggregations
@cindex aggregate
The figure below shows how an @code{Object} could be illustrated in detail.
The line with the circle at the top of the diagram represents the appearance 
of the @code{Object} API to the external world.  This circle and line are 
together called a lollipop because of its superficial similarity to a kind of
childs candy.  

@sp 1
@center @image{oneobj,,,,png}

@cindex API
You could declare this API and associated @code{Object} quite simply using a
non-virtual class as follows,

@verbatim
  class A : public Object {
  public:
    static ns3::TypeId GetTypeId (void)
    {
      static ns3::TypeId tid = ns3::TypeId ("A")
        .SetParent (Object::GetTypeId ())
        .AddConstructor<A> ();
      return tid;
    }

    A () 
    {
    }

    void MethodA (void);
  };
@end verbatim

The methods that are then available via the API labeled @code{A} in the
figure above are the methods inherited from the @code{Object} base class 
(@code{GetObject}, @code{Ref}, and @code{Unref}) and those from class 
@code{A} (@code{MethodA}).

Note that you must declare a @code{TypeId} in your @code{Object} class, and
it must be declared static to make it class-wide in scope.  This @code{TypeId}
is a unifying element in the @command{ns-3} object model and uniquely
identifies @code{Objects} at run-time as being instantiated from a particular
class.  We'll have much more to say about @code{TypiId} shortly.

You can think of the arc and arrow device coming off each side of the 
illustrated @code{Objects} as part of a connector.  These connectors allow 
@code{GetObject} to search aggregations for an instance of a class type.
The figure below shows an aggregation of three @code{Objects}: A, B and C.
The class declarations for classes @code{B} and @code{C} are substantially 
similar to that of class @code{A}.

@sp 1
@center @image{threeobj,,,,png}

You can visualize these @code{Objects} as being snapped together like Lego
building blocks if you like.  When @code{Objects} are aggregated, a
@code{GetObject} search path is formed through the connectors.  In order
to create this aggregation you will first need to create the @code{Objects}.
These are just normal, everyday C++ objects that we can create using the
@code{CreateObject} template function and manage using smart pointers.  The 
following code should be obvious to you by now:

@verbatim
  Ptr<A> a = CreateObject<A> ();
  Ptr<B> b = CreateObject<B> ();
  Ptr<C> c = CreateObject<C> ();
@end verbatim

@cindex aggregation
When you create an aggregation, you pick one of the @code{Objects} of the
aggregation to think of as the container.  In this case well pick @code{Object}
A.  In order to aggregate an @code{Object}, you simply call the method
@code{AggregateObject} that your class has inherited from class @code{Object}.
The following code will aggregate @code{Object B} and @code{Object C} onto
the @code{Object} (and container/aggregation) @code{A}.

@cindex AggregateObject
@cindex GetObject
@cindex Object
@verbatim
  a->AggregateObject (b);
  a->AggregateObject (c);
@end verbatim

Thats all there is to it.  Now that you have those connectors snapped
together, you can ask each of the @code{Objects} in the aggregation for any of
the other @code{Objects} in the aggregation.  Lets look at a simple example:

@verbatim
  Ptr<B> newB = a->GetObject<B> ();
@end verbatim

Now, the explanation of what this snippet does is not as simple as writing it.
The left hand side of this assignment declares a smart pointer to the class 
@code{B} to help with memory management of the returned @code{Object} pointer.
You should be very familiar with smart pointers at this stage of the tutorial.

The right hand side illustrates how @code{GetObject} is acutally used.  
The method @code{GetObject} is templated.  The assocated template parameter 
(between the brackets) specifies the @emph{class} that is being requested.
This is important.  Since it is the class type that specifies the search
criteron, there can be only one instance of a particular class present in an
aggregation.  Looking back a little, although the parameter to
@code{AggregateObject} appears to be a vanilla C++ object (@code{b} or @code{c}
above), it actually represents (is an instance of) a class that has an
associated @code{TypeId} and inherits from @code{Object}.  When you call
@code{GetObject} you specify the search criterion (using the template 
parameter) as a class name.  This referenced class must also have an
associated @code{TypeId} and must also have inherited from @code{Object}.

This may be summarized by saying that @code{AggregateObject} takes an
@emph{instance} of an object of a particular class that inherits from 
@code{Object}. GetObject looks for a @emph{class} of a particular type
(that again inherits from @code{Object}) and possibly returns an aggregated
object instance of that type.

Now that you have those conceptual connectors snapped together, you can ask 
each of the @code{Objects} in the aggregation for any of the @code{Objects}
in the aggregation.  For example we could walk the @code{Objects} asking each
for the next in the aggregation.  First we would ask the @code{Object} pointed
to by the smart pointer @code{a} to look for the @code{Object} @code{class B}:

@verbatim
  Ptr<B> newB = a->GetObject<B> ();
@end verbatim

Next, we can ask the @code{Object} pointed to by the smart pointer @code{newB}
to look for the @code{Object} representing @code{class C}:

@verbatim
  Ptr<C> newC = newB->GetObject<C> ();
@end verbatim

@cindex Object
Then, we can ask the @code{Object} pointed to by the smart pointer @code{newC}
to look for the @code{Object} representing @code{class A} and complete our
circuit of the aggregation:

@verbatim
  Ptr<A> newA = newC->GetObject<A> ();
@end verbatim

@cindex GetObject
@code{GetObject} has some important properties that we need to go over.
Technically, @code{GetObject} is a @emph{symmetric}, @emph{reflexive} and 
@emph{transitive} operation with respect to the set of aggregated 
@code{Objects}.

@subsubsection Symmetry
@cindex symmetry
The symmetric nature of @code{GetObject} guarantees that if one performs a 
@code{GetObject} on a given @code{Object} for the class of that same
@code{Object}, that @code{GetObject} must succeed.  In other words, the
fact that you accessed the aggregation via an instance of an @code{Object A}
in the aggregation implies the reachability of that @code{Object} in the
aggregation.  This is usually written (by Microsoft) as,

@center must succeed (A >> A)

We can illustrate this property with the code snippet,

@verbatim
  Ptr<A> symmetricA = a->GetObject<A> ();
  NS_ASSERT (symmetricA);
@end verbatim

Here we take as given an interface (smart) pointer --- named @code{a} --- on
which we perform a @code{GetObject} looking for the class that represents that
same @code{Object}.  This call must always succeed and a smart pointer to the
aggregated instance of that class is returned.

@subsubsection Reflexivity
@cindex reflexivity
Calls to @code{GetObject} must also be reflexive.  This means that if you
successfully @code{GetObject} for @code{Object B} from @code{Object A}, then
you must always be able to @code{GetObject} for @code{A} from @code{B}.  This
is usually written as,

@center must succeed (A >> B, then B >> A)

This property can be illustrated with the code snippet,

@verbatim
  Ptr<B> b = a->GetObject<B> ();
  Ptr<A> reflexiveA = b->GetObject<A> ();
  NS_ASSERT (reflexiveA);
@end verbatim

If the first @code{GetObject} on @code{Object A} looking for @code{Object B} 
succeeds, then a @code{GetObject} on @code{Object B} looking @code{Object A} 
must succeed.

@subsubsection Transitivity
@cindex transitivity
@code{GetObject} must also be transitive.  This means that if one can
find @code{Object B} from @code{Object A}, and @code{Object C} from
@code{Object B}, then one must also be able to find @code{Object C} from
@code{Object A}.  This is usually written as,

@center must succeed (A >> B, and B >> C, then A >> C)

This property can be illustrated with the code snippet,

@verbatim
  Ptr<B> b = a->GetObject<B> ();
  Ptr<C> c = b->GetObject<C> ();
  Ptr<C> transitiveC = a->GetObject<C> ();
  NS_ASSERT (transitiveC);
@end verbatim

If you can get to @code{Object B} from @code{Object A}, and you can get to
@code{Object C} from @code{Object B}, then a @code{GetObject} on
@code{Object A} looking for @code{Object C} must also succeed.

@subsection Creating the TypeId
@cindex TypeId
@cindex GetTypeId
The final piece of this puzzle is the @code{TypeId}.  Recall that the
declaration our eample object above included the following code

@verbatim
  static ns3::TypeId GetTypeId (void)
  {
    static ns3::TypeId tid = ns3::TypeId ("A")
      .SetParent (Object::GetTypeId ())
      .AddConstructor<A> ();
    return tid;
  }
@end verbatim

This is the bit of code that ties this all together.  For those unfamiliar
with the idioms involved, this declaration can be rather dense.  First, let's
examine the function declaration itself.  The following code,

@verbatim
  static ns3::TypeId GetTypeId (void) ...
@end verbatim

declares a function that will be associated with all of the instances of the
given class.  This is a function, not a method, in that it can be accessed 
without a @emph{this} pointer; but it is associated with the class in a 
namespace sense.  The use of this kind of declaration allows one to write,

@verbatim
  return A::GetTypeId (void);
@end verbatim

if the @code{TypeId} is needed for our @code{class A}.  More generically the
class name can be substituted in a template, as is done deep in the 
@command{ns-3} object system. 

From this perspective, if you leave out the middle of the function definition,
the boundaries should make sense to you.

@verbatim
  static ns3::TypeId GetTypeId (void)
  {
    return tid;
  }
@end verbatim

@cindex function-local variable
You are obviously looking at a global function associated with your class
that simply returns a @code{TypeId}.  Now, what about the rest.  The code

@verbatim
    static ns3::TypeId tid = ns3::TypeId ("A")
      .SetParent (Object::GetTypeId ())
      .AddConstructor<A> ();
@end verbatim

when found inside the function declaration is called a function-local variable
with associated initialization.  It'll be easier to pick this statement apart
piece by piece as well.  The first line,

@verbatim
    static ns3::TypeId tid = ...
@end verbatim

is the declaration of the function-local variable tid.  This is essentially 
an initialized global variable, the scope of which has been reduced to within
the enclosing method.  You can think of this as a kind of global variable
that can only be accessed right there where it is created.  If the variable
is initialized, this amounts to the same behavior as if a global static 
initializer was declared in a namespace of the same name as your class.  
Global static initializers are guaranteed by the C++ language definition to
be executed before your main procedure is entered.  So are function-local
variables.

The variable that is being initialized is of type @code{ns3::TypeId}, is 
named @code{A::tid} since it is inside the class declaration for 
@code{class A}, and is initialized by a call to the constructor for the class
@code{TypeId}.  The constructor for @code{TypeId} takes a @code{std::string}
that can be used to locate the type information for your class.  We usually
privide the class name as the string.

Hopefully, this much of the declaration is now clear:

@verbatim
  static ns3::TypeId GetTypeId (void)
  {
    static ns3::TypeId tid = ns3::TypeId ("A")
    ...
    return tid;
  }
@end verbatim

All that is left now are the lines including @code{SetParent} and
@code{AddConstructor}.

@verbatim
  static ns3::TypeId tid = ns3::TypeId ("A")
    .SetParent (Object::GetTypeId ())
    .AddConstructor<A> ();
@end verbatim

The last bit may seem quite odd at first glance, but don't let the way the
code is broken up over several lines throw you.  If you saw something like,

@verbatim
  pointer->TypeId()->SetParent()->AddConstructor();
@end verbatim

you probably wouldn't hesitate at all.  Clearly, you would think, a method
called @code{TypeId} is called using the pointer called @code{pointer} as 
shown below.

@verbatim
  pointer->TypeId()
@end verbatim

The method @code{TypeId} must further return a pointer to an object that has
a method called @code{SetParent}.  Just as clearly, @code{SetParent} must
return a pointer to an object that has a method called @code{AddConstructor}.
The same sort of thing is happening in our code snipped, except we are using
references instead of pointers.  Perhaps if we rearrange this code to live on
one line it will be clearer.

@verbatim
  ns3::TypeId ("A").SetParent (Object::GetTypeId ()).AddConstructor<A> ();
@end verbatim

It's just a string of method calls.  The remaining question is then, what do
those three methods do.

The first, @code{ns3::TypeId ("A")}, simply allocates a new type in the system
and allows you to refer to it in the future by a string.  We have mentioned
inheritance trees often in the previous discussion.  The second method,
@code{SetParent} associates the class being defined with its parents in the
tree.  Finally, the @code{AddConstructor} method allows you to specify a 
constructor to be used when an instance of your class is created using
@code{CreateObject}.  

@verbatim
  AddConstructor<A> ();
@end verbatim

You can interpret this as explaining to the @command{ns-3} object ssytem that
you have a constructor named @code{A::A} which takes no parameters.  You are
saying that this constructor should be used when @code{CreateObject} is called
with no parameters.

By including the structure of the inheritance tree, in @command{ns-3} we can
use implementation inheritance to easily create new @code{Objects}.  You are
prevented from doing so in Microsoft COM, but this was almost universally
identified as a problem.

So, looking at the entire @code{GetTypeId} declaration again,

@verbatim
  static ns3::TypeId GetTypeId (void)
  {
    static ns3::TypeId tid = ns3::TypeId ("A")
      .SetParent (Object::GetTypeId ())
      .AddConstructor<A> ();
    return tid;
  }
@end verbatim

it should be clear what is happening.

@subsection A Very Real Example
@cindex Node
@cindex AggregateObject
@cindex GetObject
@cindex Object
At this point you may be asking yourself what the point of all of this is,
since you already had those pointers laying around when you created the
objects.  The typical case is that one will create and aggregate some number
of @code{Objects} in a constructor and return only a pointer to a single
@code{Object} as in our canonical example with @code{class Node}.  In this
case, the @code{Node} would be created and the @code{Node} constructor might
create and call @code{AggregateObject} to aggregate the @code{Objects} for
internetwork routing and TCP/IP.  From an external point of view, these 
aggregated objects may be discovered at run-time using @code{GetObject}.

Generally one tends to think of one of the @code{Objects} in the aggregation
as being the container and other @code{Objects} being aggregated to that
container.  In the case of a Node, for example, it is quite natural to think
of the Node as being the container which contains protocol stacks, internet
routing, etc.  So, lets start thinking about a real example by calling the 
container @code{Object Node} instead of @code{A} as we have been.  The 
creation of this @code{Object} is found all over our example programs.  For 
example, you will find code like the following in 
@code{samples/simple-point-to-point.cc}:

@verbatim
  Ptr<Node> n = CreateObject<InternetNode> ();
@end verbatim

It may appear obvious to you now that the @code{InternetNode} class name
provided to the template function @code{CreateObject} means that 
@code{InternetNode} is an @command{ns-3} @code{Object} and you will be able to
call @code{GetObject} on the resulting smart pointer.  Well, I'm afraid that's
not entirely true.  It's slightly more complicated.

Take a look at @code{src/internet-node/internet-node.h} and find the class
declaration for @code{InternetNode}.

@verbatim
  class InternetNode : public Node
  {
  public:
    InternetNode();
    ...
  };
@end verbatim

@cindex GetTypeId
@cindex TypeId
@cindex Object
There is no declaration of a @code{static TypeId GetTypeId (void)} in this
class.  This means that the @code{InternetNode} is really not an @code{Object}
for which you can @code{GetObject}.  It turns out that the @code{InternetNode}
is an @emph{implementation class} of the @code{Node Object}.

You may recall that there can be an implicit cast in a smart pointer
assignment if the cast is to a visible, unambiguous base class.  That is, in 
fact, what is happening here.  Now, take a look at @code{src/node/node.h} and
find the class declaration for @code{class Node}.  There you will find,

@verbatim
  class Node : public Object
  {
  public:
    static TypeId GetTypeId (void);
    ...
  };
@end verbatim

Class @code{InternetNode} inherits from class @code{Node} that, in turn,
inherits from class @code{Object}.  It is @code{Node} that provides a
@code{GetTypeId} method.  Therefore it is @code{Node} that is an 
@command{ns-3} @code{Object}.  Note well that @code{InternetNode} is not an
@code{Object} in the sense that one should call @code{GetObject} on an 
aggregation looking for an @code{InternetNode} class.  That is, you should not
do,

@verbatim
  Ptr<InternetNode> i = node->GetObject<InternetNode> ();
@end verbatim

since there really is not InternetNode::GetTypeId.  It is @code{Node} that is 
the @emph{proper} @code{Object} in this case and you should view 
@code{InternetNode} as an implementation of the @code{Node Object}.  This may
become clearer as we look a little deeper.

We spoke of a protocol stack that is aggregated to a @code{Node} in our
discussions above, what we see in the real @command{ns-3} code is that this
is represented by the @code{Ipv4 Object}.  If you look in 
@code{src/node/ipv4.h} you will find,

@verbatim
  class Ipv4 : public Object
  {
  public:
    static TypeId GetTypeId (void);
    ...
  };
@end verbatim

Since class @code{Ipv4} inherits from class @code{Object} and has a 
@code{GetTypeId}, it is an @command{ns-3} @code{Object}.  If you look in
@code{src/node/ipv4.cc} you will find,

@verbatim
TypeId
Ipv4::GetTypeId (void)
{
  static TypeId tid = TypeId ("Ipv4")
    .SetParent<Object> ();
  return tid;
}
@end verbatim

After all of this reading you know that this code snippet is asking the
system to create a unique @code{TypeId} for the @code{Ipv4} class and
declares that @code{Ipv4} inherits from class @code{Object}.  This is what
makes an @code{Ipv4} an @code{Object}.

@cindex Ipv4
It turns out that the Ipv4 class is an abstract base class (ABC).  There are
a number of pure virtual methods declared in that class.  This means that
an @code{Ipv4} object may not be instantiated.  This is reflected by the fact
that there are no constructors registered in the @code{GetTypeId} method above.
What is instantiated in the real system is an implementation class, called 
@code{Ipv4Impl}.  This class inherits from @code{Ipv4} and provides the 
required virtual methods.  This is where understanding what is an 
@code{Object} and what is not can get tricky.  The @code{Object} is the 
@code{Ipv4} class since that is where the @code{GetTypeId} is found.  The fact
that you see @code{GetTypeId} there tells you that the @code{Ipv4} class is
the class for which you can @code{GetObject}.

@cindex implementation class
The class @code{Ipv4Impl} provides an implementation for the pure virtual
methods in @code{Ipv4}.  Since class @code{Ipv4} cannot be instantiated, one
instantiates the @code{Ipv4Impl} class to create an @code{Ipv4} @code{Object}.
You will use the @code{CreateObject} template function to create an object that
implements the methods of an @code{Object}.  You can probably see how this
gets even more tricky in conversation.

Once the @code{Ipv4Impl} object is instantiated, the resulting pointer is
immediately cast to an @code{Ipv4} pointer.  Clients will then use the
methods specified in the @code{Ipv4} class to access the @code{Ipv4 Object}
methods which are, in turn, implemented in the @code{Ipv4Impl} object.

If you now look in the file, @code{src/internet-node/internet-node.cc} you
will see the following code in @code{InternetNode::Construct} that creates the
@code{Ipv4} Interface and aggregates it.

@verbatim
  Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> (ipv4);
  ...
  Object::AggregateObject (ipv4Impl);
@end verbatim

Note that the parameter @code{ipv4} passed to the @code{CreateObject} template
function is actually a pointer to an @code{Ipv4L3Protocol} which you can
ignore at this point --- it doesn't really have anything to do with the 
@code{Ipv4} Interface.

This is exactly the same thing that is happening in the case of the 
@code{InternetNode}.

@verbatim
  Ptr<Node> n = CreateObject<InternetNode> ();
@end verbatim

@cindex implementation object
@code{CreateObject} is being called to create an implementation object,
in this case @code{InternetNode}, which implements the methods of the 
@code{Node Object}.  It is the resulting @code{Node Object} which you would
use as the container and it is the @code{Node} class that you would use as
the template parameter when calling @code{GetObject}.  In the same way, you
would @emph{not} want to do,

@verbatim
  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4Impl> ();
@end verbatim

Rather you should understand that the @emph{proper} @code{Object} is the 
@code{Ipv4} not the @code{Ipv4Impl} and do the following,

@verbatim
  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
@end verbatim

@cindex CreateObject
This does illustrate that the fact that whether an object created by 
@code{CreateObject} is or is not an @code{Object} in the usual sense can be
quite well hidden if you are casually looking at the object creation code.
The designers of the system had long and involved discussions on this issue 
and in the end decided that mnemonic aids such as Hungarian notation were a
stylistic thing and you should just refer to the system documentation to
determine what objects are @command{ns-3} @code{Objects} and what the APIs 
of those @code{Objects} actually are (RTFM --- as in Read the Fine Manual, 
of course).

@cindex AggregateObject
@cindex Object
In the case of @code{Ipv4Impl}, you know that the class inherits somehow 
from @code{Object} since there is a call to @code{AggregateObject} that
refers to an instance of an @code{Ipv4Impl}.  You will have to go to
the header file @code{src/internet-node/ipv4-impl.h} and find that
@code{Ipv4Impl} inherits from class @code{Ipv4}.  You will then have go to
the file @code{src/node/ipv4.h} and see that it inherits from @code{Object} and
defines a @code{GetTypeId}.  Thus the @code{Object} for which you can
@code{GetObject} is really the @code{Ipv4 Object}.

Returning to some real @command{ns-3} example code, lets take a look at 
@code{examples/simple-point-to-point.cc}.  You will find the following
code in this file:

@verbatim
  Ptr<Node> n0 = CreateObject<InternetNode> ();
  ...
  Ptr<Ipv4> ipv4;
  ipv4 = n0->GetObject<Ipv4> ();
  ipv4->SetDefaultRoute (Ipv4Address (``10.1.1.2''), 1);
@end verbatim

@cindex InternetNode
@cindex Node
@cindex Object
@cindex GetObject
The first line creates an @code{InternetNode} implementation object and casts
the resulting smart pointer to a @code{Node} as we have discussed extensively.
The next line shown declares a smart pointer to an @code{Ipv4 Object}.  We
then do a @code{GetObject} on the @code{Node} looking for the 
@code{Ipv4 Object}.  You know since you've read every line of this tutorial
in detail exactly how that @code{Ipv4 Object} got into every @code{Node}.  You
know that the @code{GetObject} will return a smart pointer to its aggregated 
@code{Ipv4} Interface.  Once we have the @code{Ipv4} smart pointer, we simply
use it as if it were any other C++ object.  The last line shows this by
setting the default route for the node.

@section Caveats
There are a few things that you should remember but which may not be 
immediately obvious.  

@subsection Ns-3 Objects are Associated with Classes not C++ objects
@cindex Object
@cindex GetObject
@cindex iterate
@cindex aggregation
@cindex GetNDevices
Okay, you can see some of the problems with the terminology popping up again.
We are reminding you that when you do a GetObject you are providing the key
to the lookup by giving a class name and not anything that is unique to a
C++ object.

You cannot add more than one @code{Object} of a given type (class name) to an
aggregation.  If you need to contain a number of @code{Objects} of the same
type in the same aggregation, you will need to provide a separate container 
over which you can iterate.  For example, the @code{Node} class provides 
methods,

@verbatim
  uint32_t GetNDevices (void) const;
  Ptr<NetDevice> GetDevice (uint32_t index) const;
@end verbatim

that are used iterate over the multiple @code{NetDevice} @code{Objects}
associated with it.

@emph{Remember:  Object types do not identify objects.}

@subsection Dont use GetObject to Check Your Own Type.
@cindex GetObject
It is tempting to use @code{GetObject} as a form of runtime type
information.  Dont do it.  You have no control over what @emph{other}
object may be added to your aggregation.  Someone else may have
appropriated (reimplemented) your type and aggregated themselves onto the
aggregation.

Consider a socket factory implementation.  Sockets can be either UDP sockets
or TCP sockets.  A socket factory will have a generic @code{SocketFactory}
Object and either a UDP specific interface for setting UDP parameters or a
similar TCP-specific interface.

Consider what might happen if you declared your socket factory as a partially
abstract base class, and then provided separate implementations for UDP and
TCP specific methods of this factory in separate concrete classes.  Now 
consider what might happen if you used @code{GetObject} in your base class
to determine if you were a UDP or a TCP factory.

If a factory, say the UDP version, were not aggregated to any other 
@code{Object}, the base class could @code{GetObject} on itself for the 
UDP-specific class name.  If the @code{GetObject} succeeded, it could then
infer that it was a UDP implementation and would then do any UDP-specific
tasks it could.  [Experienced C++ folks are cringing about how
horrible this design is, but bear with me --- its a simple illustration of 
a specific and perhaps not-too-obvious problem.]

If another factory, say the TCP version, were not aggregated to any other
Interface, the base class could @code{GetObject} on itself for the UDP-specific
interface.  If this failed, it could then infer that it had a TCP
implementation and would then do any TCP-specific tasks it could.

Now, what happens when these two working objects are aggregated together by
some innocent end-user.  Since the @code{Objects} are conceptually snapped
together, the TCP implementation would suddenly begin finding the UDP 
Interface from the other class factory and think it was the UPD implementation.

@emph{Objects should not be used as run-time type information.}

@section Connecting the Dots
@cindex Object
@cindex GetObject
@cindex AggregateObject
@cindex GetTypeId
@cindex API
This may all sound very complicated to you if this is your first exposure to
these concepts.  It may be annoying if I tell you that its really not as hard
as it sounds.  Rest assured that if you take some time, look at and understand
the examples and write a little test code it will all come together for you.
Grep around the system for @code{AggregateObject} and @code{GetObject} and
take a look at how we have used them.  This will also give you a good idea of
what our core @code{Objects} and associated APIs are.  If you grep for 
@code{GetTypeId} you will find most, if not all of the @code{Object} API
interface declarations in the system.  The more you see this idiom in
use, the more comfortable you will be with the idea and the more you will see
how this addresses the weak base class, swiss army knife base class, and
fragile base class problems I explained at the beginning.

As I alluded to earlier, the developers had long discussions regarding how to
make navigating the @code{Object} environment easier.  The primary issue was
how we could make it easier to convey to you, the model writer, that an object
was an @code{Object}.  We originally used similar terminology as Microsoft
COM and used QueryInterface instead of @code{GetObject}.  One suggestion was
to adopt the convention that classes that implemented Interfaces must begin
with the letter I.  Microsoft does this, as exemplified by the class IUnknown.
We also toyed with the idea of beginning our header files with ``i-'' as in 
``i-ipv4.h.'' We considered forcing some structure on Interfaces with a pure
virtual class specification, the names of which begin with an I; and 
corresponding implementations, the names of which begin with a C.  This all
got out of hand fairly quickly.

In the end we decided that we were really discussing issues of programming
style, and we really could not come up with a strong reason to impose any
particular solution.  No matter what direction we took, we ended up with some
form of extra confusion or extra complexity somewhere in the system.  The 
resulting system is extremely flexible and easy to use.  It is, unfortunately,
sometimes hard to document and talk about.

@cindex Feynman
If it helps you to think in terms of Microsoft COM and Interfaces, by all means
do so, just be aware that even though @command{ns-3} @code{Objects} descend
from COM in some sense, there are subtle differences that may get you lost or
into trouble.  So to paraphrase Feynman one more time,

@quotation
``@command{Ns-3} @code{Objects} do not behave like COM Components, or Java
Beans, or CORBA objects, or clouds or weights on springs, or like anything 
that you have  ever seen --- they are @command{ns-3} components.''
@end quotation

Just get very familiar with the @command{ns-3} object model.  It is the heart
of the system and if you do not understand it you will not understand how to
write an @command{ns-3} model properly.

@c ========================================================================
@c Doxygen
@c ========================================================================

@node The-Doxygen-Documentation-System
@chapter The Doxygen Documentation System

@node How-To-Change-Things
@chapter How to Change Things

@node How-To-Set-Default-Values
@chapter How to Set Default Values

@node How-To-Write-A-New-Application
@chapter How to Write a New Application