cleanup, doxygen, prepare for review
authorCraig Dowell <craigdo@ee.washington.edu>
Mon, 02 Feb 2009 10:12:29 -0800
changeset 4176 0246ffdff112
parent 4175 31a57b66cef5
child 4177 1212830d6f76
cleanup, doxygen, prepare for review
examples/csma-tap-bridge.cc
examples/wscript
src/devices/tap-bridge/tap-bridge.h
src/devices/tap-bridge/tap-creator.cc
src/devices/tap-bridge/tap.h
--- a/examples/csma-tap-bridge.cc	Sat Jan 31 22:45:42 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/* -*- 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
- */
-
-// Network topology
-//
-//  +----------+                           +----------+  
-//  | external |                           | external |  
-//  |  Linux   |                           |  Linux   |  
-//  |   Host   |                           |   Host   |  
-//  |  "left"  |                           | "right"  |  
-//  +----------+                           +----------+
-//       |           n0             n3           |
-//       |       +--------+     +--------+       |
-//       +-------|  tap   |     |  tap   |-------+
-//               | bridge | ... | bridge |
-//               +--------+     +--------+
-//               |  CSMA  |     |  CSMA  |
-//               +--------+     +--------+
-//                   |              |
-//                   |              |
-//                   |    n1  n2    |
-//                   |     |   |    |
-//                   ================
-//                          LAN
-
-#include <iostream>
-#include <fstream>
-
-#include "ns3/simulator-module.h"
-#include "ns3/node-module.h"
-#include "ns3/core-module.h"
-#include "ns3/helper-module.h"
-
-using namespace ns3;
-
-NS_LOG_COMPONENT_DEFINE ("CsmaTapBridgeExample");
-
-int 
-main (int argc, char *argv[])
-{
-  //
-  // Users may find it convenient to turn on explicit debugging
-  // for selected modules; the below lines suggest how to do this
-  //
-#if 0 
-  LogComponentEnable ("CsmaOneSubnetExample", LOG_LEVEL_INFO);
-#endif
-
-  //
-  // Make the random number generators generate reproducible results.
-  //
-  RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
-
-  //
-  // Allow the user to override any of the defaults and the above Bind() at
-  // run-time, via command-line arguments
-  //
-  CommandLine cmd;
-  cmd.Parse (argc, argv);
-
-  //
-  // We need to enable the real-time simulator since we are going to be
-  // talking to the "real world."
-  GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
-
-  // 
-  // Also, since the whole point of this exercise is to exchange packets
-  // with hosts running in the real world, we are going to need to enable
-  // checksums.
-  //
-  Config::SetDefault ("ns3::Ipv4L3Protocol::CalcChecksum", BooleanValue (true)); 
-  Config::SetDefault ("ns3::Icmpv4L4Protocol::CalcChecksum", BooleanValue (true)); 
-  Config::SetDefault ("ns3::TcpL4Protocol::CalcChecksum", BooleanValue (true)); 
-  Config::SetDefault ("ns3::UdpL4Protocol::CalcChecksum", BooleanValue (true)); 
-
-  //
-  // Create the nodes required by the topology (shown above).
-  //
-  NS_LOG_INFO ("Create nodes.");
-  NodeContainer nodes;
-  nodes.Create (4);
-
-  //
-  // Create and install the network.
-  //
-  NS_LOG_INFO ("Build Topology");
-  CsmaHelper csma;
-  csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
-  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
-
-  NetDeviceContainer devices = csma.Install (nodes);
-
-  InternetStackHelper internet;
-  internet.Install (nodes);
-
-  //
-  // We've got the "hardware" in place.  Now add IP addresses.
-  //
-  NS_LOG_INFO ("Assign IP Addresses.");
-  Ipv4AddressHelper ipv4;
-  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
-  Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
-
-  //
-  // The Tap bridge is going to use the address information we just created
-  // when it makes a Tap device on the Linux host.  This actually happens
-  // when the simulation is started, so there is no dependence on ordering
-  // of the IP and MAC address assignment in the initialization phase of
-  // the simulation.
-  //
-  // The Tap bridge will suck the MAC address out of the bridged device, and 
-  // the IP address and net mask out of the Ipv4Interface which is associated 
-  // with the bridged device.  It will use these found values unless we 
-  // configure Attribute to provide alternate values.  There are two 
-  // configuration Attributes we always need to pay some attention to.
-  //
-  // The "Gateway" Attribute is the IP address of the default gateway that 
-  // will be set on the newly created Tap devices on the Linux hosts.  We
-  // can't derive this address, so it must be set.  Following standard 
-  // practice in helpers, this Attribute is a construction parameter for
-  // the Helper.  Here, we pick the interface corresponding to the 
-  // CSMA device on node one as the default gateway.  You can change this
-  // at a later time by setting the "Gateway" Attribute in the helper.
-  //
-  TapBridgeHelper bridge (interfaces.GetAddress (1));
-
-  //
-  // The "DeviceName" is the name of the Tap device that will be created on
-  // the Linux host.  If we leave this Attribute set to the default value,
-  // the Linux system will create on of the name /dev/tapx where x will be 
-  // a number from 0 to 255.  In a simulation where you have some number of
-  // Tap devices, it is convenient to assign a name.  Referring back to the 
-  // topology illustration, we assign the name "left" to the tap device on
-  // the host to the left of the diagram, and "right" to the host on the right.
-  //
-  // Create a tap-bridge on node zero, create a Tap device called "left" on the
-  // Linux host and bridge that Linux device to the CSMA device on node zero.
-  //
-  bridge.SetAttribute ("DeviceName", StringValue ("left"));
-  bridge.Install (nodes.Get (0), devices.Get (0));
-
-  //
-  // Create a tap-bridge on node three, create a Tap device called "right" on the
-  // Linux host and bridge that Linux device to the CSMA device on node three.
-  //
-  bridge.SetAttribute ("DeviceName", StringValue ("right"));
-  bridge.Install (nodes.Get (3), devices.Get (3));
-
-  //
-  // Configure tracing of all enqueue, dequeue, and NetDevice receive events.
-  //
-  NS_LOG_INFO ("Configure Tracing.");
-  CsmaHelper::EnablePcapAll ("csma-tap-bridge");
-
-  //
-  // Now, do the actual simulation.  Run for a few minutes to allow the user a chance
-  // to run some applications on the Linux hosts.
-  //
-  Simulator::Stop (Seconds (60.));
-  NS_LOG_INFO ("Run Simulation.");
-  Simulator::Run ();
-  Simulator::Destroy ();
-  NS_LOG_INFO ("Done.");
-}
--- a/examples/wscript	Sat Jan 31 22:45:42 2009 -0800
+++ b/examples/wscript	Mon Feb 02 10:12:29 2009 -0800
@@ -48,10 +48,6 @@
                                  ['csma', 'internet-stack'])
     obj.source = 'csma-one-subnet.cc'
 
-    obj = bld.create_ns3_program('csma-tap-bridge',
-                                 ['csma', 'tap-bridge', 'internet-stack'])
-    obj.source = 'csma-tap-bridge.cc'
-
     obj = bld.create_ns3_program('tap-dumbbell',
                                  ['csma', 'point-to-point', 'tap-bridge', 'internet-stack'])
     obj.source = 'tap-dumbbell.cc'
--- a/src/devices/tap-bridge/tap-bridge.h	Sat Jan 31 22:45:42 2009 -0800
+++ b/src/devices/tap-bridge/tap-bridge.h	Mon Feb 02 10:12:29 2009 -0800
@@ -46,7 +46,7 @@
  * The Tap Bridge lives in a kind of a gray world somewhere between a Linux host and
  * an ns-3 bridge device.  From the Linux perspective, this code appears as the user
  * mode handler for a Tap net device.  That is, when the Linux host writes to the
- * /dev/tapx device that we create for it, the write is redirected into the TapBridge
+ * /dev/tap device that we create for it, the write is redirected into the TapBridge
  * and from that perspective, becomes a read.  The TapBridge then redirects the data
  * written (by the Linux host) to the tap device on out the ns-3 net device to which
  * we are bridged.  When a packet comes in from the ns-3 world to the ns-3 net device
@@ -78,6 +78,9 @@
   virtual ~TapBridge ();
 
   /** \brief Get the bridged net device.
+   *
+   * The bridged net device is the ns-3 device to which this bridge is connected,
+   *
    * \returns the bridged net device.
    */
   Ptr<NetDevice> GetBridgedNetDevice (void);
@@ -93,9 +96,16 @@
   void SetBridgedNetDevice (Ptr<NetDevice> bridgedDevice);
 
   /**
-   * Set a start time for the device.
+   * \brief Set a start time for the device.
    *
-   * @param tStart the start time
+   * The tap bridge consumes a non-trivial amount of time to start.  It starts
+   * up in the context of a scheduled event to ensure that all configuration
+   * has been completed before extracting the configuration (IP addresses, etc.)
+   * In order to allow a more reasonable start-up sequence than a thundering 
+   * herd of devices, the time at which each device starts is also configurable
+   * bot via the Attribute system and via this call.
+   *
+   * \param tStart the start time
    */
   void Start (Time tStart);
 
@@ -103,10 +113,15 @@
    * Set a stop time for the device.
    *
    * @param tStop the stop time
+   *
+   * \see TapBridge::Start
    */
   void Stop (Time tStop);
 
-  // inherited from NetDevice base class.
+  //
+  // The following methods are inherited from NetDevice base class and are
+  // documented there.
+  //
   virtual void SetName(const std::string name);
   virtual std::string GetName(void) const;
   virtual void SetIfIndex(const uint32_t index);
@@ -134,6 +149,14 @@
   virtual Address GetMulticast (Ipv6Address addr) const;
 
 protected:
+  /**
+   * \internal
+   *
+   * Call out to a separate process running as suid root in order to get our
+   * tap device created.  We do this to avoid having the entire simulation 
+   * running as root.  If this method returns, we'll have a socket waiting 
+   * for us in m_sock that we can use to talk to the tap device.
+   */
   virtual void DoDispose (void);
 
   void ReceiveFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
@@ -141,6 +164,8 @@
 private:
 
   /**
+   * \internal
+   *
    * Call out to a separate process running as suid root in order to get our
    * tap device created.  We do this to avoid having the entire simulation 
    * running as root.  If this method returns, we'll have a socket waiting 
@@ -149,67 +174,218 @@
   void CreateTap (void);
 
   /**
+   * \internal
+   *
    * Figure out where the tap creation program lives on the system.
+   *
+   * \param creatorName The name of the program used to create the Tap.
+   * \returns A path name to use when you want to create a Tap.
    */
   std::string FindCreator (std::string creatorName);
 
   /**
+   * \internal
+   *
    * Spin up the device
    */
   void StartTapDevice (void);
 
   /**
+   * \internal
+   *
    * Tear down the device
    */
   void StopTapDevice (void);
 
   /**
+   * \internal
+   *
    * Loop to read and process packets
    */
   void ReadThread (void);
 
   /*
+   * \internal
+   *
    * Forward a packet received from the tap device to the bridged ns-3 
    * device
+   *
+   * \param buf A character buffer containing the actaul packet bits that were
+   *            received from the host.
+   * \param buf The length of the buffer.
    */
   void ForwardToBridgedDevice (uint8_t *buf, uint32_t len);
 
   /**
+   * \internal
+   *
    * The host we are bridged to is in the evil real world.  Do some sanity
    * checking on a received packet to make sure it isn't too evil for our
    * poor naive virginal simulator to handle.
-   */
+   *
+   * \param packet The packet we received from the host, and which we need 
+   *               to check.
+   * \param src    A pointer to the data structure that will get the source
+   *               MAC address of the packet (extracted from the packet Ethernet
+   *               header).
+   * \param dst    A pointer to the data structure that will get the destination
+   *               MAC address of the packet (extracted from the packet Ethernet 
+   *               header).
+   * \param type   A pointer to the variable that will get the packet type from 
+   *               either the Ethernet header in the case of type interpretation
+   *               (DIX framing) or from the 802.2 LLC header in the case of 
+   *               length interpretation (802.3 framing).
+   */   
   Ptr<Packet> Filter (Ptr<Packet> packet, Address *src, Address *dst, uint16_t *type);
 
+  /**
+   * \internal
+   *
+   * Callback used to hook the standard packet receive callback of the TapBridge
+   * ns-3 net device.  This is never called, and therefore no packets will ever
+   * be received forwarded up the IP stack on the ghost node through this device.
+   */
   NetDevice::ReceiveCallback m_rxCallback;
+
+  /**
+   * \internal
+   *
+   * Callback used to hook the promiscuous packet receive callback of the TapBridge
+   * ns-3 net device.  This is never called, and therefore no packets will ever
+   * be received forwarded up the IP stack on the ghost node through this device.
+   *
+   * Note that we intercept the similar callback in the bridged device in order to
+   * do the actual bridging between the bridged ns-3 net device and the Tap device
+   * on the host.
+   */
   NetDevice::PromiscReceiveCallback m_promiscRxCallback;
 
+  /**
+   * \internal
+   *
+   * Pointer to the (ghost) Node to which we are connected.
+   */
   Ptr<Node> m_node;
+
+  /**
+   * \internal
+   *
+   * A possible name for the (ghost) Node to which we are connected.
+   */
   std::string m_name;
+
+  /**
+   * \internal
+   *
+   * The ns-3 interface index of this TapBridge net device.
+   */
   uint32_t m_ifIndex;
+
+  /**
+   * \internal
+   *
+   * The common mtu to use for the net devices
+   */
   uint16_t m_mtu;
+
+  /**
+   * \internal
+   *
+   * The socket (actually interpreted as fd) to use to talk to the Tap device on
+   * the real internet host.
+   */
   int32_t m_sock;
+
+  /**
+   * \internal
+   *
+   * The ID of the ns-3 event used to schedule the start up of the underlying
+   * host Tap device and ns-3 read thread.
+   */
   EventId m_startEvent;
+
+  /**
+   * \internal
+   *
+   * The ID of the ns-3 event used to schedule the tear down of the underlying
+   * host Tap device and ns-3 read thread.
+   */
   EventId m_stopEvent;
+
+  /**
+   * \internal
+   *
+   * Used to identify the ns-3 read thread used to do blocking reads on the 
+   * socket (fd) corresponding to the host device.
+   */
   Ptr<SystemThread> m_readThread;
+
+  /**
+   * \internal
+   *
+   * The (unused) MAC address of the TapBridge net device.  Since the TapBridge
+   * is implemented as a ns-3 net device, it is required to implement certain
+   * functionality.  In this case, the TapBridge is automatically assigned a
+   * MAC address, but it is not used.  The MAC address assigned to the internet
+   * host actually comes from the bridged (N.B. the "ed") device and not from 
+   * the bridge device.
+   */
   Mac48Address m_address;
 
   /**
+   * \internal
+   *
    * Time to start spinning up the device
    */
   Time m_tStart;
 
   /**
+   * \internal
+   *
    * Time to start tearing down the device
    */
   Time m_tStop;
 
+  /**
+   * \internal
+   *
+   * The name of the device to create on the host.  If the device name is the
+   * empty string, we allow the host kernel to choose a name.
+   */
   std::string m_tapDeviceName;
+
+  /**
+   * \internal
+   *
+   * The IP address to use as the device default gateway on the host.
+   */
   Ipv4Address m_tapGateway;
+
+  /**
+   * \internal
+   *
+   * The IP address to use as the device IP on the host.
+   */
   Ipv4Address m_tapIp;
+  /**
+   * \internal
+   *
+   * The MAC address to use as the hardware address on the host.
+   */
   Mac48Address m_tapMac;
+
+  /**
+   * \internal
+   *
+   * The network mask to assign to the device created on the host.
+   */
   Ipv4Mask m_tapNetmask;
 
+  /**
+   * \internal
+   *
+   * The ns-3 net device to which we are bridging.
+   */
   Ptr<NetDevice> m_bridgedDevice;
 };
 
--- a/src/devices/tap-bridge/tap-creator.cc	Sat Jan 31 22:45:42 2009 -0800
+++ b/src/devices/tap-bridge/tap-creator.cc	Mon Feb 02 10:12:29 2009 -0800
@@ -61,7 +61,7 @@
     }
 
 //
-// Thanks, Mathieu, for the beginning of these functions
+// Lots of the following helper code taken from corresponding functions in src/node.
 //
 #define ASCII_DOT (0x2e)
 #define ASCII_ZERO (0x30)
@@ -146,14 +146,6 @@
   sin->sin_addr.s_addr = htonl (networkOrder);
 }
 
-/**
- * \brief Send the socket file descriptor we created back to the tap bridge, 
- * which will read it as soon as we're done.
- *
- * \param path The socket address information from the Unix socket we use
- * to send the created socket back to.
- * \param fd The socket we're going to send. 
- */
   static void
 SendSocket (const char *path, int fd)
 {
@@ -447,14 +439,6 @@
   int sock = CreateTap (dev, gw, ip, mac, netmask);
   ABORT_IF (sock == -1, "main(): Unable to create tap socket", 1);
 
-#if 0
-  for (;;)
-    {
-      LOG ("z");
-      sleep (1);
-    }
-#endif
-
   //
   // Send the socket back to the tap net device so it can go about its business
   //
--- a/src/devices/tap-bridge/tap.h	Sat Jan 31 22:45:42 2009 -0800
+++ b/src/devices/tap-bridge/tap.h	Mon Feb 02 10:12:29 2009 -0800
@@ -4,5 +4,65 @@
  *
  * \section TapBridgeModelOverview TapBridge Model Overview
  *
- * The tap bridge ...
+ * The Tap Bridge is designed to integrate "real" internet hosts (or more 
+ * precisely, hosts that support Tun/Tap devices) into ns-3 simulations.  The 
+ * goal is to make it appear to the host host node in question that it has an
+ * ns-3 net device as a local device.  The concept of a "real host" is a bit
+ * slippery the "real host" may actually be virtualized using readily avialable
+ * technologies such as VMware or OpenVZ.
+ *
+ * Since we are, in essence, connecting the inputs and outputs of an ns-3 net 
+ * device to the inputs and outputs of a Linux Tap net device, we call this 
+ * arrangement a Tap Bridge.
+ *
+ * The TapBridge appears to the Linux host computer as a network device just
+ * like any arbitrary "eth0" or "ath0" might appear.  The creation and
+ * configuration of the device is done by the ns-3 simulation, however.  You 
+ * should not expect to be able to configure a net device via, for example,
+ * wlanconfig.  The IP addresses, MAC addresses, gateway, etc., for the given
+ * Tap device are also set up by the ns-3 simulation.  If you change the
+ * or manipulate the configuration manually, you will almost certainly break
+ * the simulation.
+ *
+ * The TapBridge appears to an ns-3 simulation as a channel-less net device.
+ * This device, however, must _not_ have an IP address associated with it.  
+ * Be aware that this is the inverse situation of an ns-3 BridgeNetDevice
+ * which demands that its bridge ports not have IP addresses, but allows the
+ * bridge to have an IP address.  
+ *
+ * The host computer will appear in a simulation as a "ghost" node that contains
+ * pairs of net devices and Tap bridges that represent the host devices.  From
+ * the perspective of a simulation, the only difference between a ghost node and
+ * another node will be the presence of the TapBridge devices that connect to
+ * the hosts.  Configuration of address information and the ns-3 devices is
+ * not changed in any way.  A TapBridge will pick up the addressing info from
+ * the ns-3 net device to which it is connected (its "bridged" net device) and
+ * use that information to configure the device on the real host.
+ *
+ * The end result of this is a situation where one can, for example, use the
+ * standard ping utility on a real host to ping a simulated ns-3 net device.  If
+ * correct routes are added to the internet host, the routing systems in ns-3
+ * will enable correct routing of the packets across simulated ns-3 networks.
+ * For an example of this, see the example program, tap-dumbbell.cc in the 
+ * ns-3 distribution.
+ *
+ * \section TapBridgeChannelModel Tap Bridge Channel Model
+ *
+ * There is no channel model associated with the Tap Bridge.  In fact, the
+ * intention is make it appear that the real internet host is connected to 
+ * the channel of the bridged net device.
+ *
+ * \section TapBridgeTracingModel Tap Bridge Tracing Model
+ *
+ * Unlike most ns-3 devices, the TapBridge does not provide any standard trace
+ * sources.  This is because the bridge is an intermediary that is essentially
+ * one function call away from the bridged device.  We expect that the trace
+ * hooks in the bridged device will be sufficient for most users,
+ *
+ * \section TapBridgeUsage Using the Tap Bridge
+ *
+ * We expect that most users will interact with the TapBridge device through
+ * the TapBridgeHelper.  Users of other helper classes, such as CSMA or Wifi,
+ * should be comfortable with the idioms used.
  */
+