Finally make tap bridge work with VMs (bug 569)

This commit is contained in:
Craig Dowell
2009-06-23 22:12:35 -07:00
parent c3b6466263
commit 6e8b7012e7
22 changed files with 116 additions and 121 deletions

View File

@@ -227,7 +227,7 @@ main (int argc, char *argv[])
apps = sink.Install (nodesRight.Get (0));
apps.Start (Seconds (1.0));
CsmaHelper::EnablePcapAll ("tap-dumbbell", false);
CsmaHelper::EnablePcapAll ("tap-wifi-dumbbell", false);
GlobalRouteManager::PopulateRoutingTables ();
Simulator::Stop (Seconds (60.));

View File

@@ -278,6 +278,13 @@ BridgeNetDevice::GetChannel (void) const
return m_channel;
}
void
BridgeNetDevice::SetAddress (Address address)
{
NS_LOG_FUNCTION_NOARGS ();
m_address = Mac48Address::ConvertFrom (address);
}
Address
BridgeNetDevice::GetAddress (void) const
{

View File

@@ -91,6 +91,7 @@ public:
virtual void SetIfIndex(const uint32_t index);
virtual uint32_t GetIfIndex(void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);
virtual uint16_t GetMtu (void) const;

View File

@@ -321,13 +321,6 @@ CsmaNetDevice::GetFrameSize (void) const
return m_frameSize;
}
void
CsmaNetDevice::SetAddress (Mac48Address self)
{
NS_LOG_FUNCTION (self);
m_address = self;
}
void
CsmaNetDevice::SetSendEnable (bool sendEnable)
{
@@ -875,6 +868,13 @@ CsmaNetDevice::GetChannel (void) const
return m_channel;
}
void
CsmaNetDevice::SetAddress (Address address)
{
NS_LOG_FUNCTION_NOARGS ();
m_address = Mac48Address::ConvertFrom (address);
}
Address
CsmaNetDevice::GetAddress (void) const
{

View File

@@ -182,13 +182,6 @@ public:
*/
void SetReceiveEnable (bool enable);
/**
* Set the MAC address of the the network device.
*
* \param addr The Mac48Address to use as the address of the device.
*/
void SetAddress (Mac48Address addr);
/**
* Set The max frame size of packets sent over this device.
*
@@ -310,6 +303,7 @@ public:
virtual Ptr<Channel> GetChannel (void) const;
virtual bool SetMtu (const uint16_t mtu);
virtual uint16_t GetMtu (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool IsLinkUp (void) const;
virtual void SetLinkChangeCallback (Callback<void> callback);

View File

@@ -876,10 +876,10 @@ EmuNetDevice::GetChannel (void) const
}
void
EmuNetDevice::SetAddress (Mac48Address addr)
EmuNetDevice::SetAddress (Address address)
{
NS_LOG_FUNCTION (addr);
m_address = addr;
NS_LOG_FUNCTION (address);
m_address = Mac48Address::ConvertFrom (address);
}
Address

View File

@@ -94,14 +94,6 @@ public:
*/
void SetQueue (Ptr<Queue> queue);
/**
* Assign a MAC address to this device.
*
* @see Mac48Address
* @param addr The new address.
*/
void SetAddress (Mac48Address addr);
//
// Pure virtual methods inherited from NetDevice we must implement.
//
@@ -109,6 +101,8 @@ public:
virtual uint32_t GetIfIndex(void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);

View File

@@ -395,10 +395,11 @@ PointToPointNetDevice::GetChannel (void) const
// information. However, the base class NetDevice wants us to define the
// methods to get and set the address. Rather than be rude and assert, we let
// clients get and set the address, but simply ignore them.
void
PointToPointNetDevice::SetAddress (Mac48Address addr)
PointToPointNetDevice::SetAddress (Address address)
{
m_address = addr;
m_address = Mac48Address::ConvertFrom (address);
}
Address

View File

@@ -131,14 +131,6 @@ public:
*/
void Receive (Ptr<Packet> p);
/**
* Assign a MAC address to this device.
*
* @see Mac48Address
* @param addr The new address.
*/
void SetAddress (Mac48Address addr);
/**
* Set The max frame size of packets sent over this device.
*
@@ -230,6 +222,8 @@ public:
virtual uint32_t GetIfIndex(void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);

View File

@@ -131,7 +131,7 @@ TapBridge::TapBridge ()
m_startEvent (),
m_stopEvent (),
m_readThread (0),
m_learnedMac (Mac48Address ("ff:ff:ff:ff:ff:ff"))
m_ns3AddressRewritten (false)
{
NS_LOG_FUNCTION_NOARGS ();
Start (m_tStart);
@@ -641,7 +641,7 @@ TapBridge::ReadThread (void)
return;
}
NS_LOG_INFO ("TapBridge::ReadThread(): Received packet");
NS_LOG_INFO ("TapBridge::ReadThread(): Received packet on node " << m_node->GetId ());
NS_LOG_INFO ("TapBridge::ReadThread(): Scheduling handler");
DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->ScheduleRealtimeNow (
MakeEvent (&TapBridge::ForwardToBridgedDevice, this, buf, len));
@@ -713,21 +713,21 @@ TapBridge::ForwardToBridgedDevice (uint8_t *buf, uint32_t len)
//
NS_ASSERT_MSG (Mac48Address::ConvertFrom (src) != Mac48Address ("ff:ff:ff:ff:ff:ff"),
"TapBridge::ForwardToBridgedDevice: Source addr is broadcast");
//
// Remember the Mac address since we are going to spoof it when we go
// the other way.
//
m_learnedMac = Mac48Address::ConvertFrom (src);
NS_LOG_LOGIC ("Learned MacAddr is " << m_learnedMac);
if (m_ns3AddressRewritten == false)
{
//
// Set the ns-3 device's mac address to the overlying container's
// mac address
//
Mac48Address learnedMac = Mac48Address::ConvertFrom (src);
NS_LOG_LOGIC ("Learned MacAddr is " << learnedMac << ": setting ns-3 device to use this address");
m_bridgedDevice->SetAddress (Mac48Address::ConvertFrom (learnedMac));
m_ns3AddressRewritten = true;
}
//
// If we are operating in USE_LOCAL mode, we may be attached to an ns-3
// device that does not support bridging (SupportsSendFrom returns false).
// The whole point of this mode is really to support this case. We allow
// only packets from one source MAC to flow across the TapBridge in this
// mode and will spoof that address when packets flow the other way.
// Since we will be doing this spoofing, we can relax the normal bridged
// device requirement to support SendFrom and use Send.
// But, since the mac addresses are now aligned, we can call Send()
//
NS_LOG_LOGIC ("Forwarding packet to ns-3 device via Send()");
m_bridgedDevice->Send (packet, dst, type);
@@ -864,20 +864,34 @@ 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.
// We need to disconnect the bridged device from the internet stack on our
// node to ensure that only one stack responds to packets inbound over the
// bridged device. That one stack lives outside ns-3 so we just blatantly
// steal the device callbacks.
//
m_node->RegisterProtocolHandler (MakeCallback (&TapBridge::ReceiveFromBridgedDevice, this), 0, bridgedDevice, true);
// N.B This can be undone if someone does a RegisterProtocolHandler later
// on this node.
//
bridgedDevice->SetReceiveCallback (MakeCallback (&TapBridge::DiscardFromBridgedDevice, this));
bridgedDevice->SetPromiscReceiveCallback (MakeCallback (&TapBridge::ReceiveFromBridgedDevice, this));
m_bridgedDevice = bridgedDevice;
}
void
bool
TapBridge::DiscardFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol, const Address &src)
{
NS_LOG_FUNCTION (device << packet << protocol << src);
NS_LOG_LOGIC ("Discarding packet stolen from bridged device " << device);
return true;
}
bool
TapBridge::ReceiveFromBridgedDevice (
Ptr<NetDevice> device,
Ptr<const Packet> packet,
uint16_t protocol,
Address const &src,
Address const &dst,
const Address &src,
const Address &dst,
PacketType packetType)
{
NS_LOG_FUNCTION (device << packet << protocol << src << dst << packetType);
@@ -913,35 +927,11 @@ TapBridge::ReceiveFromBridgedDevice (
// we want to act like a bridge and forward these PACKET_OTHERHOST
// packets.
//
return;
return true;
}
//
// 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 tap
// device on the Linux host. The only question we have to answer is, what
// should the destination address be?
//
// If we are in CONFIGURE_LOCAL mode, then the destination address is just
// left alone since it can only be the shared single MAC address, broadcast
// or multicast.
//
// If we are in USE_LOCAL mode, then we need to spoof the destination
// address with the one we saved.
//
// If we are in USE_BRIDGE mode, then we need to do the equvalent of a
// SendFrom and leave the source and destination alone.
//
Mac48Address from = Mac48Address::ConvertFrom (src);
Mac48Address to;
if (m_mode == USE_LOCAL)
{
to = Mac48Address::ConvertFrom (m_learnedMac);
}
else
{
to = Mac48Address::ConvertFrom (dst);
}
Mac48Address to = Mac48Address::ConvertFrom (dst);
Ptr<Packet> p = packet->Copy ();
EthernetHeader header = EthernetHeader (false);
@@ -956,9 +946,11 @@ TapBridge::ReceiveFromBridgedDevice (
NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
NS_LOG_LOGIC ("Pkt LengthType is " << header.GetLengthType ());
NS_LOG_LOGIC ("Pkt size is " << p->GetSize ());
NS_LOG_LOGIC ("End of receive packet handling on node " << m_node->GetId ());
uint32_t bytesWritten = write (m_sock, p->PeekData (), p->GetSize ());
NS_ABORT_MSG_IF (bytesWritten != p->GetSize (), "TapBridge::ReceiveFromBridgedDevice(): Write error.");
return true;
}
void
@@ -982,6 +974,13 @@ TapBridge::GetChannel (void) const
return 0;
}
void
TapBridge::SetAddress (Address address)
{
NS_LOG_FUNCTION (address);
m_address = Mac48Address::ConvertFrom (address);
}
Address
TapBridge::GetAddress (void) const
{

View File

@@ -176,6 +176,7 @@ public:
virtual void SetIfIndex(const uint32_t index);
virtual uint32_t GetIfIndex(void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);
virtual uint16_t GetMtu (void) const;
@@ -208,8 +209,11 @@ protected:
*/
virtual void DoDispose (void);
void ReceiveFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
bool ReceiveFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
Address const &src, Address const &dst, PacketType packetType);
bool DiscardFromBridgedDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol, Address const &src);
private:
/**
@@ -443,13 +447,10 @@ private:
/**
* \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.
* Whether the MAC address of the underlying ns-3 device has already been
* rewritten is stored in this variable (for UseLocal mode only).
*/
Mac48Address m_learnedMac;
bool m_ns3AddressRewritten;
};

View File

@@ -114,17 +114,11 @@ public:
PacketType packetType);
/**
* Set the MAC address of the the network device.
*
* \param addr The Address to use as the address of the device.
*/
void SetAddress (Address addr);
// inherited from NetDevice base class.
virtual void SetIfIndex(const uint32_t index);
virtual uint32_t GetIfIndex(void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual uint16_t GetMtu (void) const;
virtual bool IsLinkUp (void) const;

View File

@@ -157,6 +157,11 @@ WifiNetDevice::DoGetChannel (void) const
{
return m_phy->GetChannel ();
}
void
WifiNetDevice::SetAddress (Address address)
{
m_mac->SetAddress (Mac48Address::ConvertFrom (address));
}
Address
WifiNetDevice::GetAddress (void) const
{

View File

@@ -78,6 +78,7 @@ public:
virtual void SetIfIndex(const uint32_t index);
virtual uint32_t GetIfIndex(void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);
virtual uint16_t GetMtu (void) const;

View File

@@ -93,6 +93,12 @@ LoopbackNetDevice::GetChannel (void) const
return 0;
}
void
LoopbackNetDevice::SetAddress (Address address)
{
m_address = Mac48Address::ConvertFrom (address);
}
Address
LoopbackNetDevice::GetAddress (void) const
{

View File

@@ -45,6 +45,7 @@ public:
virtual void SetIfIndex(const uint32_t index);
virtual uint32_t GetIfIndex(void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);
virtual uint16_t GetMtu (void) const;

View File

@@ -300,7 +300,7 @@ Ptr<SimpleNetDevice>
TcpSocketImplTest::AddSimpleNetDevice (Ptr<Node> node, const char* ipaddr, const char* netmask)
{
Ptr<SimpleNetDevice> dev = CreateObject<SimpleNetDevice> ();
dev->SetAddress (Mac48Address::Allocate ());
dev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
node->AddDevice (dev);
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
uint32_t ndid = ipv4->AddInterface (dev);

View File

@@ -134,7 +134,7 @@ UdpSocketImplTest::RunTests (void)
Ptr<SimpleNetDevice> rxDev1, rxDev2;
{ // first interface
rxDev1 = CreateObject<SimpleNetDevice> ();
rxDev1->SetAddress (Mac48Address::Allocate ());
rxDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
rxNode->AddDevice (rxDev1);
Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
@@ -145,7 +145,7 @@ UdpSocketImplTest::RunTests (void)
{ // second interface
rxDev2 = CreateObject<SimpleNetDevice> ();
rxDev2->SetAddress (Mac48Address::Allocate ());
rxDev2->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
rxNode->AddDevice (rxDev2);
Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
@@ -160,7 +160,7 @@ UdpSocketImplTest::RunTests (void)
Ptr<SimpleNetDevice> txDev1;
{
txDev1 = CreateObject<SimpleNetDevice> ();
txDev1->SetAddress (Mac48Address::Allocate ());
txDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
txNode->AddDevice (txDev1);
Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
uint32_t netdev_idx = ipv4->AddInterface (txDev1);
@@ -171,7 +171,7 @@ UdpSocketImplTest::RunTests (void)
Ptr<SimpleNetDevice> txDev2;
{
txDev2 = CreateObject<SimpleNetDevice> ();
txDev2->SetAddress (Mac48Address::Allocate ());
txDev2->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
txNode->AddDevice (txDev2);
Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
uint32_t netdev_idx = ipv4->AddInterface (txDev2);

View File

@@ -97,10 +97,16 @@ public:
*/
virtual Ptr<Channel> GetChannel (void) const = 0;
/**
* Set the address of this interface
*/
virtual void SetAddress (Address address) = 0;
/**
* \return the current Address of this interface.
*/
virtual Address GetAddress (void) const = 0;
/**
* \param mtu MTU value, in bytes, to set for the device
* \return whether the MTU value was within legal bounds

View File

@@ -192,23 +192,12 @@ Node::RegisterProtocolHandler (ProtocolHandler handler,
i != m_devices.end (); i++)
{
Ptr<NetDevice> dev = *i;
if (dev->SupportsSendFrom ())
{
dev->SetPromiscReceiveCallback (MakeCallback (&Node::PromiscReceiveFromDevice, this));
}
dev->SetPromiscReceiveCallback (MakeCallback (&Node::PromiscReceiveFromDevice, this));
}
}
else
{
if (device->SupportsSendFrom ())
{
device->SetPromiscReceiveCallback (MakeCallback (&Node::PromiscReceiveFromDevice, this));
}
else
{
NS_LOG_WARN ("Protocol handler request promiscuous mode for a specific netdevice,"
" but netdevice does not support promiscuous mode.");
}
device->SetPromiscReceiveCallback (MakeCallback (&Node::PromiscReceiveFromDevice, this));
}
}

View File

@@ -76,12 +76,6 @@ SimpleNetDevice::SetChannel (Ptr<SimpleChannel> channel)
m_channel->Add (this);
}
void
SimpleNetDevice::SetAddress (Mac48Address address)
{
m_address = address;
}
void
SimpleNetDevice::SetIfIndex(const uint32_t index)
{
@@ -97,9 +91,17 @@ SimpleNetDevice::GetChannel (void) const
{
return m_channel;
}
void
SimpleNetDevice::SetAddress (Address address)
{
m_address = Mac48Address::ConvertFrom(address);
}
Address
SimpleNetDevice::GetAddress (void) const
{
//
// Implicit conversion from Mac48Address to Address
//
return m_address;
}
bool

View File

@@ -43,12 +43,12 @@ public:
void Receive (Ptr<Packet> packet, uint16_t protocol, Mac48Address to, Mac48Address from);
void SetChannel (Ptr<SimpleChannel> channel);
void SetAddress (Mac48Address address);
// inherited from NetDevice base class.
virtual void SetIfIndex(const uint32_t index);
virtual uint32_t GetIfIndex(void) const;
virtual Ptr<Channel> GetChannel (void) const;
virtual void SetAddress (Address address);
virtual Address GetAddress (void) const;
virtual bool SetMtu (const uint16_t mtu);
virtual uint16_t GetMtu (void) const;