--- a/src/devices/csma/csma-net-device.h Wed Mar 11 11:16:25 2009 +0000
+++ b/src/devices/csma/csma-net-device.h Fri Mar 13 17:37:35 2009 -0700
@@ -61,7 +61,6 @@
/**
* Enumeration of the types of packets supported in the class.
- *
*/
enum EncapsulationMode {
ILLEGAL, /**< Encapsulation mode not set */
--- a/src/devices/tap-bridge/tap-bridge.cc Wed Mar 11 11:16:25 2009 +0000
+++ b/src/devices/tap-bridge/tap-bridge.cc Fri Mar 13 17:37:35 2009 -0700
@@ -28,6 +28,7 @@
#include "ns3/abort.h"
#include "ns3/boolean.h"
#include "ns3/string.h"
+#include "ns3/enum.h"
#include "ns3/ipv4.h"
#include "ns3/simulator.h"
#include "ns3/realtime-simulator-impl.h"
@@ -48,10 +49,7 @@
// if you are running in an environment where you have got to run as root,
// such as ORBIT or CORE.
//
-// sudo tunctl -t tap0
-// sudo ifconfig tap0 hw ether 00:00:00:00:00:01
-// sudo ifconfig tap0 10.1.1.1 netmask 255.255.255.0 up
-//
+
// #define NO_CREATOR
@@ -111,6 +109,12 @@
TimeValue (Seconds (0.)),
MakeTimeAccessor (&TapBridge::m_tStop),
MakeTimeChecker ())
+ .AddAttribute ("Mode",
+ "The operating and configuration mode (LocalDevice or BridgedDevice) to use.",
+ EnumValue (LOCAL_DEVICE),
+ MakeEnumAccessor (&TapBridge::SetMode),
+ MakeEnumChecker (LOCAL_DEVICE, "LocalDevice",
+ BRIDGED_DEVICE, "BridgedDevice"))
;
return tid;
}
@@ -215,35 +219,27 @@
{
NS_LOG_FUNCTION_NOARGS ();
-#ifdef NO_CREATOR
- //
- // In come cases, can you say FreeBSD, the tap-creator just gets in the way.
- // in this case, just define NO_CREATOR, manually set up your tap device and
- // just open and use it.
+ //
+ // The TapBridge has two distinct operating modes. The difference revolves
+ // around who is responsible for creating and configuring the underlying
+ // network tap that we use. In LocalDevice mode, the TapBridge has the
+ // responsibility for creating and configuring the TAP.
//
- //
- // Creation and management of Tap devices is done via the tun device
- //
- m_sock = open ("/dev/net/tun", O_RDWR);
- NS_ABORT_MSG_IF (m_sock == -1, "TapBridge::CreateTap(): could not open /dev/net/tun: " << strerror (errno));
-
+ // In BridgedDevice mode, the user will provide us a configuration and we have
+ // to adapt to it. For example, the user will do something like:
//
- // Allocate a tap device, making sure that it will not send the tun_pi header.
- // If we provide a null name to the ifr.ifr_name, we tell the kernel to pick
- // a name for us (i.e., tapn where n = 0..255
+ // sudo tunctl -t tap0
+ // sudo ifconfig tap0 hw ether 00:00:00:00:00:01
+ // sudo ifconfig tap0 10.1.1.1 netmask 255.255.255.0 up
//
- struct ifreq ifr;
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- strcpy (ifr.ifr_name, m_tapDeviceName.c_str ());
- int status = ioctl (m_sock, TUNSETIFF, (void *) &ifr);
- NS_ABORT_MSG_IF (status == -1, "TapBridge::CreateTap(): could not open device " << m_tapDeviceName <<
- ": " << strerror (errno));
-
-#else // use the tap-creator
-
+ // set the "Mode" Attribute to "BridgedDevice" and the "DeviceName" Attribute
+ // to "tap0" in this case.
//
- // We want to create a tap device on the host. Unfortunately for us
- // you have to have root privileges to do that. Instead of running the
+ // In LocalDevice mode, we will do the configuration and create a TAP with
+ // the provided "DeviceName" with which the user can later do what she wants.
+ //
+ // We want to either create or use a tap device on the host. Unfortunately for
+ // us you have to have root privileges to do that. Instead of running the
// entire simulation as root, we decided to make a small program who's whole
// reason for being is to run as suid root and do what it takes to create the
// tap. We're going to fork and exec that program soon, but we need to have
@@ -300,9 +296,10 @@
// -i<IP-address> The IP address to assign to the new tap device;
// -m<MAC-address> The MAC-48 address to assign to the new tap device;
// -n<network-mask> The network mask to assign to the new tap device;
+ // -o<operating mode> The operating mode of the bridge (1=LocalDevice, 2=BridgedDevice)
// -p<path> the path to the unix socket described above.
//
- // Example tap-creator -dnewdev -g1.2.3.2 -i1.2.3.1 -m08:00:2e:00:01:23 -n255.255.255.0 -pblah
+ // Example tap-creator -dnewdev -g1.2.3.2 -i1.2.3.1 -m08:00:2e:00:01:23 -n255.255.255.0 -o1 -pblah
//
// We want to get as much of this stuff automagically as possible.
//
@@ -382,6 +379,17 @@
ossNetmask << "-n" << m_tapNetmask;
}
+ std::ostringstream ossMode;
+ ossMode << "-o";
+ if (m_mode == LOCAL_DEVICE)
+ {
+ ossMode << "1";
+ }
+ else
+ {
+ ossMode << "2";
+ }
+
std::ostringstream ossPath;
ossPath << "-p" << path;
//
@@ -394,7 +402,8 @@
ossIp.str ().c_str (), // argv[3] (-i<IP address>)
ossMac.str ().c_str (), // argv[4] (-m<MAC address>)
ossNetmask.str ().c_str (), // argv[5] (-n<net mask>)
- ossPath.str ().c_str (), // argv[6] (-p<path>)
+ ossMode.str ().c_str (), // argv[6] (-o<operating mode>)
+ ossPath.str ().c_str (), // argv[7] (-p<path>)
(char *)NULL);
//
@@ -521,7 +530,6 @@
}
NS_FATAL_ERROR ("Did not get the raw socket from the socket creator");
}
-#endif // use the tap-creator
}
std::string
@@ -634,6 +642,32 @@
NS_LOG_LOGIC ("Pkt destination is " << dst);
NS_LOG_LOGIC ("Pkt LengthType is " << type);
+ //
+ // If we are in BridgedDevice mode, the MAC addresses of the bridged device
+ // and the TAP device will be different. If this is a unicast packet, we
+ // need to remember the source MAC address for the trip back the other way.
+ // Only remember the first such address and error out if we find another
+ // one since "that can't happen." We use the variable m_tapMac for
+ // remembering this (set by the Attribute "MacAddress") which allows a
+ // user to override the remembered address.
+ //
+ Mac48Address mac48Source = Mac48Address::ConvertFrom (src);
+ if (m_mode == BRIDGED_DEVICE)
+ {
+ if (mac48Source.IsBroadcast () == false && mac48Source.IsMulticast () == false)
+ {
+ if (m_tapMac.IsBroadcast ())
+ {
+ m_tapMac = mac48Source;
+ }
+ else
+ {
+ NS_ABORT_MSG_UNLESS (mac48Source == m_tapMac, "TapBridge::ForwardToBridgedDevice(): "
+ "Multiple distinct source addresses appearing from network tap unexpectedly");
+ }
+ }
+ }
+
NS_LOG_LOGIC ("Forwarding packet");
m_bridgedDevice->Send (packet, dst, type);
}
@@ -755,7 +789,13 @@
// destination address of the actual packet. This means we will be getting
// PACKET_OTHERHOST packets (not broadcast, not multicast, not unicast to
// this device, but to some other address). We don't want to forward those
- // PACKET_OTHERHOST packets so just ignore them
+ // PACKET_OTHERHOST packets so just ignore them.
+ //
+ // In the BRIDGED_DEVICE case, as far as the ns-3 device knows, there is no
+ // other device involved. As far as other devices on the ns-3 side of things
+ // are concerned, there is no other device involved, so a PACKET_OTHERHOST
+ // here carries the same meaning as in any other device. THey are packets
+ // we can safely ignore.
//
if (packetType == PACKET_OTHERHOST)
{
@@ -775,7 +815,34 @@
EthernetHeader header = EthernetHeader (false);
header.SetSource (from);
- header.SetDestination (to);
+
+ //
+ // We have to be careful here when we're running in BRIDGED_DEVICE mode.
+ // In this case, the user will have configured the network tap and it will
+ // have its own MAC address that is distinct from the ns-3 device from which
+ // we just got the packet. We learn what this address is when we receive
+ // packets from the tap. All we have to do is to spoof the packet by
+ // substituting the learned address in here as the source address. However,
+ // until we get that address we don't know what to do and so we just ignore
+ // the packet. N.B. This means that bridging will not start until the
+ // network tap sends its first packet across the bridge.
+ //
+ if (m_mode == BRIDGED_DEVICE)
+ {
+ if (m_tapMac.IsBroadcast ())
+ {
+ return;
+ }
+ else
+ {
+ header.SetDestination (m_tapMac);
+ }
+ }
+ else
+ {
+ header.SetDestination (to);
+ }
+
header.SetLengthType (protocol);
p->AddHeader (header);
@@ -831,6 +898,20 @@
return m_address;
}
+ void
+TapBridge::SetMode (enum Mode mode)
+{
+ NS_LOG_FUNCTION (mode);
+ m_mode = mode;
+}
+
+ TapBridge::Mode
+TapBridge::GetMode (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_mode;
+}
+
bool
TapBridge::SetMtu (const uint16_t mtu)
{
--- a/src/devices/tap-bridge/tap-bridge.h Wed Mar 11 11:16:25 2009 +0000
+++ b/src/devices/tap-bridge/tap-bridge.h Fri Mar 13 17:37:35 2009 -0700
@@ -38,57 +38,77 @@
class Node;
/**
- * \ingroup devices
- * \defgroup tap-bridge TapBridge
+ * \ingroup tap-bridge
*
- * \brief A bridge to make it appear that a host is connected to an ns-3 net device.
- *
- * 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/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
- * we are bridging, it appears via a callback from that net device. Our job is to
- * take those bits and write them back to the host using the user mode handler for
- * /dev/tapx. This write to the device will then appear to the Linux host as if a
- * packet has arrived on its device.
+ * \brief A bridge to make it appear that a real host process is connected to
+ * an ns-3 net device.
*
- * The upshot is that the Tap Bridge appears to bridge a tap device on a Linux host
- * in the "real world" to an ns-3 net device in the simulation. In order to do this
- * we need a "ghost node" in the simulation to hold the bridged ns-3 net device and
- * this Tap Bridge. This node will not be able to actually do anything else in the
- * simulation with respect to the Tap Bridge and its bridged net device. This is
- * because:
- *
- * - Bits sent to the Tap Bridge using its Send() method are completely ignored.
- * The Tap Bridge is not, itself, connected to any network.
- * - The bridged ns-3 net device is has had its receive callback disconnected from
- * the ns-3 node and reconnected to the Tap Bridge. All data received by a
- * bridged device will be sent to the Linux host and will not be received by the
- * node. You can send but you cannot ever receive.
+ * 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 a /dev/tap device (that is either
+ * manually or automatically created depending on basic operating mode
+ * -- more on this later), the write is redirected into the TapBridge that
+ * lives in the ns-3 world; and from this perspective, becomes a read.
+ * In other words, a Linux process writes a packet to a tap device and
+ * this packet is redirected to an ns-3 process where it is received by
+ * the TapBridge as a result of a read operation there. The TapBridge
+ * then sends the packet to the ns-3 net device to which it is bridged.
+ * In the other direction, a packet received by an ns-3 net device is
+ * bridged to the TapBridge (it appears via a callback from that net
+ * device. The TapBridge then takes that packet and writes it back to
+ * the host using the Linux TAP mechanism. This write to the device will
+ * then appear to the Linux host as if a packet has arrived on its
+ * device.
*
- * You will be able to perform typical ns-3 operations on the ghost node if you so
- * desire. The internet stack, for example, must be there and functional on that
- * node in order to participate in IP address assignment and global routing.
- * However, interfaces talking any Tap Bridge or associated bridged net devices
- * will not work completely. If you understand exactly what you are doing, you
- * can set up other interfaces and devices on the ghost node and use them; but we
- * generally recommend that you treat this node as a ghost of the Linux host and
- * leave it alone.
+ * The upshot is that the Tap Bridge appears to bridge a tap device on a
+ * Linux host in the "real world" to an ns-3 net device in the simulation
+ * and make is appear that a ns-3 net device is actually installed in the
+ * Linux host. In order to do this on the ns-3 side, we need a "ghost
+ * node" in the simulation to hold the bridged ns-3 net device and the
+ * TapBridge. This node should not actually do anything else in the
+ * simulation since its job is simply to make the net device appear in
+ * Linux. This is not just arbitrary policy, it is because:
+ *
+ * - Bits sent to the Tap Bridge from higher layers in the ghost node (using
+ * the TapBridge Send() method) are completely ignored. The Tap Bridge is
+ * not, itself, connected to any network, neither in Linux nor in ns-3;
+ * - The bridged ns-3 net device is has had its receive callback disconnected
+ * from the ns-3 node and reconnected to the Tap Bridge. All data received
+ * by a bridged device will be sent to the Linux host and will not be
+ * received by the node. From the perspective of the ghost node, you can
+ * send over this device but you cannot ever receive.
+ *
+ * Of course, if you understand all of the issues you can take control of
+ * your own destiny and do whatever you want -- we do not actively
+ * prevent you from using the ghost node for anything you decide. You
+ * will be able to perform typical ns-3 operations on the ghost node if
+ * you so desire. The internet stack, for example, must be there and
+ * functional on that node in order to participate in IP address
+ * assignment and global routing. However, as mentioned above,
+ * interfaces talking any Tap Bridge or associated bridged net devices
+ * will not work completely. If you understand exactly what you are
+ * doing, you can set up other interfaces and devices on the ghost node
+ * and use them; or take advantage of the operational send side of the
+ * bridged devices to create traffic generators. We generally recommend
+ * that you treat this node as a ghost of the Linux host and leave it to
+ * itself, though.
*/
-
-/**
- * \ingroup tap-bridge
- * \brief A bridge to make it appear that a host is connected to an ns-3 net device.
- */
-
class TapBridge : public NetDevice
{
public:
static TypeId GetTypeId (void);
+ /**
+ * Enumeration of the operating modes supported in the class.
+ *
+ */
+ enum Mode {
+ ILLEGAL, /**< mode not set */
+ LOCAL_DEVICE, /**< ns-3 creates and configures TAP device */
+ BRIDGED_DEVICE, /**< user creates and configures TAP */
+ };
+
TapBridge ();
virtual ~TapBridge ();
@@ -134,6 +154,20 @@
*/
void Stop (Time tStop);
+ /**
+ * Set the operating mode of this device.
+ *
+ * \param mode The operating mode of this device.
+ */
+ void SetMode (TapBridge::Mode mode);
+
+ /**
+ * Get the operating mode of this device.
+ *
+ * \returns The operating mode of this device.
+ */
+ TapBridge::Mode GetMode (void);
+
//
// The following methods are inherited from NetDevice base class and are
// documented there.
@@ -338,13 +372,19 @@
/**
* \internal
+ *
+ * The operating mode of the bridge. Tells basically who creates and
+ * configures the underlying network tap.
+ */
+ Mode m_mode;
+
+ /**
+ * \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.
+ * MAC address, but it is not used.
*/
Mac48Address m_address;
@@ -386,7 +426,18 @@
/**
* \internal
*
- * The MAC address to use as the hardware address on the host.
+ * The MAC address to use as the hardware address on the host. This can
+ * come from one of two places depending on the operating mode.
+ *
+ * If the TapBridge is in LocalDevice mode, this value comes from the MAC
+ * address assigned to the bridged ns-3 net device and matches the MAC
+ * address of the underlying network TAP which we configured to have the
+ * same value.
+ *
+ * If the TapBridge is in BridgedDevice mode, this value is learned from
+ * from the packets received by the underlying netowrk TAP. This is
+ * because we did not configure the TAP, but have got to spoof packets
+ * destined for there.
*/
Mac48Address m_tapMac;
--- a/src/devices/tap-bridge/tap-creator.cc Wed Mar 11 11:16:25 2009 +0000
+++ b/src/devices/tap-bridge/tap-creator.cc Fri Mar 13 17:37:35 2009 -0700
@@ -29,17 +29,10 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
-#if 0
-#include <linux/un.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#include <linux/route.h>
-#else
#include <sys/un.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <net/route.h>
-#endif
#include <netinet/in.h>
#include "tap-encode-decode.h"
@@ -277,7 +270,7 @@
}
static int
-CreateTap (const char *dev, const char *gw, const char *ip, const char *mac, const char *netmask)
+CreateTap (const char *dev, const char *gw, const char *ip, const char *mac, const char *mode, const char *netmask)
{
//
// Creation and management of Tap devices is done via the tun device
@@ -288,7 +281,9 @@
//
// Allocate a tap device, making sure that it will not send the tun_pi header.
// If we provide a null name to the ifr.ifr_name, we tell the kernel to pick
- // a name for us (i.e., tapn where n = 0..255
+ // a name for us (i.e., tapn where n = 0..255.
+ //
+ // If the device does not already exist, the system will create one.
//
struct ifreq ifr;
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
@@ -300,6 +295,17 @@
LOG ("Allocated TAP device " << tapDeviceName);
//
+ // Operating mode "2" corresponds to BRIDGED_DEVICE mode. This means that
+ // we expect that the user will have named, created and configured a network
+ // tap that we are just going to use. So don't mess up his hard work by
+ // changing anything, just return the tap fd.
+ //
+ if (strcmp (mode, "2") == 0)
+ {
+ return tap;
+ }
+
+ //
// Set the hardware (MAC) address of the new device
//
ifr.ifr_hwaddr.sa_family = 1; // this is ARPHRD_ETHER from if_arp.h
@@ -348,31 +354,35 @@
char *ip = NULL;
char *mac = NULL;
char *netmask = NULL;
+ char *operatingMode = NULL;
char *path = NULL;
opterr = 0;
- while ((c = getopt (argc, argv, "vd:g:i:m:n:p:")) != -1)
+ while ((c = getopt (argc, argv, "vd:g:i:m:n:o:p:")) != -1)
{
switch (c)
{
case 'd':
- dev = optarg; // name of the new tap device
+ dev = optarg; // name of the new tap device
break;
case 'g':
- gw = optarg; // gateway address for the new device
+ gw = optarg; // gateway address for the new device
break;
case 'i':
- ip = optarg; // ip address of the new device
+ ip = optarg; // ip address of the new device
break;
case 'm':
- mac = optarg; // mac address of the new device
+ mac = optarg; // mac address of the new device
break;
case 'n':
- netmask = optarg; // net mask for the new device
+ netmask = optarg; // net mask for the new device
+ break;
+ case 'o':
+ operatingMode = optarg; // operating mode of tap bridge
break;
case 'p':
- path = optarg; // path back to the tap bridge
+ path = optarg; // path back to the tap bridge
break;
case 'v':
gVerbose = true;
@@ -422,6 +432,12 @@
LOG ("Provided Net Mask is \"" << netmask << "\"");
//
+ // We have got to know whether or not to create the TAP.
+ //
+ ABORT_IF (operatingMode == NULL, "Operating Mode is a required argument", 0);
+ LOG ("Provided Operating Mode is \"" << operatingMode << "\"");
+
+ //
// This program is spawned by a tap bridge running in a simulation. It
// wants to create a socket as described below. We are going to do the
// work here since we're running suid root. Once we create the socket,
@@ -444,7 +460,7 @@
// us to exeucte the following code:
//
LOG ("Creating Tap");
- int sock = CreateTap (dev, gw, ip, mac, netmask);
+ int sock = CreateTap (dev, gw, ip, mac, operatingMode, netmask);
ABORT_IF (sock == -1, "main(): Unable to create tap socket", 1);
//
--- a/src/devices/tap-bridge/tap.h Wed Mar 11 11:16:25 2009 +0000
+++ b/src/devices/tap-bridge/tap.h Fri Mar 13 17:37:35 2009 -0700
@@ -6,46 +6,244 @@
*
* 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
+ * goal is to make it appear to a "real" host node in that it has an ns-3 net
+ * device as a local device. The concept of a "real host" is a bit slippery
+ * since 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.
+ * There are two basic operating modes of this device available to users.
+ * Basic functionality is essentially identical, but the two modes are
+ * different in details regarding how the arrangement is configured. In the
+ * first mode, the configuration is ns-3 configuration-centric. Configuration
+ * information is taken from the ns-3 simulation and a tap device matching
+ * the ns-3 attributes is created for you. In this mode, which we call
+ * LocalDevice mode, an ns-3 net device is made to appear to be directly
+ * connected to a real host. In LocalDevice mode, configuration of the TAP
+ * device is almost completely handled by ns-3. This is useful if you want
+ * to use real processes in your host to talk over simulated networks.
+ *
+ * This is illustrated below
+ *
+ * \verbatim
+ * +--------+
+ * | Linux |
+ * | host | +----------+
+ * | ------ | | ghost |
+ * | apps | | node |
+ * | ------ | | -------- |
+ * | stack | | IP | +----------+
+ * | ------ | | stack | | node |
+ * | TAP | |==========| | -------- |
+ * | device | <-- IPC -> | tap | | IP |
+ * +--------+ | bridge | | stack |
+ * | -------- | | -------- |
+ * | ns-3 | | ns-3 |
+ * | net | | net |
+ * | device | | device |
+ * +----------+ +----------+
+ * || ||
+ * +---------------------------+
+ * | ns-3 channel |
+ * +---------------------------+
+ *\endverbatim
+ *
+ * In this case, the ns-3 net device in the ghost node appears as if it were
+ * actually replacing the TAP device in the Linux host. The ns-3 process
+ * configures the IP address and MAC address of the TAP device to match the
+ * values assigned to the ns-3 net device. The IPC link is via the network
+ * tap mechanism in the underlying OS.
+ *
+ * The LocalDevice mode is the default operating mode of the Tap Bridge.
+ *
+ * The second mode, BridgedDevice mode, is more oriented toward allowing existing
+ * host configurations. This allows the Tap Bridge to be "further bridged" to
+ * other existing devices via an existing TAP device. This mode is especially
+ * useful in the case of virtualization where the configuration of the virtual
+ * hosts may be dictated by an existing system and not easily changed. For
+ * example, a particular VM scheme may create virtual "vethx" or "vmnetx"
+ * devices that appear local to virtual hosts. In order to connect to such
+ * systems, we need to manually create TAP devices on the host system and brigde
+ * these TAP devices to the existing virtual devices. We then need to have a Tap
+ * Bridge corresponding created to talk to each of these TAP devices.
+ *
+ * This is illustrated below:
+ *
+ * \verbatim
+ * +---------+
+ * | Linux |
+ * | VM | +----------+
+ * | ------- | | ghost |
+ * | apps | | node |
+ * | ------- | | -------- |
+ * | stack | | IP | +----------+
+ * | ------- | +--------+ | stack | | node |
+ * | Virtual | | TAP | |==========| | -------- |
+ * | device | | device | <-- IPC -> | tap | | IP |
+ * +---------+ +--------+ | bridge | | stack |
+ * || || | -------- | | -------- |
+ * +--------------------+ | ns-3 | | ns-3 |
+ * | OS (brctl) Bridge | | net | | net |
+ * +--------------------+ | device | | device |
+ * +----------+ +----------+
+ * || ||
+ * +---------------------------+
+ * | ns-3 channel |
+ * +---------------------------+
+ *\endverbatim
+ *
+ * In this case, the ns-3 net device in the ghost node appears as a TAP device
+ * in the collection of virtual machines. The idea is that some existing
+ * configuration of virtual machines is created using an external mechanism
+ * such as OpenVZ or VMware. It is desired to have some subset of these VMs be
+ * connected to an ns-3 simulation. To accomplish this, there must be a TAP
+ * device created for each connection and the appropriate VM virtual network
+ * device bridged to the TAP device. The ns-3 simulation determines which TAP
+ * to associate with which ns-3 net device via the name of the TAP which is
+ * provided via ns-3 Attribute. Clearly there is considerably more
+ * manual configuration which needs to be done here, but the result is much
+ * more flexible.
+ *
+ * \subsection TapBridgeLocalDeviceMode TapBridge LocalDevice Mode
+ *
+ * In LocalDevice mode, the TapBridge and therefore its associated ns-3 net
+ * device 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 TAP device is done by the ns-3 simulation and no manual configuration
+ * is required. The IP addresses, MAC addresses, gateways, etc., for created
+ * TAP devices are extracted from the simulation itself by querying the
+ * configuration of the ns-3 device and the TapBridge Attributes.
*
* 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.
+ * This device must not have an IP address associated with it, but the bridged
+ * (ns-3) net device must have an IP adress. Be aware that this is the inverse
+ * of an ns-3 BridgeNetDevice which demands that its bridge ports not have IP
+ * addresses, but allows the bridge device itself 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.
+ * one TapBridge for each NetDevice that is being bridged. From the perspective
+ * of a simulation, the only difference between a ghost node and any other node
+ * will be the presence of the TapBridge devices. Note however, that the
+ * presence of the TapBridge does affect the connectivity of the net device to
+ * the IP stack of the ghost node.
+ *
+ * Configuration of address information and the ns-3 devices is not changed in
+ * any way if a TapBridge is present. A TapBridge will pick up the addressing
+ * information from the ns-3 net device to which it is connected (its "bridged"
+ * net device) and use that information to create and configure the TAP 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.
+ * standard ping utility on a real host to ping a simulated ns-3 node. If
+ * correct routes are added to the internet host (this is expected to be done
+ * automatically in future ns-3 releases), 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-wifi-dumbbell.cc in
+ * the ns-3 distribution.
+ *
+ * \subsection TapBridgeLocalDeviceModeOperation TapBridge LocalDevice Mode Operation
+ *
+ * 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. In LocalDevice mode, this TAP is
+ * automatically created by the ns-3 simulation. When the Linux host writes
+ * to one of these /dev/tap devices, the write is redirected into the TapBridge
+ * that lives in the ns-3 world; and from this perspective, the packet write on
+ * linux becomes a packet read. In other words, a Linux process writes a packet
+ * to a tap device and this packet is redirected by the network tap mechanism to
+ * an ns-3 process where it is received by the TapBridge as a result of a read
+ * operation there. The TapBridge then forwards the packet to the ns-3 net
+ * device to which it is bridged; and therefore it appears as if the Linux host
+ * sent a packet directly over an ns-3 net device.
+ *
+ * In the other direction, a packet received by an ns-3 net device is bridged
+ * (in the ns-3 sense) to the TapBridge. A packet sent to the ns-3 device then
+ * appears via a callback in the TapBridge. The TapBridge then takes that
+ * packet and writes it back to the host using the network tap mechanism. This
+ * write to the device will appear to the Linux host as if a packet has arrived
+ * on its device; and therefore as if a packet received by the ns-3 net device
+ * has appeared on the Linux net device.
+ *
+ * The upshot is that the Tap Bridge appears to bridge a tap device on a
+ * Linux host in the "real world" to an ns-3 net device in the simulation
+ * and make is appear that a ns-3 net device is actually installed in the
+ * Linux host. In order to do this on the ns-3 side, we need a "ghost
+ * node" in the simulation to hold the bridged ns-3 net device and the
+ * TapBridge. This node should not actually do anything else in the
+ * simulation since its job is simply to make the net device appear in
+ * Linux. This is not just arbitrary policy, it is because:
+ *
+ * - Bits sent to the Tap Bridge from higher layers in the ghost node (using
+ * the TapBridge Send() method) are completely ignored. The Tap Bridge is
+ * not, itself, connected to any network, neither in Linux nor in ns-3. You
+ * can never send nor receive data over a Tap Bridge from the ghost node.
+ *
+ * - The bridged ns-3 net device has its receive callback disconnected
+ * from the ns-3 node and reconnected to the Tap Bridge. All data received
+ * by a bridged device will then be sent to the Linux host and will not be
+ * received by the node. From the perspective of the ghost node, you can
+ * send over this device but you cannot ever receive.
*
+ * Of course, if you understand all of the issues you can take control of
+ * your own destiny and do whatever you want -- we do not actively
+ * prevent you from using the ghost node for anything you decide. You
+ * will be able to perform typical ns-3 operations on the ghost node if
+ * you so desire. The internet stack, for example, must be there and
+ * functional on that node in order to participate in IP address
+ * assignment and global routing. However, as mentioned above,
+ * interfaces talking any Tap Bridge or associated bridged net devices
+ * will not work completely. If you understand exactly what you are
+ * doing, you can set up other interfaces and devices on the ghost node
+ * and use them; or take advantage of the operational send side of the
+ * bridged devices to create traffic generators. We generally recommend
+ * that you treat this node as a ghost of the Linux host and leave it to
+ * itself, though.
+ *
+ * \subsection TapBridgeBridgedDeviceMode TapBridge BridgedDevice Mode
+ *
+ * In BridgedDevice mode, the TapBridge and its associated ns-3 net device are
+ * arranged in a fundamentally similar was as in LocalDevice mode. The bridging
+ * functionality is also accomplished in a fundamentally similar way. The
+ * previous description applies except as noted below.
+ *
+ * The most user-visible difference in modes is how the creation and
+ * configuration of the underlying TAP device is done. In LocalDevice mode,
+ * both creation and configuration of the underlying TAP device are handled
+ * completely by ns-3. In BridgedDevice mode, creation and configuration is
+ * delegated (due to requirements) to the user. No configuration is done in
+ * ns-3 other than settting the operating mode of the TapBridge to
+ * "BridgedDevice" and specifying the name of the pre-configured TAP device,
+ * both via ns-3 Attributes of the TapBridge.
+ *
+ * Functionally, the primary difference between modes is due to the fact that
+ * MAC addresses of the TAPs will be pre-configured and will therefore be
+ * different than those in the bridged device. This necessitates spoofing
+ * MAC addresses in the ns-3 to TAP direction.
+ *
+ * \subsection TapBridgeBridgedDeviceModeOperation TapBridge BridgedDevice Mode Operation
+ *
+ * As described in the LocalDevice mode section, when the Linux host writes to
+ * one of the /dev/tap devices, the write is redirected into the TapBridge
+ * that lives in the ns-3 world; and from this perspective, the packet write on
+ * linux becomes a packet read. The packet at this point will contain a MAC
+ * source address corresponding to the address of the TAP device. Before this
+ * packet is sent to the bridged ns-3 net device, the MAC headers are stripped
+ * off. When the bridged net device actually executes the send, it will replace
+ * the MAC headers with its own.
+ *
+ * In the other direction, a packet received by an ns-3 net device is bridged
+ * (in the ns-3 sense) to the TapBridge. A packet sent to the ns-3 device then
+ * appears via a callback in the TapBridge. At this point, there is no MAC
+ * addressing information on the packet. In LocalDevice mode, the TapBridge
+ * adds back the MAC address that it found in the ns-3 bridged net device
+ * configuration. In the BridgedDevice mode, it needs to add back the MAC
+ * address of the TAP device. So the main difference is that the TapBridge
+ * learns the MAC address of the TAP device from received packets instead of
+ * learning it from the ns-3 device configuration.
+ *
* \section TapBridgeChannelModel Tap Bridge Channel Model
*
* There is no channel model associated with the Tap Bridge. In fact, the