--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tap/tap-csma.cc Wed Dec 02 11:25:29 2009 -0800
@@ -0,0 +1,111 @@
+/* -*- 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
+//
+// Packets sent to the device "thetap" on the Linux host will be sent to the
+// tap bridge on node zero and then emitted onto the ns-3 simulated CSMA
+// network. ARP will be used on the CSMA network to resolve MAC addresses.
+// Packets destined for the CSMA device on node zero will be sent to the
+// device "thetap" on the linux Host.
+//
+// +----------+
+// | external |
+// | Linux |
+// | Host |
+// | |
+// | "thetap" |
+// +----------+
+// | n0 n1 n2 n3
+// | +--------+ +--------+ +--------+ +--------+
+// +-------| tap | | | | | | |
+// | bridge | | | | | | |
+// +--------+ +--------+ +--------+ +--------+
+// | CSMA | | CSMA | | CSMA | | CSMA |
+// +--------+ +--------+ +--------+ +--------+
+// | | | |
+// | | | |
+// | | | |
+// ===========================================
+// CSMA LAN 10.1.1
+//
+// The CSMA device on node zero is: 10.1.1.1
+// The CSMA device on node one is: 10.1.1.2
+// The CSMA device on node two is: 10.1.1.3
+// The CSMA device on node three is: 10.1.1.4
+//
+// Some simple things to do:
+//
+// 1) Ping one of the simulated nodes
+//
+// ./waf --run tap-csma&
+// ping 10.1.1.2
+//
+#include <iostream>
+#include <fstream>
+
+#include "ns3/simulator-module.h"
+#include "ns3/node-module.h"
+#include "ns3/core-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/helper-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TapCsmaExample");
+
+int
+main (int argc, char *argv[])
+{
+ std::string mode = "ConfigureLocal";
+ std::string tapName = "thetap";
+
+ CommandLine cmd;
+ cmd.AddValue("mode", "Mode setting of TapBridge", mode);
+ cmd.AddValue("tapName", "Name of the OS tap device", tapName);
+ cmd.Parse (argc, argv);
+
+ GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
+ GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true));
+
+ NodeContainer nodes;
+ nodes.Create (4);
+
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+ csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+
+ NetDeviceContainer devices = csma.Install (nodes);
+
+ InternetStackHelper stack;
+ stack.Install (nodes);
+
+ Ipv4AddressHelper addresses;
+ addresses.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer interfaces = addresses.Assign (devices);
+
+ TapBridgeHelper tapBridge;
+ tapBridge.SetAttribute ("Mode", StringValue (mode));
+ tapBridge.SetAttribute ("DeviceName", StringValue (tapName));
+ tapBridge.Install (nodes.Get (0), devices.Get (0));
+
+ CsmaHelper::EnablePcapAll ("tap-csma", false);
+ Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+ Simulator::Stop (Seconds (60.));
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
--- a/examples/tap/tap-wifi-dumbbell.cc Tue Dec 01 18:34:11 2009 +0300
+++ b/examples/tap/tap-wifi-dumbbell.cc Wed Dec 02 11:25:29 2009 -0800
@@ -216,6 +216,7 @@
apps = sink.Install (nodesRight.Get (0));
apps.Start (Seconds (1.0));
+ wifiPhy.EnablePcapAll ("tap-wifi-dumbbell");
CsmaHelper::EnablePcapAll ("tap-wifi-dumbbell", false);
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
--- a/examples/tap/wscript Tue Dec 01 18:34:11 2009 +0300
+++ b/examples/tap/wscript Wed Dec 02 11:25:29 2009 -0800
@@ -3,6 +3,7 @@
def build(bld):
env = bld.env_of_name('default')
if env['ENABLE_TAP']:
- obj = bld.create_ns3_program('tap-wifi-dumbbell',
- ['wifi', 'csma', 'point-to-point', 'tap-bridge', 'internet-stack'])
+ obj = bld.create_ns3_program('tap-csma', ['csma', 'tap-bridge', 'internet-stack'])
+ obj.source = 'tap-csma.cc'
+ obj = bld.create_ns3_program('tap-wifi-dumbbell', ['wifi', 'csma', 'point-to-point', 'tap-bridge', 'internet-stack'])
obj.source = 'tap-wifi-dumbbell.cc'
--- a/src/devices/emu/emu-net-device.cc Tue Dec 01 18:34:11 2009 +0300
+++ b/src/devices/emu/emu-net-device.cc Wed Dec 02 11:25:29 2009 -0800
@@ -189,11 +189,8 @@
EmuNetDevice::~EmuNetDevice ()
{
- if (m_packetBuffer)
- {
- delete [] m_packetBuffer;
- m_packetBuffer = 0;
- }
+ delete [] m_packetBuffer;
+ m_packetBuffer = 0;
}
void
@@ -229,20 +226,6 @@
//
Simulator::Cancel (m_startEvent);
m_startEvent = Simulator::Schedule (tStart, &EmuNetDevice::StartDevice, this);
-
- //
- // We're going to need a pointer to the realtime simulator implementation.
- // It's important to remember that access to that implementation may happen
- // in a completely different thread than the simulator is running in. We are
- // talking about multiple threads here, so it is very, very dangerous to do
- // any kind of reference couning on a shared object. So what we are going to
- // do is to get a reference to the realtime simulator and then save a raw
- // pointer to that implementation for use by the other threads. We must not
- // free this pointer or we may delete the simulator out from under us an
- // everyone else.
- //
- Ptr<RealtimeSimulatorImpl> impl = DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ());
- m_rtImpl = GetPointer (impl);
}
void
@@ -269,7 +252,28 @@
NS_FATAL_ERROR ("EmuNetDevice::StartDevice(): Device is already started");
}
+ //
+ // We're going to need a pointer to the realtime simulator implementation.
+ // It's important to remember that access to that implementation may happen
+ // in a completely different thread than the simulator is running in (we're
+ // going to spin up that thread below). We are talking about multiple threads
+ // here, so it is very, very dangerous to do any kind of reference couning on
+ // a shared object that is unaware of what is happening. What we are going to
+ // do to address that is to get a reference to the realtime simulator here
+ // where we are running in the context of a running simulator scheduler --
+ // recall we did a Simulator::Schedule of this method above. We get the
+ // simulator implementation pointer in a single-threaded way and save the
+ // underlying raw pointer for use by the (other) read thread. We must not
+ // free this pointer or we may delete the simulator out from under us an
+ // everyone else. We assume that the simulator implementation cannot be
+ // replaced while the emu device is running and so will remain valid through
+ // the time during which the read thread is running.
+ //
+ Ptr<RealtimeSimulatorImpl> impl = DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ());
+ m_rtImpl = GetPointer (impl);
+
NS_LOG_LOGIC ("Creating socket");
+
//
// Call out to a separate process running as suid root in order to get a raw
// socket. We do this to avoid having the entire simulation running as root.
--- a/src/devices/tap-bridge/tap-bridge.cc Tue Dec 01 18:34:11 2009 +0300
+++ b/src/devices/tap-bridge/tap-bridge.cc Wed Dec 02 11:25:29 2009 -0800
@@ -134,12 +134,17 @@
m_ns3AddressRewritten (false)
{
NS_LOG_FUNCTION_NOARGS ();
+ m_packetBuffer = new uint8_t[65536];
Start (m_tStart);
}
TapBridge::~TapBridge()
{
NS_LOG_FUNCTION_NOARGS ();
+
+ delete [] m_packetBuffer;
+ m_packetBuffer = 0;
+
m_bridgedDevice = 0;
}
@@ -181,6 +186,26 @@
NS_ABORT_MSG_IF (m_sock != -1, "TapBridge::StartTapDevice(): Tap is already started");
//
+ // We're going to need a pointer to the realtime simulator implementation.
+ // It's important to remember that access to that implementation may happen
+ // in a completely different thread than the simulator is running in (we're
+ // going to spin up that thread below). We are talking about multiple threads
+ // here, so it is very, very dangerous to do any kind of reference couning on
+ // a shared object that is unaware of what is happening. What we are going to
+ // do to address that is to get a reference to the realtime simulator here
+ // where we are running in the context of a running simulator scheduler --
+ // recall we did a Simulator::Schedule of this method above. We get the
+ // simulator implementation pointer in a single-threaded way and save the
+ // underlying raw pointer for use by the (other) read thread. We must not
+ // free this pointer or we may delete the simulator out from under us an
+ // everyone else. We assume that the simulator implementation cannot be
+ // replaced while the tap bridge is running and so will remain valid through
+ // the time during which the read thread is running.
+ //
+ Ptr<RealtimeSimulatorImpl> impl = DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ());
+ m_rtImpl = GetPointer (impl);
+
+ //
// Spin up the tap bridge and start receiving packets.
//
NS_LOG_LOGIC ("Creating tap device");
@@ -643,7 +668,8 @@
NS_LOG_INFO ("TapBridge::ReadThread(): Received packet on node " << m_node->GetId ());
NS_LOG_INFO ("TapBridge::ReadThread(): Scheduling handler");
- DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ())->ScheduleRealtimeNow (
+ NS_ASSERT_MSG (m_rtImpl, "EmuNetDevice::ReadThread(): Realtime simulator implementation pointer not set");
+ m_rtImpl->ScheduleRealtimeNowWithContext (GetNode ()->GetId (),
MakeEvent (&TapBridge::ForwardToBridgedDevice, this, buf, len));
buf = 0;
}
@@ -699,7 +725,7 @@
Ptr<Packet> p = Filter (packet, &src, &dst, &type);
if (p == 0)
{
- NS_LOG_LOGIC ("Discarding packet as unfit for ns-3 consumption");
+ NS_LOG_LOGIC ("TapBridge::ForwardToBridgedDevice: Discarding packet as unfit for ns-3 consumption");
return;
}
@@ -946,10 +972,14 @@
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 ());
+
+ NS_ASSERT_MSG (p->GetSize () <= 65536, "TapBridge::ReceiveFromBridgedDevice: Packet too big " << p->GetSize ());
+ p->CopyData (m_packetBuffer, p->GetSize ());
- uint32_t bytesWritten = write (m_sock, p->PeekData (), p->GetSize ());
+ uint32_t bytesWritten = write (m_sock, m_packetBuffer, p->GetSize ());
NS_ABORT_MSG_IF (bytesWritten != p->GetSize (), "TapBridge::ReceiveFromBridgedDevice(): Write error.");
+
+ NS_LOG_LOGIC ("End of receive packet handling on node " << m_node->GetId ());
return true;
}
--- a/src/devices/tap-bridge/tap-bridge.h Tue Dec 01 18:34:11 2009 +0300
+++ b/src/devices/tap-bridge/tap-bridge.h Wed Dec 02 11:25:29 2009 -0800
@@ -32,6 +32,7 @@
#include "ns3/ptr.h"
#include "ns3/mac48-address.h"
#include "ns3/system-thread.h"
+#include "ns3/realtime-simulator-impl.h"
namespace ns3 {
@@ -456,6 +457,16 @@
*/
bool m_ns3AddressRewritten;
+ /**
+ * A 64K buffer to hold packet data while it is being sent.
+ */
+ uint8_t *m_packetBuffer;
+
+ /**
+ * A copy of a raw pointer to the required real-time simulator implementation.
+ * Never free this pointer!
+ */
+ RealtimeSimulatorImpl *m_rtImpl;
};
} // namespace ns3