initial modifications to tap-bridge

This commit is contained in:
Unknown
2009-03-21 15:40:49 -07:00
parent 3eff196614
commit a0f8fdbfcc
6 changed files with 118 additions and 64 deletions

View File

@@ -80,22 +80,22 @@ TapBridge::GetTypeId (void)
MakeStringAccessor (&TapBridge::m_tapDeviceName),
MakeStringChecker ())
.AddAttribute ("Gateway",
"The IP address of the default gateway to assign to the tap device.",
"The IP address of the default gateway to assign to the host machine, when in ConfigureLocal mode.",
Ipv4AddressValue ("255.255.255.255"),
MakeIpv4AddressAccessor (&TapBridge::m_tapGateway),
MakeIpv4AddressChecker ())
.AddAttribute ("IpAddress",
"The IP address to assign to the tap device.",
"The IP address to assign to the tap device, when in ConfigureLocal mode.",
Ipv4AddressValue ("255.255.255.255"),
MakeIpv4AddressAccessor (&TapBridge::m_tapIp),
MakeIpv4AddressChecker ())
.AddAttribute ("MacAddress",
"The MAC address to assign to the tap device.",
"The MAC address to assign to the tap device, when in ConfigureLocal mode.",
Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
MakeMac48AddressAccessor (&TapBridge::m_tapMac),
MakeMac48AddressChecker ())
.AddAttribute ("Netmask",
"The network mask to assign to the tap device.",
"The network mask to assign to the tap device, when in ConfigureLocal mode.",
Ipv4MaskValue ("255.255.255.255"),
MakeIpv4MaskAccessor (&TapBridge::m_tapNetmask),
MakeIpv4MaskChecker ())
@@ -110,11 +110,12 @@ TapBridge::GetTypeId (void)
MakeTimeAccessor (&TapBridge::m_tStop),
MakeTimeChecker ())
.AddAttribute ("Mode",
"The operating and configuration mode (LocalDevice or BridgedDevice) to use.",
EnumValue (LOCAL_DEVICE),
"The operating and configuration mode to use.",
EnumValue (USE_LOCAL),
MakeEnumAccessor (&TapBridge::SetMode),
MakeEnumChecker (LOCAL_DEVICE, "LocalDevice",
BRIDGED_DEVICE, "BridgedDevice"))
MakeEnumChecker (CONFIGURE_LOCAL, "ConfigureLocal",
USE_LOCAL, "UseLocal",
USE_BRIDGE, "UseBridge"))
;
return tid;
}
@@ -126,7 +127,8 @@ TapBridge::TapBridge ()
m_sock (-1),
m_startEvent (),
m_stopEvent (),
m_readThread (0)
m_readThread (0),
m_learnedMac (Mac48Address ("ff:ff:ff:ff:ff:ff"))
{
NS_LOG_FUNCTION_NOARGS ();
Start (m_tStart);
@@ -222,20 +224,20 @@ TapBridge::CreateTap (void)
//
// 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
// network tap that we use. In ConfigureLocal mode, the TapBridge has the
// responsibility for creating and configuring the TAP.
//
// In BridgedDevice mode, the user will provide us a configuration and we have
// In UseBridge mode, the user will provide us a configuration and we have
// to adapt to it. For example, the user will do something like:
//
// 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
//
// set the "Mode" Attribute to "BridgedDevice" and the "DeviceName" Attribute
// set the "Mode" Attribute to "UseBridge" and the "DeviceName" Attribute
// to "tap0" in this case.
//
// In LocalDevice mode, we will do the configuration and create a TAP with
// In ConfigureLocal 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
@@ -296,7 +298,7 @@ TapBridge::CreateTap (void)
// -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)
// -o<operating mode> The operating mode of the bridge (1=ConfigureLocal, 2=UseLocal, 3=UseBridge)
// -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 -o1 -pblah
@@ -381,14 +383,18 @@ TapBridge::CreateTap (void)
std::ostringstream ossMode;
ossMode << "-o";
if (m_mode == LOCAL_DEVICE)
if (m_mode == CONFIGURE_LOCAL)
{
ossMode << "1";
}
else
else if (m_mode == USE_LOCAL)
{
ossMode << "2";
}
else
{
ossMode << "3";
}
std::ostringstream ossPath;
ossPath << "-p" << path;
@@ -590,11 +596,12 @@ TapBridge::ReadThread (void)
uint32_t bufferSize = 65536;
uint8_t *buf = (uint8_t *)malloc (bufferSize);
NS_ABORT_MSG_IF (buf == 0, "TapBridge::ReadThread(): malloc packet buffer failed");
NS_LOG_LOGIC ("Calling read on tap device socket fd");
NS_LOG_LOGIC ("Calling read on tap device socket fd " << m_sock);
len = read (m_sock, buf, bufferSize);
if (len == -1)
{
NS_LOG_INFO ("TapBridge::ReadThread(): Returning");
free (buf);
buf = 0;
return;
@@ -603,13 +610,13 @@ TapBridge::ReadThread (void)
NS_LOG_INFO ("TapBridge::ReadThread(): Received packet");
NS_LOG_INFO ("TapBridge::ReadThread(): Scheduling handler");
DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->ScheduleRealtimeNow (
MakeEvent (&TapBridge::ForwardToBridgedDevice, this, buf, len));
MakeEvent (&TapBridge::ForwardToSimDevice, this, buf, len));
buf = 0;
}
}
void
TapBridge::ForwardToBridgedDevice (uint8_t *buf, uint32_t len)
TapBridge::ForwardToSimDevice (uint8_t *buf, uint32_t len)
{
NS_LOG_FUNCTION (buf << len);
@@ -641,10 +648,22 @@ TapBridge::ForwardToBridgedDevice (uint8_t *buf, uint32_t len)
NS_LOG_LOGIC ("Pkt source is " << src);
NS_LOG_LOGIC ("Pkt destination is " << dst);
NS_LOG_LOGIC ("Pkt LengthType is " << type);
if (m_mode == USE_LOCAL)
{
// Should not be a broadcast src
NS_ASSERT_MSG (Mac48Address::ConvertFrom (src) != Mac48Address ("ff:ff:ff:ff:ff:ff"), "TapBridge::ForwardToSimDevice: Source addr is broadcast");
m_learnedMac = Mac48Address::ConvertFrom (src);
NS_LOG_LOGIC ("Learned MacAddr is " << m_learnedMac);
// If we are operating in USE_LOCAL mode, we may be attached to an ns-3
// bridging or non-bridging NetDevice. We use the generic Send() method.
NS_LOG_LOGIC ("Forwarding packet");
m_bridgedDevice->Send (packet, dst, type);
return;
}
//
// If we are operating in BRIDGED_DEVICE mode, we have the situation described
// below:
// If we are operating in USE_BRIDGE mode, we have the
// situation described below:
//
// Other Device <--> Tap Device <--> ns3 device
// Mac Addr A Mac Addr B Mac Addr C
@@ -657,14 +676,14 @@ TapBridge::ForwardToBridgedDevice (uint8_t *buf, uint32_t len)
// (modulo learning behavior) sent out to "Other Device." This makes it
// appear as if both devices are on a single subnet.
//
// In BRIDGED_DEVICE mode, we want to logically extend this Linux behavior
// In USE_BRIDGE mode, we want to logically extend this Linux behavior
// to the ns3 device and make it appear as if it is connected to the Linux
// subnet. As you may expect, this means that we need to act like a real
// bridge and do what is described above. The code here will do the
// equivalent of a SendFrom on "ns3 Device" of the bits received on
// "Tap Device"
//
// If we are operating in LOCAL_DEVICE mode, we simply simply take all packets
// If we are operating in CONFIGURE_LOCAL mode, we simply simply take all packets
// that come from "Tap Device" and ask "ns3 Device" to send them down its
// directly connected network. To to this, we just need to remove the
// Ethernet header (which was done for us by the Filter () method), and then
@@ -677,16 +696,15 @@ TapBridge::ForwardToBridgedDevice (uint8_t *buf, uint32_t len)
// what to do if the bridged device does not support SendFrom, which will be
// the case for Wifi STA nodes.
//
NS_LOG_LOGIC ("Forwarding packet");
if (m_bridgedDevice->SupportsSendFrom ())
if (m_mode == USE_BRIDGE)
{
m_bridgedDevice->SendFrom (packet, src, dst, type);
}
else
{
NS_FATAL_ERROR ("TapBridge::ForwardToBridgedDevice(): Bridged device does not support SendFrom");
m_bridgedDevice->Send (packet, dst, type);
}
}
@@ -698,7 +716,7 @@ TapBridge::Filter (Ptr<Packet> p, Address *src, Address *dst, uint16_t *type)
//
// We have a candidate packet for injection into ns-3. We expect that since
// it came over a socket that provides Ethernet packets, it sould be big
// it came over a socket that provides Ethernet packets, it should be big
// enough to hold an EthernetHeader. If it can't, we signify the packet
// should be filtered out by returning 0.
//
@@ -772,7 +790,7 @@ TapBridge::SetBridgedNetDevice (Ptr<NetDevice> bridgedDevice)
NS_FATAL_ERROR ("TapBridge::SetBridgedDevice: Device does not support eui 48 addresses: cannot be added to bridge.");
}
if (!bridgedDevice->SupportsSendFrom ())
if (m_mode == USE_BRIDGE && !bridgedDevice->SupportsSendFrom ())
{
NS_FATAL_ERROR ("TapBridge::SetBridgedDevice: Device does not support SendFrom: cannot be added to bridge.");
}
@@ -781,12 +799,12 @@ TapBridge::SetBridgedNetDevice (Ptr<NetDevice> bridgedDevice)
// Tell the bridged device to forward its received packets here. We use the
// promiscuous mode hook to get both the source and destination addresses.
//
m_node->RegisterProtocolHandler (MakeCallback (&TapBridge::ReceiveFromBridgedDevice, this), 0, bridgedDevice, true);
m_node->RegisterProtocolHandler (MakeCallback (&TapBridge::ReceiveFromSimDevice, this), 0, bridgedDevice, true);
m_bridgedDevice = bridgedDevice;
}
void
TapBridge::ReceiveFromBridgedDevice (
TapBridge::ReceiveFromSimDevice (
Ptr<NetDevice> device,
Ptr<const Packet> packet,
uint16_t protocol,
@@ -799,11 +817,33 @@ TapBridge::ReceiveFromBridgedDevice (
NS_LOG_DEBUG ("Packet UID is " << packet->GetUid ());
if (m_mode == CONFIGURE_LOCAL && packetType == PACKET_OTHERHOST)
{
// We hooked the promiscuous mode protocol handler so we could get the
// destination address of the actual packet. This means we will be
// getting PACKET_OTHERHOST packets (not broadcast, not multicast, not
// unicast to the ns-3 net device, but to some other address). In
// CONFIGURE_LOCAL mode we are not interested in these packets since they
// don't refer to the single MAC address shared by the ns-3 device and
// the TAP device. If, however, we are in USE_LOCAL or USE_BRIDGE mode,
// we want to act like a bridge and forward these
// PACKET_OTHERHOST packets.
return;
}
Mac48Address from = Mac48Address::ConvertFrom (src);
Mac48Address to = Mac48Address::ConvertFrom (dst);
Mac48Address to;
if (m_mode == USE_LOCAL)
{
to = Mac48Address::ConvertFrom (m_learnedMac);
}
else
{
to = Mac48Address::ConvertFrom (dst);
}
//
// If we are operating in BRIDGED_DEVICE mode, we have the situation described
// If we are operating in USE_BRIDGE mode, we have the situation described
// below:
//
// Other Device <--> Tap Device <--> ns3 device
@@ -817,14 +857,14 @@ TapBridge::ReceiveFromBridgedDevice (
// (modulo learning behavior) sent out to "Other Device." This makes it
// appear as if both devices are on a single subnet.
//
// In BRIDGED_DEVICE mode, we want to logically extend this Linux behavior
// In USE_BRIDGE mode, we want to logically extend this Linux behavior
// to the ns3 device and make it appear as if it is connected to the Linux
// subnet. As you may expect, this means that we need to act like a real
// bridge and do what is described above. The code here will do the
// equivalent of a SendFrom on the "Tap Device" of the bits received on the
// ns-3 device.
//
// If we are operating in LOCAL_DEVICE mode, we simply simply take all packets
// If we are operating in CONFIGURE_LOCAL mode, we simply simply take all packets
// that would normally be received by the device and forward them to the TAP
// device as if the ns-3 net device was never there. To to this, we just need
// to reconstruct an Ethernet header and add the original source and
@@ -835,19 +875,6 @@ TapBridge::ReceiveFromBridgedDevice (
// even though they seem quite different at first glance.
//
if (m_mode == LOCAL_DEVICE && packetType == PACKET_OTHERHOST)
{
// We hooked the promiscuous mode protocol handler so we could get the
// destination address of the actual packet. This means we will be
// getting PACKET_OTHERHOST packets (not broadcast, not multicast, not
// unicast to the ns-3 net device, but to some other address). In
// LOCAL_DEVICE mode we are not interested in these packets since they
// don't refer to the single MAC address shared by the ns-3 device and
// the TAP device. If, however, we are in BRIDGED_DEVICE mode, we want
// to act like a bridge and forward these PACKET_OTHERHOST packets.
return;
}
//
// We have received a packet from the ns-3 net device that has been associated
// with this bridge. We want to take these bits and send them off to the
@@ -873,7 +900,7 @@ TapBridge::ReceiveFromBridgedDevice (
NS_LOG_LOGIC ("Pkt size is " << p->GetSize ());
uint32_t bytesWritten = write (m_sock, p->PeekData (), p->GetSize ());
NS_ABORT_MSG_IF (bytesWritten != p->GetSize (), "TapBridge::ReceiveFromBridgedDevice(): Write error.");
NS_ABORT_MSG_IF (bytesWritten != p->GetSize (), "TapBridge::ReceiveFromSimDevice(): Write error.");
}
void

View File

@@ -105,8 +105,9 @@ public:
*/
enum Mode {
ILLEGAL, /**< mode not set */
LOCAL_DEVICE, /**< ns-3 creates and configures TAP device */
BRIDGED_DEVICE, /**< user creates and configures TAP */
CONFIGURE_LOCAL, /**< ns-3 creates and configures tap device */
USE_LOCAL, /**< ns-3 uses a pre-created tap, without configuring it */
USE_BRIDGE, /**< ns-3 uses a pre-created tap, and bridges to a bridging net device */
};
TapBridge ();
@@ -209,7 +210,7 @@ protected:
*/
virtual void DoDispose (void);
void ReceiveFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
void ReceiveFromSimDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
Address const &src, Address const &dst, PacketType packetType);
private:
@@ -264,7 +265,7 @@ private:
* received from the host.
* \param buf The length of the buffer.
*/
void ForwardToBridgedDevice (uint8_t *buf, uint32_t len);
void ForwardToSimDevice (uint8_t *buf, uint32_t len);
/**
* \internal
@@ -426,18 +427,11 @@ private:
/**
* \internal
*
* 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
* The MAC address to use as the hardware address on the host; only used
* in UseLocal 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;
@@ -454,6 +448,17 @@ private:
* The ns-3 net device to which we are bridging.
*/
Ptr<NetDevice> m_bridgedDevice;
/**
* \internal
*
* The MAC address of the local tap device is stored in this variable.
* When in UseLocal mode, this address is added back to the destination
* Mac address for frames destined to the tap device. It is learned from
* the first frame sent from the host to the TapBridge device. In the
* other modes of this device, this value is unused.
*/
Mac48Address m_learnedMac;
};
} // namespace ns3

View File

@@ -39,7 +39,7 @@
#define TAP_MAGIC 95549
static int gVerbose = 0; // Set to true to turn on logging messages.
static int gVerbose = 1; // Set to true to turn on logging messages.
#define LOG(msg) \
if (gVerbose) \
@@ -295,13 +295,15 @@ CreateTap (const char *dev, const char *gw, const char *ip, const char *mac, con
LOG ("Allocated TAP device " << tapDeviceName);
//
// Operating mode "2" corresponds to BRIDGED_DEVICE mode. This means that
// Operating mode "2" corresponds to USE_LOCAL and "3" to USE_BRIDGE 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)
if (strcmp (mode, "2") == 0 || strcmp (mode, "3") == 0)
{
LOG ("Returning precreated tap ");
return tap;
}

View File

@@ -27,6 +27,7 @@ def build(bld):
module.source.extend([
'tap-bridge.cc',
'tap-encode-decode.cc',
'tap-creator.cc',
])
headers.source.extend([
'tap-bridge.h',

View File

@@ -18,6 +18,7 @@
#include "ns3/log.h"
#include "ns3/node.h"
#include "ns3/enum.h"
#include "ns3/tap-bridge.h"
#include "ns3/names.h"
#include "tap-bridge-helper.h"
@@ -26,11 +27,18 @@ NS_LOG_COMPONENT_DEFINE ("TapBridgeHelper");
namespace ns3 {
TapBridgeHelper::TapBridgeHelper ()
{
NS_LOG_FUNCTION_NOARGS ();
m_deviceFactory.SetTypeId ("ns3::TapBridge");
}
TapBridgeHelper::TapBridgeHelper (Ipv4Address gateway)
{
NS_LOG_FUNCTION_NOARGS ();
m_deviceFactory.SetTypeId ("ns3::TapBridge");
SetAttribute ("Gateway", Ipv4AddressValue (gateway));
SetAttribute ("Mode", EnumValue(TapBridge::CONFIGURE_LOCAL));
}
void
@@ -41,6 +49,14 @@ TapBridgeHelper::SetAttribute (std::string n1, const AttributeValue &v1)
}
Ptr<NetDevice>
TapBridgeHelper::Install (Ptr<Node> node, Ptr<NetDevice> nd, const AttributeValue &v1)
{
NS_LOG_FUNCTION (node << nd << &v1);
m_deviceFactory.Set ("DeviceName", v1);
return Install (node, nd);
}
Ptr<NetDevice>
TapBridgeHelper::Install (Ptr<Node> node, Ptr<NetDevice> nd)
{

View File

@@ -21,6 +21,7 @@
#include "net-device-container.h"
#include "ns3/object-factory.h"
#include "ns3/tap-bridge.h"
#include <string>
namespace ns3 {
@@ -31,12 +32,14 @@ class AttributeValue;
class TapBridgeHelper
{
public:
TapBridgeHelper ();
TapBridgeHelper (Ipv4Address gateway);
void SetAttribute (std::string n1, const AttributeValue &v1);
Ptr<NetDevice> Install (Ptr<Node> node, Ptr<NetDevice> nd);
Ptr<NetDevice> Install (std::string nodeName, Ptr<NetDevice> nd);
Ptr<NetDevice> Install (Ptr<Node> node, std::string ndName);
Ptr<NetDevice> Install (std::string nodeName, std::string ndName);
Ptr<NetDevice> Install (Ptr<Node> node, Ptr<NetDevice> nd, const AttributeValue &v1);
private:
ObjectFactory m_deviceFactory;
};