Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Remove one of the many pimple: HostModel::p_cpuModel
[simgrid.git] / src / surf / ns3 / my-point-to-point-helper.cc
1 /* Copyright (c) 2011, 2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /*
8  * Copyright (c) 2008 INRIA
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation;
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
24  */
25
26 #include <ns3/abort.h>
27 #include "ns3/simulator.h"
28 #include "ns3/point-to-point-net-device.h"
29 #include "ns3/point-to-point-channel.h"
30 #include "ns3/point-to-point-remote-channel.h"
31 #include "ns3/queue.h"
32 #include "ns3/config.h"
33 #include "ns3/packet.h"
34 #include "ns3/names.h"
35 #include "ns3/string.h"
36 #include "ns3/mpi-interface.h"
37 #include "ns3/mpi-receiver.h"
38
39 #include "ns3/trace-helper.h"
40 #include "my-point-to-point-helper.h"
41
42 #include "xbt/log.h"
43
44 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(ns3);
45
46 ///> RED Parameters  see src/node/red-queue.* for details
47 //.AddAttribute ("Mode",
48 //                "Whether to use Bytes (see MaxBytes) or Packets (see MaxPackets) as the maximum queue size metric.",
49 //                EnumValue (BYTES), ///> currently supports BYTES only
50 //                MakeEnumAccessor (&RedQueue::SetMode),
51 //                MakeEnumChecker (BYTES, "Bytes",
52 //                                 PACKETS, "Packets"))
53 // .AddAttribute ("MaxPackets",
54 //                "The maximum number of packets accepted by this RedQueue.",
55 //                UintegerValue (100),
56 //                MakeUintegerAccessor (&RedQueue::m_maxPackets),
57 //                MakeUintegerChecker<uint32_t> ())
58 // .AddAttribute ("MaxBytes",
59 //                "The maximum number of bytes accepted by this RedQueue.",
60 //                UintegerValue (100000),
61 //                MakeUintegerAccessor (&RedQueue::m_maxBytes),
62 //                MakeUintegerChecker<uint32_t> ())
63 // .AddAttribute ("m_burst",
64 //                "maximum number of m_burst packets accepted by this queue",
65 //                UintegerValue (6), ///> bursts must be > minTh/avpkt
66 //                MakeUintegerAccessor (&RedQueue::m_burst),
67 //                MakeUintegerChecker<uint32_t> ())
68 // .AddAttribute ("m_avPkt",
69 //                "In bytes, use with m_burst to determine the time constant for average queue size calculations",
70 //                UintegerValue (1024), ///> average packet size
71 //                MakeUintegerAccessor (&RedQueue::m_avPkt),
72 //                MakeUintegerChecker<uint32_t> ())
73 // .AddAttribute ("m_minTh",
74 //                "Average queue size at which marking becomes a m_prob",
75 //                UintegerValue (5120), ///> in bytes  1024x5
76 //                MakeUintegerAccessor (&RedQueue::m_minTh),
77 //                MakeUintegerChecker<uint32_t> ())
78 // .AddAttribute ("m_maxTh",
79 //                "Maximal marking m_prob, should be at least twice min to prevent synchronous retransmits",
80 //                UintegerValue (15360), ///> in bytes 1024x15
81 //                MakeUintegerAccessor (&RedQueue::m_maxTh),
82 //                MakeUintegerChecker<uint32_t> ())
83 // .AddAttribute ("m_rate",
84 //                "this m_rate is used for calculating the average queue size after some idle time.",
85 //                UintegerValue (1500000), ///> in bps, should be set to bandwidth of interface
86 //                MakeUintegerAccessor (&RedQueue::m_rate),
87 //                MakeUintegerChecker<uint64_t> ())
88 // .AddAttribute ("m_prob",
89 //                "Probability for marking, suggested values are 0.01 and 0.02",
90 //                DoubleValue (0.02),
91 //                MakeDoubleAccessor (&RedQueue::m_prob),
92 //                MakeDoubleChecker <double> ())
93 std::string qMode = "Bytes";
94 std::string qBurst = "6";
95 std::string qAvPkt = "1024";
96 std::string qLimit = "25600"; //"100000";
97 std::string qthMin = "5120";  // 1024 x 5 bytes
98 std::string qthMax = "15360"; // 1024 x 15 bytes
99 std::string qIdleRate = "1500000";  //1.5 Mbps
100 std::string qProb = "0.02";
101
102 namespace ns3 {
103
104 MyPointToPointHelper::MyPointToPointHelper ()
105 {
106   m_queueFactory.SetTypeId ("ns3::DropTailQueue");
107   m_queueFactory_red.SetTypeId ("ns3::RedQueue");
108 //  m_queueFactory_red.Set ("Mode",    StringValue (qMode));
109 //  m_queueFactory_red.Set ("MaxBytes",StringValue (qLimit));
110 //  m_queueFactory_red.Set ("m_burst", StringValue (qBurst));
111 //  m_queueFactory_red.Set ("m_avPkt", StringValue (qAvPkt));
112 //  m_queueFactory_red.Set ("m_minTh", StringValue (qthMin));
113 //  m_queueFactory_red.Set ("m_maxTh", StringValue (qthMax));
114 //  m_queueFactory_red.Set ("m_rate",  StringValue (qIdleRate));
115 //  m_queueFactory_red.Set ("m_prob",  StringValue (qProb));
116   m_deviceFactory.SetTypeId ("ns3::PointToPointNetDevice");
117   m_channelFactory.SetTypeId ("ns3::PointToPointChannel");
118   m_remoteChannelFactory.SetTypeId ("ns3::PointToPointRemoteChannel");
119 }
120
121 void 
122 MyPointToPointHelper::SetQueue (std::string type,
123                               std::string n1, const AttributeValue &v1,
124                               std::string n2, const AttributeValue &v2,
125                               std::string n3, const AttributeValue &v3,
126                               std::string n4, const AttributeValue &v4,
127                               std::string n5, const AttributeValue &v5,
128                               std::string n6, const AttributeValue &v6,
129                               std::string n7, const AttributeValue &v7,
130                               std::string n8, const AttributeValue &v8)
131 {
132   m_queueFactory.SetTypeId (type);
133   m_queueFactory.Set (n1, v1);
134   m_queueFactory.Set (n2, v2);
135   m_queueFactory.Set (n3, v3);
136   m_queueFactory.Set (n4, v4);
137   m_queueFactory.Set (n5, v5);
138   m_queueFactory.Set (n6, v6);
139   m_queueFactory.Set (n7, v7);
140   m_queueFactory.Set (n8, v8);
141 }
142
143 void 
144 MyPointToPointHelper::SetDeviceAttribute (std::string n1, const AttributeValue &v1)
145 {
146   m_deviceFactory.Set (n1, v1);
147 }
148
149 void 
150 MyPointToPointHelper::SetChannelAttribute (std::string n1, const AttributeValue &v1)
151 {
152   m_channelFactory.Set (n1, v1);
153   m_remoteChannelFactory.Set (n1, v1);
154 }
155
156 void 
157 MyPointToPointHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
158 {
159   //
160   // All of the Pcap enable functions vector through here including the ones
161   // that are wandering through all of devices on perhaps all of the nodes in
162   // the system.  We can only deal with devices of type PointToPointNetDevice.
163   //
164   Ptr<PointToPointNetDevice> device = nd->GetObject<PointToPointNetDevice> ();
165   if (device == 0)
166     {
167       XBT_INFO ("MyPointToPointHelper::EnablePcapInternal(): Device not of type ns3::PointToPointNetDevice");
168       return;
169     }
170
171   PcapHelper pcapHelper;
172
173   std::string filename;
174   if (explicitFilename)
175     {
176       filename = prefix;
177     }
178   else
179     {
180       filename = pcapHelper.GetFilenameFromDevice (prefix, device);
181     }
182
183   Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, 
184                                                      PcapHelper::DLT_PPP);
185   pcapHelper.HookDefaultSink<PointToPointNetDevice> (device, "PromiscSniffer", file);
186 }
187
188 void 
189 MyPointToPointHelper::EnableAsciiInternal (
190   Ptr<OutputStreamWrapper> stream, 
191   std::string prefix, 
192   Ptr<NetDevice> nd,
193   bool explicitFilename)
194 {
195   //
196   // All of the ascii enable functions vector through here including the ones
197   // that are wandering through all of devices on perhaps all of the nodes in
198   // the system.  We can only deal with devices of type PointToPointNetDevice.
199   //
200   Ptr<PointToPointNetDevice> device = nd->GetObject<PointToPointNetDevice> ();
201   if (device == 0)
202     {
203       XBT_INFO ("MyPointToPointHelper::EnableAsciiInternal(): Device not of type ns3::PointToPointNetDevice");
204       return;
205     }
206
207   //
208   // Our default trace sinks are going to use packet printing, so we have to 
209   // make sure that is turned on.
210   //
211   Packet::EnablePrinting ();
212
213   //
214   // If we are not provided an OutputStreamWrapper, we are expected to create 
215   // one using the usual trace filename conventions and do a Hook*WithoutContext
216   // since there will be one file per context and therefore the context would
217   // be redundant.
218   //
219   if (stream == 0)
220     {
221       //
222       // Set up an output stream object to deal with private ofstream copy 
223       // constructor and lifetime issues.  Let the helper decide the actual
224       // name of the file given the prefix.
225       //
226       AsciiTraceHelper asciiTraceHelper;
227
228       std::string filename;
229       if (explicitFilename)
230         {
231           filename = prefix;
232         }
233       else
234         {
235           filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
236         }
237
238       Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
239
240       //
241       // The MacRx trace source provides our "r" event.
242       //
243       asciiTraceHelper.HookDefaultReceiveSinkWithoutContext<PointToPointNetDevice> (device, "MacRx", theStream);
244
245       //
246       // The "+", '-', and 'd' events are driven by trace sources actually in the
247       // transmit queue.
248       //
249       Ptr<Queue> queue = device->GetQueue ();
250       asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext<Queue> (queue, "Enqueue", theStream);
251       asciiTraceHelper.HookDefaultDropSinkWithoutContext<Queue> (queue, "Drop", theStream);
252       asciiTraceHelper.HookDefaultDequeueSinkWithoutContext<Queue> (queue, "Dequeue", theStream);
253
254       // PhyRxDrop trace source for "d" event
255       asciiTraceHelper.HookDefaultDropSinkWithoutContext<PointToPointNetDevice> (device, "PhyRxDrop", theStream);
256
257       return;
258     }
259
260   //
261   // If we are provided an OutputStreamWrapper, we are expected to use it, and
262   // to providd a context.  We are free to come up with our own context if we
263   // want, and use the AsciiTraceHelper Hook*WithContext functions, but for 
264   // compatibility and simplicity, we just use Config::Connect and let it deal
265   // with the context.
266   //
267   // Note that we are going to use the default trace sinks provided by the 
268   // ascii trace helper.  There is actually no AsciiTraceHelper in sight here,
269   // but the default trace sinks are actually publicly available static 
270   // functions that are always there waiting for just such a case.
271   //
272   uint32_t nodeid = nd->GetNode ()->GetId ();
273   uint32_t deviceid = nd->GetIfIndex ();
274   std::ostringstream oss;
275
276   oss << "/NodeList/" << nd->GetNode ()->GetId () << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/MacRx";
277   Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultReceiveSinkWithContext, stream));
278
279   oss.str ("");
280   oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/TxQueue/Enqueue";
281   Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultEnqueueSinkWithContext, stream));
282
283   oss.str ("");
284   oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/TxQueue/Dequeue";
285   Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDequeueSinkWithContext, stream));
286
287   oss.str ("");
288   oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/TxQueue/Drop";
289   Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream));
290
291   oss.str ("");
292   oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/PhyRxDrop";
293   Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream));
294 }
295
296 NetDeviceContainer 
297 MyPointToPointHelper::Install (NodeContainer c)
298 {
299   NS_ASSERT (c.GetN () == 2);
300   return Install (c.Get (0), c.Get (1));
301 }
302
303 NetDeviceContainer 
304 MyPointToPointHelper::Install (Ptr<Node> a, e_ns3_network_element_type_t type_a, Ptr<Node> b, e_ns3_network_element_type_t type_b)
305 {
306   NetDeviceContainer container;
307   Ptr<Queue> queueA;
308   Ptr<Queue> queueB;
309
310   Ptr<PointToPointNetDevice> devA = m_deviceFactory.Create<PointToPointNetDevice> ();
311   devA->SetAddress (Mac48Address::Allocate ());
312   a->AddDevice (devA);
313
314   if(type_a == NS3_NETWORK_ELEMENT_ROUTER){
315         queueA = m_queueFactory_red.Create<Queue> ();
316   }
317   else
318           queueA = m_queueFactory.Create<Queue> ();
319   devA->SetQueue (queueA);
320
321   Ptr<PointToPointNetDevice> devB = m_deviceFactory.Create<PointToPointNetDevice> ();
322   devB->SetAddress (Mac48Address::Allocate ());
323   b->AddDevice (devB);
324
325   if(type_b == NS3_NETWORK_ELEMENT_ROUTER){
326         queueB = m_queueFactory_red.Create<Queue> ();
327   }
328   else
329           queueB = m_queueFactory.Create<Queue> ();
330   devB->SetQueue (queueB);
331
332   // If MPI is enabled, we need to see if both nodes have the same system id 
333   // (rank), and the rank is the same as this instance.  If both are true, 
334   //use a normal p2p channel, otherwise use a remote channel
335   bool useNormalChannel = true;
336   Ptr<PointToPointChannel> channel = 0;
337   if (MpiInterface::IsEnabled ())
338     {
339       uint32_t n1SystemId = a->GetSystemId ();
340       uint32_t n2SystemId = b->GetSystemId ();
341       uint32_t currSystemId = MpiInterface::GetSystemId ();
342       if (n1SystemId != currSystemId || n2SystemId != currSystemId) 
343         {
344           useNormalChannel = false;
345         }
346     }
347   if (useNormalChannel)
348     {
349       channel = m_channelFactory.Create<PointToPointChannel> ();
350     }
351   else
352     {
353       channel = m_remoteChannelFactory.Create<PointToPointRemoteChannel> ();
354       Ptr<MpiReceiver> mpiRecA = CreateObject<MpiReceiver> ();
355       Ptr<MpiReceiver> mpiRecB = CreateObject<MpiReceiver> ();
356       mpiRecA->SetReceiveCallback (MakeCallback (&PointToPointNetDevice::Receive, devA));
357       mpiRecB->SetReceiveCallback (MakeCallback (&PointToPointNetDevice::Receive, devB));
358       devA->AggregateObject (mpiRecA);
359       devB->AggregateObject (mpiRecB);
360     }
361
362   devA->Attach (channel);
363   devB->Attach (channel);
364   container.Add (devA);
365   container.Add (devB);
366
367   return container;
368 }
369
370 NetDeviceContainer 
371 MyPointToPointHelper::Install (Ptr<Node> a, Ptr<Node> b)
372 {
373   NetDeviceContainer container;
374
375   Ptr<PointToPointNetDevice> devA = m_deviceFactory.Create<PointToPointNetDevice> ();
376   devA->SetAddress (Mac48Address::Allocate ());
377   a->AddDevice (devA);
378   Ptr<Queue> queueA = m_queueFactory.Create<Queue> ();
379   devA->SetQueue (queueA);
380   Ptr<PointToPointNetDevice> devB = m_deviceFactory.Create<PointToPointNetDevice> ();
381   devB->SetAddress (Mac48Address::Allocate ());
382   b->AddDevice (devB);
383   Ptr<Queue> queueB = m_queueFactory.Create<Queue> ();
384   devB->SetQueue (queueB);
385   // If MPI is enabled, we need to see if both nodes have the same system id
386   // (rank), and the rank is the same as this instance.  If both are true,
387   //use a normal p2p channel, otherwise use a remote channel
388   bool useNormalChannel = true;
389   Ptr<PointToPointChannel> channel = 0;
390   if (MpiInterface::IsEnabled ())
391     {
392       uint32_t n1SystemId = a->GetSystemId ();
393       uint32_t n2SystemId = b->GetSystemId ();
394       uint32_t currSystemId = MpiInterface::GetSystemId ();
395       if (n1SystemId != currSystemId || n2SystemId != currSystemId)
396         {
397           useNormalChannel = false;
398         }
399     }
400   if (useNormalChannel)
401     {
402       channel = m_channelFactory.Create<PointToPointChannel> ();
403     }
404   else
405     {
406       channel = m_remoteChannelFactory.Create<PointToPointRemoteChannel> ();
407       Ptr<MpiReceiver> mpiRecA = CreateObject<MpiReceiver> ();
408       Ptr<MpiReceiver> mpiRecB = CreateObject<MpiReceiver> ();
409       mpiRecA->SetReceiveCallback (MakeCallback (&PointToPointNetDevice::Receive, devA));
410       mpiRecB->SetReceiveCallback (MakeCallback (&PointToPointNetDevice::Receive, devB));
411       devA->AggregateObject (mpiRecA);
412       devB->AggregateObject (mpiRecB);
413     }
414
415   devA->Attach (channel);
416   devB->Attach (channel);
417   container.Add (devA);
418   container.Add (devB);
419
420   return container;
421 }
422
423 NetDeviceContainer
424 MyPointToPointHelper::Install (Ptr<Node> a, std::string bName)
425 {
426   Ptr<Node> b = Names::Find<Node> (bName);
427   return Install (a, b);
428 }
429
430 NetDeviceContainer 
431 MyPointToPointHelper::Install (std::string aName, Ptr<Node> b)
432 {
433   Ptr<Node> a = Names::Find<Node> (aName);
434   return Install (a, b);
435 }
436
437 NetDeviceContainer 
438 MyPointToPointHelper::Install (std::string aName, std::string bName)
439 {
440   Ptr<Node> a = Names::Find<Node> (aName);
441   Ptr<Node> b = Names::Find<Node> (bName);
442   return Install (a, b);
443 }
444
445 } // namespace ns3