A Discrete-Event Network Simulator
API
point-to-point-helper.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18  */
19 
20 #include "ns3/abort.h"
21 #include "ns3/config.h"
22 #include "ns3/log.h"
23 #include "ns3/names.h"
24 #include "ns3/net-device-queue-interface.h"
25 #include "ns3/packet.h"
26 #include "ns3/point-to-point-channel.h"
27 #include "ns3/point-to-point-net-device.h"
28 #include "ns3/simulator.h"
29 
30 #ifdef NS3_MPI
31 #include "ns3/mpi-interface.h"
32 #include "ns3/mpi-receiver.h"
33 #include "ns3/point-to-point-remote-channel.h"
34 #endif
35 
36 #include "point-to-point-helper.h"
37 
38 #include "ns3/trace-helper.h"
39 
40 namespace ns3
41 {
42 
43 NS_LOG_COMPONENT_DEFINE("PointToPointHelper");
44 
46 {
47  m_queueFactory.SetTypeId("ns3::DropTailQueue<Packet>");
48  m_deviceFactory.SetTypeId("ns3::PointToPointNetDevice");
49  m_channelFactory.SetTypeId("ns3::PointToPointChannel");
50  m_enableFlowControl = true;
51 }
52 
53 void
55 {
56  m_deviceFactory.Set(n1, v1);
57 }
58 
59 void
61 {
62  m_channelFactory.Set(n1, v1);
63 }
64 
65 void
67 {
68  m_enableFlowControl = false;
69 }
70 
71 void
73  Ptr<NetDevice> nd,
74  bool promiscuous,
75  bool explicitFilename)
76 {
77  //
78  // All of the Pcap enable functions vector through here including the ones
79  // that are wandering through all of devices on perhaps all of the nodes in
80  // the system. We can only deal with devices of type PointToPointNetDevice.
81  //
82  Ptr<PointToPointNetDevice> device = nd->GetObject<PointToPointNetDevice>();
83  if (!device)
84  {
85  NS_LOG_INFO("PointToPointHelper::EnablePcapInternal(): Device "
86  << device << " not of type ns3::PointToPointNetDevice");
87  return;
88  }
89 
90  PcapHelper pcapHelper;
91 
92  std::string filename;
93  if (explicitFilename)
94  {
95  filename = prefix;
96  }
97  else
98  {
99  filename = pcapHelper.GetFilenameFromDevice(prefix, device);
100  }
101 
102  Ptr<PcapFileWrapper> file = pcapHelper.CreateFile(filename, std::ios::out, PcapHelper::DLT_PPP);
103  pcapHelper.HookDefaultSink<PointToPointNetDevice>(device, "PromiscSniffer", file);
104 }
105 
106 void
108  std::string prefix,
109  Ptr<NetDevice> nd,
110  bool explicitFilename)
111 {
112  //
113  // All of the ascii enable functions vector through here including the ones
114  // that are wandering through all of devices on perhaps all of the nodes in
115  // the system. We can only deal with devices of type PointToPointNetDevice.
116  //
117  Ptr<PointToPointNetDevice> device = nd->GetObject<PointToPointNetDevice>();
118  if (!device)
119  {
120  NS_LOG_INFO("PointToPointHelper::EnableAsciiInternal(): Device "
121  << device << " not of type ns3::PointToPointNetDevice");
122  return;
123  }
124 
125  //
126  // Our default trace sinks are going to use packet printing, so we have to
127  // make sure that is turned on.
128  //
130 
131  //
132  // If we are not provided an OutputStreamWrapper, we are expected to create
133  // one using the usual trace filename conventions and do a Hook*WithoutContext
134  // since there will be one file per context and therefore the context would
135  // be redundant.
136  //
137  if (!stream)
138  {
139  //
140  // Set up an output stream object to deal with private ofstream copy
141  // constructor and lifetime issues. Let the helper decide the actual
142  // name of the file given the prefix.
143  //
144  AsciiTraceHelper asciiTraceHelper;
145 
146  std::string filename;
147  if (explicitFilename)
148  {
149  filename = prefix;
150  }
151  else
152  {
153  filename = asciiTraceHelper.GetFilenameFromDevice(prefix, device);
154  }
155 
156  Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream(filename);
157 
158  //
159  // The MacRx trace source provides our "r" event.
160  //
162  "MacRx",
163  theStream);
164 
165  //
166  // The "+", '-', and 'd' events are driven by trace sources actually in the
167  // transmit queue.
168  //
169  Ptr<Queue<Packet>> queue = device->GetQueue();
170  asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext<Queue<Packet>>(queue,
171  "Enqueue",
172  theStream);
173  asciiTraceHelper.HookDefaultDropSinkWithoutContext<Queue<Packet>>(queue, "Drop", theStream);
174  asciiTraceHelper.HookDefaultDequeueSinkWithoutContext<Queue<Packet>>(queue,
175  "Dequeue",
176  theStream);
177 
178  // PhyRxDrop trace source for "d" event
180  "PhyRxDrop",
181  theStream);
182 
183  return;
184  }
185 
186  //
187  // If we are provided an OutputStreamWrapper, we are expected to use it, and
188  // to providd a context. We are free to come up with our own context if we
189  // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
190  // compatibility and simplicity, we just use Config::Connect and let it deal
191  // with the context.
192  //
193  // Note that we are going to use the default trace sinks provided by the
194  // ascii trace helper. There is actually no AsciiTraceHelper in sight here,
195  // but the default trace sinks are actually publicly available static
196  // functions that are always there waiting for just such a case.
197  //
198  uint32_t nodeid = nd->GetNode()->GetId();
199  uint32_t deviceid = nd->GetIfIndex();
200  std::ostringstream oss;
201 
202  oss << "/NodeList/" << nd->GetNode()->GetId() << "/DeviceList/" << deviceid
203  << "/$ns3::PointToPointNetDevice/MacRx";
204  Config::Connect(oss.str(),
206 
207  oss.str("");
208  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
209  << "/$ns3::PointToPointNetDevice/TxQueue/Enqueue";
210  Config::Connect(oss.str(),
212 
213  oss.str("");
214  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
215  << "/$ns3::PointToPointNetDevice/TxQueue/Dequeue";
216  Config::Connect(oss.str(),
218 
219  oss.str("");
220  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
221  << "/$ns3::PointToPointNetDevice/TxQueue/Drop";
222  Config::Connect(oss.str(),
224 
225  oss.str("");
226  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
227  << "/$ns3::PointToPointNetDevice/PhyRxDrop";
228  Config::Connect(oss.str(),
230 }
231 
234 {
235  NS_ASSERT(c.GetN() == 2);
236  return Install(c.Get(0), c.Get(1));
237 }
238 
241 {
242  NetDeviceContainer container;
243 
245  devA->SetAddress(Mac48Address::Allocate());
246  a->AddDevice(devA);
248  devA->SetQueue(queueA);
250  devB->SetAddress(Mac48Address::Allocate());
251  b->AddDevice(devB);
253  devB->SetQueue(queueB);
255  {
256  // Aggregate NetDeviceQueueInterface objects
257  Ptr<NetDeviceQueueInterface> ndqiA = CreateObject<NetDeviceQueueInterface>();
258  ndqiA->GetTxQueue(0)->ConnectQueueTraces(queueA);
259  devA->AggregateObject(ndqiA);
260  Ptr<NetDeviceQueueInterface> ndqiB = CreateObject<NetDeviceQueueInterface>();
261  ndqiB->GetTxQueue(0)->ConnectQueueTraces(queueB);
262  devB->AggregateObject(ndqiB);
263  }
264 
266 
267  // If MPI is enabled, we need to see if both nodes have the same system id
268  // (rank), and the rank is the same as this instance. If both are true,
269  // use a normal p2p channel, otherwise use a remote channel
270 #ifdef NS3_MPI
271  bool useNormalChannel = true;
273  {
274  uint32_t n1SystemId = a->GetSystemId();
275  uint32_t n2SystemId = b->GetSystemId();
276  uint32_t currSystemId = MpiInterface::GetSystemId();
277  if (n1SystemId != currSystemId || n2SystemId != currSystemId)
278  {
279  useNormalChannel = false;
280  }
281  }
282  if (useNormalChannel)
283  {
284  m_channelFactory.SetTypeId("ns3::PointToPointChannel");
286  }
287  else
288  {
289  m_channelFactory.SetTypeId("ns3::PointToPointRemoteChannel");
291  Ptr<MpiReceiver> mpiRecA = CreateObject<MpiReceiver>();
292  Ptr<MpiReceiver> mpiRecB = CreateObject<MpiReceiver>();
293  mpiRecA->SetReceiveCallback(MakeCallback(&PointToPointNetDevice::Receive, devA));
294  mpiRecB->SetReceiveCallback(MakeCallback(&PointToPointNetDevice::Receive, devB));
295  devA->AggregateObject(mpiRecA);
296  devB->AggregateObject(mpiRecB);
297  }
298 #else
300 #endif
301 
302  devA->Attach(channel);
303  devB->Attach(channel);
304  container.Add(devA);
305  container.Add(devB);
306 
307  return container;
308 }
309 
312 {
313  Ptr<Node> b = Names::Find<Node>(bName);
314  return Install(a, b);
315 }
316 
319 {
320  Ptr<Node> a = Names::Find<Node>(aName);
321  return Install(a, b);
322 }
323 
325 PointToPointHelper::Install(std::string aName, std::string bName)
326 {
327  Ptr<Node> a = Names::Find<Node>(aName);
328  Ptr<Node> b = Names::Find<Node>(bName);
329  return Install(a, b);
330 }
331 
332 } // namespace ns3
Manage ASCII trace files for device models.
Definition: trace-helper.h:173
void HookDefaultDropSinkWithoutContext(Ptr< T > object, std::string traceName, Ptr< OutputStreamWrapper > stream)
Hook a trace source to the default drop operation trace sink that does not accept nor log a trace con...
Definition: trace-helper.h:533
std::string GetFilenameFromDevice(std::string prefix, Ptr< NetDevice > device, bool useObjectNames=true)
Let the ascii trace helper figure out a reasonable filename to use for an ascii trace file associated...
static void DefaultDropSinkWithContext(Ptr< OutputStreamWrapper > file, std::string context, Ptr< const Packet > p)
Basic Drop default trace sink.
static void DefaultReceiveSinkWithContext(Ptr< OutputStreamWrapper > file, std::string context, Ptr< const Packet > p)
Basic Receive default trace sink.
Ptr< OutputStreamWrapper > CreateFileStream(std::string filename, std::ios::openmode filemode=std::ios::out)
Create and initialize an output stream object we'll use to write the traced bits.
void HookDefaultEnqueueSinkWithoutContext(Ptr< T > object, std::string traceName, Ptr< OutputStreamWrapper > stream)
Hook a trace source to the default enqueue operation trace sink that does not accept nor log a trace ...
Definition: trace-helper.h:504
void HookDefaultReceiveSinkWithoutContext(Ptr< T > object, std::string traceName, Ptr< OutputStreamWrapper > stream)
Hook a trace source to the default receive operation trace sink that does not accept nor log a trace ...
Definition: trace-helper.h:591
static void DefaultEnqueueSinkWithContext(Ptr< OutputStreamWrapper > file, std::string context, Ptr< const Packet > p)
Basic Enqueue default trace sink.
void HookDefaultDequeueSinkWithoutContext(Ptr< T > object, std::string traceName, Ptr< OutputStreamWrapper > stream)
Hook a trace source to the default dequeue operation trace sink that does not accept nor log a trace ...
Definition: trace-helper.h:562
static void DefaultDequeueSinkWithContext(Ptr< OutputStreamWrapper > file, std::string context, Ptr< const Packet > p)
Basic Dequeue default trace sink.
Hold a value for an Attribute.
Definition: attribute.h:70
static Mac48Address Allocate()
Allocate a new Mac48Address.
static bool IsEnabled()
Returns enabled state of parallel environment.
static uint32_t GetSystemId()
Get the id number of this rank.
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
keep track of a set of node pointers.
uint32_t GetN() const
Get the number of Ptr<Node> stored in this container.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t GetSystemId() const
Definition: node.cc:131
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:138
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void Set(const std::string &name, const AttributeValue &value, Args &&... args)
Set an attribute to be set during construction.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
static void EnablePrinting()
Enable printing packets metadata.
Definition: packet.cc:596
Manage pcap files for device models.
Definition: trace-helper.h:39
std::string GetFilenameFromDevice(std::string prefix, Ptr< NetDevice > device, bool useObjectNames=true)
Let the pcap helper figure out a reasonable filename to use for a pcap file associated with a device.
Definition: trace-helper.cc:79
Ptr< PcapFileWrapper > CreateFile(std::string filename, std::ios::openmode filemode, DataLinkType dataLinkType, uint32_t snapLen=std::numeric_limits< uint32_t >::max(), int32_t tzCorrection=0)
Create and initialize a pcap file.
Definition: trace-helper.cc:49
void HookDefaultSink(Ptr< T > object, std::string traceName, Ptr< PcapFileWrapper > file)
Hook a trace source to the default trace sink.
Definition: trace-helper.h:157
Simple Point To Point Channel.
ObjectFactory m_channelFactory
Channel Factory.
PointToPointHelper()
Create a PointToPointHelper to make life easier when creating point to point networks.
bool m_enableFlowControl
whether to enable flow control
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
void DisableFlowControl()
Disable flow control only if you know what you are doing.
void EnablePcapInternal(std::string prefix, Ptr< NetDevice > nd, bool promiscuous, bool explicitFilename) override
Enable pcap output the indicated net device.
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
ObjectFactory m_queueFactory
Queue Factory.
ObjectFactory m_deviceFactory
Device Factory.
NetDeviceContainer Install(NodeContainer c)
void EnableAsciiInternal(Ptr< OutputStreamWrapper > stream, std::string prefix, Ptr< NetDevice > nd, bool explicitFilename) override
Enable ascii trace output on the indicated net device.
A Device for a Point to Point Network Link.
Ptr< Queue< Packet > > GetQueue() const
Get a copy of the attached Queue.
void Receive(Ptr< Packet > p)
Receive a packet from a connected PointToPointChannel.
A Remote Point-To-Point Channel.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:975
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:768
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707
channel
Definition: third.py:81