wire needed values into tap-bridge Attribute system, but figure out as many as possible in the default case
--- a/examples/csma-tap-bridge.cc Tue Jan 27 22:00:29 2009 -0800
+++ b/examples/csma-tap-bridge.cc Thu Jan 29 11:53:12 2009 -0800
@@ -20,6 +20,7 @@
// | external | | external |
// | Linux | | Linux |
// | Host | | Host |
+// | "left" | | "right" |
// +----------+ +----------+
// | n0 n3 |
// | +--------+ +--------+ |
@@ -91,34 +92,59 @@
internet.Install (nodes);
//
- // Add the tap bridges to nodes zero and one to enable external Linux
- // processes to talk to the CSMA devices.
+ // We've got the "hardware" in place. Now add IP addresses.
//
- TapBridgeHelper bridge;
- NetDeviceContainer bridgeDevices;
- bridgeDevices.Add (bridge.Install (nodes.Get (0), devices.Get (0)));
- bridgeDevices.Add (bridge.Install (nodes.Get (3), devices.Get (3)));
+ NS_LOG_INFO ("Assign IP Addresses.");
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
//
- // We've got the "hardware" in place. Now add IP addresses. We mjust not
- // add IP addresses to the devices that we bridged using the TapBridgeHelper
- // above. The IP addresses are added to the bridge itself and are propagated
- // to the tap device on the host. We do need to add IP addresses to the CSMA
- // devices that are attached to the nodes that are entirely contained within
- // the simulation (not connected to any other external host).
+ // 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));
+
//
- NS_LOG_INFO ("Assign IP Addresses.");
- NetDeviceContainer ndc;
- ndc.Add (bridgeDevices.Get (0));
- ndc.Add (devices.Get (1));
- ndc.Add (devices.Get (2));
- ndc.Add (bridgeDevices.Get (0));
-
- Ipv4AddressHelper ipv4;
- ipv4.SetBase ("10.1.1.0", "255.255.255.0");
- Ipv4InterfaceContainer interfaces = ipv4.Assign (ndc);
+ // 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));
-#if 1
+ //
+ // 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));
+
+#if 0
//
// Testing only -- send a packet from an internal node to an external node
//
--- a/src/devices/tap-bridge/tap-bridge.cc Tue Jan 27 22:00:29 2009 -0800
+++ b/src/devices/tap-bridge/tap-bridge.cc Thu Jan 29 11:53:12 2009 -0800
@@ -27,6 +27,7 @@
#include "ns3/log.h"
#include "ns3/boolean.h"
#include "ns3/string.h"
+#include "ns3/ipv4.h"
#include "ns3/simulator.h"
#include "ns3/realtime-simulator-impl.h"
#include "ns3/system-thread.h"
@@ -64,26 +65,26 @@
StringValue (""),
MakeStringAccessor (&TapBridge::m_tapDeviceName),
MakeStringChecker ())
- .AddAttribute ("TapGateway",
+ .AddAttribute ("Gateway",
"The IP address of the default gateway to assign to the tap device.",
- StringValue (""),
- MakeStringAccessor (&TapBridge::m_tapGateway),
- MakeStringChecker ())
- .AddAttribute ("TapIp",
+ Ipv4AddressValue ("255.255.255.255"),
+ MakeIpv4AddressAccessor (&TapBridge::m_tapGateway),
+ MakeIpv4AddressChecker ())
+ .AddAttribute ("IpAddress",
"The IP address to assign to the tap device.",
- StringValue (""),
- MakeStringAccessor (&TapBridge::m_tapIp),
- MakeStringChecker ())
- .AddAttribute ("TapMac",
+ Ipv4AddressValue ("255.255.255.255"),
+ MakeIpv4AddressAccessor (&TapBridge::m_tapIp),
+ MakeIpv4AddressChecker ())
+ .AddAttribute ("MacAddress",
"The MAC address to assign to the tap device.",
- StringValue (""),
- MakeStringAccessor (&TapBridge::m_tapMac),
- MakeStringChecker ())
- .AddAttribute ("TapNetmask",
+ Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
+ MakeMac48AddressAccessor (&TapBridge::m_tapMac),
+ MakeMac48AddressChecker ())
+ .AddAttribute ("Netmask",
"The network mask to assign to the tap device.",
- StringValue (""),
- MakeStringAccessor (&TapBridge::m_tapMac),
- MakeStringChecker ())
+ Ipv4MaskValue ("255.255.255.255"),
+ MakeIpv4MaskAccessor (&TapBridge::m_tapNetmask),
+ MakeIpv4MaskChecker ())
.AddAttribute ("Start",
"The simulation time at which to spin up the tap device read thread.",
TimeValue (Seconds (0.)),
@@ -114,6 +115,7 @@
TapBridge::~TapBridge()
{
NS_LOG_FUNCTION_NOARGS ();
+ m_bridgedDevice = 0;
}
void
@@ -265,7 +267,7 @@
// build a command line argument from the encoded endpoint string that
// the socket creation process will use to figure out how to respond to
// the (now) parent process. We're going to have to give this program
- // quite a bit of information and we use program arguments to do so.
+ // quite a bit of information.
//
// -d<device-name> The name of the tap device we want to create;
// -g<gateway-address> The IP address to use as the default gateway;
@@ -276,9 +278,81 @@
//
// Example tap-sock-creator -dnewdev -g1.2.3.2 -i1.2.3.1 -m08:00:2e:00:01:23 -n255.255.255.0 -pblah
//
+ // We want to get as much of this stuff automagically as possible.
+ //
+ // <IP-address> is the IP address we are going to set in the newly
+ // created Tap device on the Linux host. At the point in the simulation
+ // where devices are coming up, we should have all of our IP addresses
+ // assigned. That means that we can find the IP address to assign to
+ // the new Tap device from the IP address associated with the bridged
+ // net device.
+ //
+ Ptr<NetDevice> nd = GetBridgedNetDevice ();
+ Ptr<Node> n = nd->GetNode ();
+ Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> ();
+ uint32_t index = ipv4->FindInterfaceForDevice (nd);
+ Ipv4Address ipv4Address = ipv4->GetAddress (index);
+
+ //
+ // The net mask is sitting right there next to the ipv4 address.
+ //
+ Ipv4Mask ipv4Mask = ipv4->GetNetworkMask (index);
+
+ //
+ // The MAC address should also already be assigned and waiting for us in
+ // the bridged net device.
+ //
+ Address address = nd->GetAddress ();
+ Mac48Address mac48Address = Mac48Address::ConvertFrom (address);
+
+ //
+ // The device-name is something we may want the system to make up in
+ // every case. We also rely on it being configured via an Attribute
+ // through the helper. By default, it is set to the empty string
+ // which tells the system to make up a device name such as "tap123".
+ //
std::ostringstream oss;
- oss << "-d" << m_tapDeviceName << " -g" << m_tapGateway << " -i" << m_tapIp << " -m" << m_tapMac
- << " -n" << m_tapNetmask << " -p" << path;
+ oss << "-d" << m_tapDeviceName;
+
+ //
+ // The gateway-address is something we can't derive, so we rely on it
+ // being configured via an Attribute through the helper.
+ //
+ oss << " -g" << m_tapGateway;
+
+ //
+ // For flexibility, we do allow a client to override any of the values
+ // above via attributes, so only use our found values if the Attribute
+ // is not equal to its default value (empty string or broadcast address).
+ //
+ if (m_tapIp.IsBroadcast ())
+ {
+ oss << " -i" << ipv4Address;
+ }
+ else
+ {
+ oss << " -i" << m_tapIp;
+ }
+
+ if (m_tapMac.IsBroadcast ())
+ {
+ oss << " -m" << mac48Address;
+ }
+ else
+ {
+ oss << " -m" << m_tapMac;
+ }
+
+ if (m_tapNetmask.IsEqual (Ipv4Mask::GetOnes ()))
+ {
+ oss << " -n" << ipv4Mask;
+ }
+ else
+ {
+ oss << " -n" << m_tapNetmask;
+ }
+
+ oss << " -p" << path;
NS_LOG_INFO ("creator arguments set to \"" << oss.str () << "\"");
//
@@ -514,8 +588,15 @@
m_bridgedDevice->SendFrom (packet, header.GetSource (), header.GetDestination (), 0x800);
}
+Ptr<NetDevice>
+TapBridge::GetBridgedNetDevice (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_bridgedDevice;
+}
+
void
-TapBridge::SetBridgedDevice (Ptr<NetDevice> bridgedDevice)
+TapBridge::SetBridgedNetDevice (Ptr<NetDevice> bridgedDevice)
{
NS_LOG_FUNCTION_NOARGS ();
--- a/src/devices/tap-bridge/tap-bridge.h Tue Jan 27 22:00:29 2009 -0800
+++ b/src/devices/tap-bridge/tap-bridge.h Thu Jan 29 11:53:12 2009 -0800
@@ -77,7 +77,12 @@
TapBridge ();
virtual ~TapBridge ();
- /** \brief Set the device to bridge.
+ /** \brief Get the bridged net device.
+ * \returns the bridged net device.
+ */
+ Ptr<NetDevice> GetBridgedNetDevice (void);
+
+ /** \brief Set the ns-3 net device to bridge.
*
* This method tells the bridge which ns-3 net device it should use to connect
* the simulation side of the bridge.
@@ -85,7 +90,7 @@
* \attention The ns-3 net device that is being set as the device must not
* have an IP address. This address is a property of the host Linux device.
*/
- void SetBridgedDevice (Ptr<NetDevice> bridgedDevice);
+ void SetBridgedNetDevice (Ptr<NetDevice> bridgedDevice);
/**
* Set a start time for the device.
@@ -189,10 +194,10 @@
Time m_tStop;
std::string m_tapDeviceName;
- std::string m_tapGateway;
- std::string m_tapIp;
- std::string m_tapMac;
- std::string m_tapNetmask;
+ Ipv4Address m_tapGateway;
+ Ipv4Address m_tapIp;
+ Mac48Address m_tapMac;
+ Ipv4Mask m_tapNetmask;
Ptr<NetDevice> m_bridgedDevice;
};
--- a/src/helper/tap-bridge-helper.cc Tue Jan 27 22:00:29 2009 -0800
+++ b/src/helper/tap-bridge-helper.cc Thu Jan 29 11:53:12 2009 -0800
@@ -25,14 +25,15 @@
namespace ns3 {
-TapBridgeHelper::TapBridgeHelper ()
+TapBridgeHelper::TapBridgeHelper (Ipv4Address gateway)
{
NS_LOG_FUNCTION_NOARGS ();
m_deviceFactory.SetTypeId ("ns3::TapBridge");
+ SetAttribute ("Gateway", Ipv4AddressValue (gateway));
}
void
-TapBridgeHelper::SetDeviceAttribute (std::string n1, const AttributeValue &v1)
+TapBridgeHelper::SetAttribute (std::string n1, const AttributeValue &v1)
{
NS_LOG_FUNCTION (n1 << &v1);
m_deviceFactory.Set (n1, v1);
@@ -46,7 +47,7 @@
Ptr<TapBridge> bridge = m_deviceFactory.Create<TapBridge> ();
node->AddDevice (bridge);
- bridge->SetBridgedDevice (nd);
+ bridge->SetBridgedNetDevice (nd);
return bridge;
}
--- a/src/helper/tap-bridge-helper.h Tue Jan 27 22:00:29 2009 -0800
+++ b/src/helper/tap-bridge-helper.h Thu Jan 29 11:53:12 2009 -0800
@@ -31,8 +31,8 @@
class TapBridgeHelper
{
public:
- TapBridgeHelper ();
- void SetDeviceAttribute (std::string n1, const AttributeValue &v1);
+ TapBridgeHelper (Ipv4Address gateway);
+ void SetAttribute (std::string n1, const AttributeValue &v1);
Ptr<NetDevice> Install (Ptr<Node> node, Ptr<NetDevice> nd);
private:
ObjectFactory m_deviceFactory;