Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(300)

Side by Side Diff: src/routing/click/helper/click-internet-stack-helper.cc

Issue 3988043: NS-3 Click Integration (Closed)
Patch Set: Incorporates Mathieu's comments Created 13 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2008 INRIA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 * Author: Faker Moatamri <faker.moatamri@sophia.inria.fr>
20 * Author: Lalith Suresh <suresh.lalith@gmail.com>
21 */
22
23 #ifdef NS3_CLICK
Tom Henderson 2011/02/18 02:06:37 again, shouldn't this be conditionally compiled su
24
25 #include "ns3/assert.h"
26 #include "ns3/log.h"
27 #include "ns3/object.h"
28 #include "ns3/names.h"
29 #include "ns3/ipv4.h"
30 #include "ns3/packet-socket-factory.h"
31 #include "ns3/config.h"
32 #include "ns3/simulator.h"
33 #include "ns3/string.h"
34 #include "ns3/net-device.h"
35 #include "ns3/callback.h"
36 #include "ns3/node.h"
37 #include "ns3/core-config.h"
38 #include "ns3/arp-l3-protocol.h"
39 #include "ns3/ipv4-click-routing.h"
40 #include "ns3/ipv4-l3-click-protocol.h"
41 #include "ns3/trace-helper.h"
42 #include "click-internet-stack-helper.h"
43 #include <limits>
44 #include <map>
45
46 NS_LOG_COMPONENT_DEFINE ("ClickInternetStackHelper");
47
48 namespace ns3 {
49
50 #define INTERFACE_CONTEXT
51
52 typedef std::pair<Ptr<Ipv4>, uint32_t> InterfacePairIpv4;·
53 typedef std::map<InterfacePairIpv4, Ptr<PcapFileWrapper> > InterfaceFileMapIpv4;
54 typedef std::map<InterfacePairIpv4, Ptr<OutputStreamWrapper> > InterfaceStreamMa pIpv4;
55
56 static InterfaceFileMapIpv4 g_interfaceFileMapIpv4; /**< A mapping of Ipv4/inter face pairs to pcap files */
57 static InterfaceStreamMapIpv4 g_interfaceStreamMapIpv4; /**< A mapping of Ipv4/i nterface pairs to ascii streams */
58
59 ClickInternetStackHelper::ClickInternetStackHelper ()
60 : m_ipv4Enabled (true)
61 {
62 Initialize ();
63 }
64
65 // private method called by both constructor and Reset ()
66 void
67 ClickInternetStackHelper::Initialize ()
68 {
69 SetTcp ("ns3::TcpL4Protocol");
70 }
71
72 ClickInternetStackHelper::~ClickInternetStackHelper ()
73 {
74 }
75
76 ClickInternetStackHelper::ClickInternetStackHelper (const ClickInternetStackHelp er &o)
77 {
78 m_ipv4Enabled = o.m_ipv4Enabled;
79 m_tcpFactory = o.m_tcpFactory;
80 }
81
82 ClickInternetStackHelper &
83 ClickInternetStackHelper::operator = (const ClickInternetStackHelper &o)
84 {
85 if (this == &o)
86 {
87 return *this;
88 }
89 return *this;
90 }
91
92 void
93 ClickInternetStackHelper::Reset (void)
94 {
95 m_ipv4Enabled = true;
96 Initialize ();
97 }
98
99 void
100 ClickInternetStackHelper::SetTcp (const std::string tid)
101 {
102 m_tcpFactory.SetTypeId (tid);
103 }
104
105 void·
106 ClickInternetStackHelper::SetTcp (std::string tid, std::string n0, const Attribu teValue &v0)
107 {
108 m_tcpFactory.SetTypeId (tid);
109 m_tcpFactory.Set (n0,v0);
110 }
111
112 void
113 ClickInternetStackHelper::SetClickFile (NodeContainer c, std::string clickfile)
114 {
115 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
116 {
117 SetClickFile (*i, clickfile);
118 }
119 }
120
121 void
122 ClickInternetStackHelper::SetClickFile (Ptr<Node> node, std::string clickfile)
123 {
124 m_nodeToClickFileMap.insert (std::make_pair (node, clickfile));
125 }
126
127 void
128 ClickInternetStackHelper::SetRoutingTableElement (NodeContainer c, std::string r t)
129 {
130 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
131 {
132 SetRoutingTableElement (*i, rt);
133 }
134 }
135
136 void
137 ClickInternetStackHelper::SetRoutingTableElement (Ptr<Node> node, std::string rt )
138 {
139 m_nodeToRoutingTableElementMap.insert (std::make_pair (node, rt));
140 }
141
142 void·
143 ClickInternetStackHelper::Install (NodeContainer c) const
144 {
145 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
146 {
147 Install (*i);
148 }
149 }
150
151 void·
152 ClickInternetStackHelper::InstallAll (void) const
153 {
154 Install (NodeContainer::GetGlobal ());
155 }
156
157 void
158 ClickInternetStackHelper::CreateAndAggregateObjectFromTypeId (Ptr<Node> node, co nst std::string typeId)
159 {
160 ObjectFactory factory;
161 factory.SetTypeId (typeId);
162 Ptr<Object> protocol = factory.Create <Object> ();
163 node->AggregateObject (protocol);
164 }
165
166 void
167 ClickInternetStackHelper::Install (Ptr<Node> node) const
168 {
169 if (m_ipv4Enabled)
170 {
171 if (node->GetObject<Ipv4> () != 0)
172 {
173 NS_FATAL_ERROR ("ClickInternetStackHelper::Install (): Aggregating "·
174 "an InternetStack to a node with an existing Ipv4 obje ct");
175 return;
176 }
177
178 CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol");
179 CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3ClickProtocol");
180 CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol");
181 CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol");
182 node->AggregateObject (m_tcpFactory.Create<Object> ());
183 Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
184 node->AggregateObject (factory);
185 // Set routing
186 Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
187 Ptr<Ipv4ClickRouting> ipv4Routing = CreateObject<Ipv4ClickRouting> ();
188 std::map< Ptr<Node>, std::string >::const_iterator it;
189 it = m_nodeToClickFileMap.find (node);
190
191 if (it != m_nodeToClickFileMap.end ())
192 {
193 ipv4Routing->SetClickFile (it->second);
194 }
195
196 it = m_nodeToRoutingTableElementMap.find (node);
197 if (it != m_nodeToRoutingTableElementMap.end ())
198 {
199 ipv4Routing->SetClickRoutingTableElement (it->second);
200 }
201 ipv4->SetRoutingProtocol (ipv4Routing);
202 node->AggregateObject (ipv4Routing);
203 }
204 }
205
206 void
207 ClickInternetStackHelper::Install (std::string nodeName) const
208 {
209 Ptr<Node> node = Names::Find<Node> (nodeName);
210 Install (node);
211 }
212
213 static void
214 Ipv4L3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ipv4> ipv4, uint32_t interface)
215 {
216 NS_LOG_FUNCTION (p << ipv4 << interface);
217
218 //
219 // Since trace sources are independent of interface, if we hook a source
220 // on a particular protocol we will get traces for all of its interfaces.
221 // We need to filter this to only report interfaces for which the user·
222 // has expressed interest.
223 //
224 InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
225 if (g_interfaceFileMapIpv4.find (pair) == g_interfaceFileMapIpv4.end ())
226 {
227 NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
228 return;
229 }
230
231 Ptr<PcapFileWrapper> file = g_interfaceFileMapIpv4[pair];
232 file->Write(Simulator::Now(), p);
233 }
234
235 bool
236 ClickInternetStackHelper::PcapHooked (Ptr<Ipv4> ipv4)
237 {
238 for ( InterfaceFileMapIpv4::const_iterator i = g_interfaceFileMapIpv4.begin ( );·
239 i != g_interfaceFileMapIpv4.end ();·
240 ++i)
241 {
242 if ((*i).first.first == ipv4)
243 {
244 return true;
245 }
246 }
247 return false;
248 }
249
250 void·
251 ClickInternetStackHelper::EnablePcapIpv4Internal (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename)
252 {
253 NS_LOG_FUNCTION (prefix << ipv4 << interface);
254
255 if (!m_ipv4Enabled)
256 {
257 NS_LOG_INFO ("Call to enable Ipv4 pcap tracing but Ipv4 not enabled");
258 return;
259 }
260
261 //
262 // We have to create a file and a mapping from protocol/interface to file·
263 // irrespective of how many times we want to trace a particular protocol.
264 //
265 PcapHelper pcapHelper;
266
267 std::string filename;
268 if (explicitFilename)
269 {
270 filename = prefix;
271 }
272 else
273 {
274 filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ipv4, interfac e);
275 }
276
277 Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, Pc apHelper::DLT_RAW);
278
279 //
280 // However, we only hook the trace source once to avoid multiple trace sink
281 // calls per event (connect is independent of interface).
282 //
283 if (!PcapHooked (ipv4))
284 {
285 //
286 // Ptr<Ipv4> is aggregated to node and Ipv4L3Protocol is aggregated to·
287 // node so we can get to Ipv4L3Protocol through Ipv4.
288 //
289 Ptr<Ipv4L3Protocol> ipv4L3Protocol = ipv4->GetObject<Ipv4L3Protocol> ();
290 NS_ASSERT_MSG (ipv4L3Protocol, "ClickInternetStackHelper::EnablePcapIpv4In ternal(): "
291 "m_ipv4Enabled and ipv4L3Protocol inconsistent");
292
293 bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Tx", MakeCallba ck (&Ipv4L3ProtocolRxTxSink));
294 NS_ASSERT_MSG (result == true, "ClickInternetStackHelper::EnablePcapIpv4In ternal(): "
295 "Unable to connect ipv4L3Protocol \"Tx\"");
296
297 result = ipv4L3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (& Ipv4L3ProtocolRxTxSink));
298 NS_ASSERT_MSG (result == true, "ClickInternetStackHelper::EnablePcapIpv4In ternal(): "
299 "Unable to connect ipv4L3Protocol \"Rx\"");
300 }
301
302 g_interfaceFileMapIpv4[std::make_pair (ipv4, interface)] = file;
303 }
304
305 static void
306 Ipv4L3ProtocolDropSinkWithoutContext (
307 Ptr<OutputStreamWrapper> stream,
308 Ipv4Header const &header,·
309 Ptr<const Packet> packet,
310 Ipv4L3Protocol::DropReason reason,·
311 Ptr<Ipv4> ipv4,·
312 uint32_t interface)
313 {
314 //
315 // Since trace sources are independent of interface, if we hook a source
316 // on a particular protocol we will get traces for all of its interfaces.
317 // We need to filter this to only report interfaces for which the user·
318 // has expressed interest.
319 //
320 InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
321 if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
322 {
323 NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
324 return;
325 }
326
327 Ptr<Packet> p = packet->Copy ();
328 p->AddHeader (header);
329 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
330 }
331
332 static void
333 Ipv4L3ProtocolDropSinkWithContext (
334 Ptr<OutputStreamWrapper> stream,
335 std::string context,
336 Ipv4Header const &header,·
337 Ptr<const Packet> packet,
338 Ipv4L3Protocol::DropReason reason,·
339 Ptr<Ipv4> ipv4,·
340 uint32_t interface)
341 {
342 //
343 // Since trace sources are independent of interface, if we hook a source
344 // on a particular protocol we will get traces for all of its interfaces.
345 // We need to filter this to only report interfaces for which the user·
346 // has expressed interest.
347 //
348 InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
349 if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
350 {
351 NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
352 return;
353 }
354
355 Ptr<Packet> p = packet->Copy ();
356 p->AddHeader (header);
357 #ifdef INTERFACE_CONTEXT
358 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << con text << "(" << interface << ") "·
359 << *p << std::endl;
360 #else
361 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << con text << " " << *p << std::endl;
362 #endif
363 }
364
365 bool
366 ClickInternetStackHelper::AsciiHooked (Ptr<Ipv4> ipv4)
367 {
368 for ( InterfaceStreamMapIpv4::const_iterator i = g_interfaceStreamMapIpv4.beg in ();·
369 i != g_interfaceStreamMapIpv4.end ();·
370 ++i)
371 {
372 if ((*i).first.first == ipv4)
373 {
374 return true;
375 }
376 }
377 return false;
378 }
379
380 void·
381 ClickInternetStackHelper::EnableAsciiIpv4Internal (
382 Ptr<OutputStreamWrapper> stream,·
383 std::string prefix,·
384 Ptr<Ipv4> ipv4,·
385 uint32_t interface,
386 bool explicitFilename)
387 {
388 if (!m_ipv4Enabled)
389 {
390 NS_LOG_INFO ("Call to enable Ipv4 ascii tracing but Ipv4 not enabled");
391 return;
392 }
393
394 //
395 // Our trace sinks are going to use packet printing, so we have to·
396 // make sure that is turned on.
397 //
398 Packet::EnablePrinting ();
399
400 //
401 // If we are not provided an OutputStreamWrapper, we are expected to create·
402 // one using the usual trace filename conventions and hook WithoutContext
403 // since there will be one file per context and therefore the context would
404 // be redundant.
405 //
406 if (stream == 0)
407 {
408 //
409 // Set up an output stream object to deal with private ofstream copy·
410 // constructor and lifetime issues. Let the helper decide the actual
411 // name of the file given the prefix.
412 //
413 // We have to create a stream and a mapping from protocol/interface to·
414 // stream irrespective of how many times we want to trace a particular·
415 // protocol.
416 //
417 AsciiTraceHelper asciiTraceHelper;
418
419 std::string filename;
420 if (explicitFilename)
421 {
422 filename = prefix;
423 }
424 else
425 {
426 filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ipv4 , interface);
427 }
428
429 Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (fi lename);
430
431 //
432 // However, we only hook the trace sources once to avoid multiple trace si nk
433 // calls per event (connect is independent of interface).
434 //
435 if (!AsciiHooked (ipv4))
436 {
437 //
438 // We can use the default drop sink for the ArpL3Protocol since it has
439 // the usual signature. We can get to the Ptr<ArpL3Protocol> through
440 // our Ptr<Ipv4> since they must both be aggregated to the same node.
441 //
442 Ptr<ArpL3Protocol> arpL3Protocol = ipv4->GetObject<ArpL3Protocol> ();
443 asciiTraceHelper.HookDefaultDropSinkWithoutContext<ArpL3Protocol> (arp L3Protocol, "Drop", theStream);
444
445 //
446 // The drop sink for the Ipv4L3Protocol uses a different signature tha n
447 // the default sink, so we have to cook one up for ourselves. We can get
448 // to the Ptr<Ipv4L3Protocol> through our Ptr<Ipv4> since they must bo th·
449 // be aggregated to the same node.
450 //
451 Ptr<Ipv4L3Protocol> ipv4L3Protocol = ipv4->GetObject<Ipv4L3Protocol> ( );
452 bool __attribute__ ((unused)) result = ipv4L3Protocol->TraceConnectWit houtContext ("Drop",·
453 MakeBoundCallback (&Ipv4L3ProtocolDropSinkWithoutContext,
454 theStream));
455 NS_ASSERT_MSG (result == true, "ClickInternetStackHelper::EanableAscii Ipv4Internal(): "
456 "Unable to connect ipv4L3Protocol \"Drop\"");
457 }
458
459 g_interfaceStreamMapIpv4[std::make_pair (ipv4, interface)] = theStream;
460 return;
461 }
462
463 //
464 // If we are provided an OutputStreamWrapper, we are expected to use it, and
465 // to provide a context. We are free to come up with our own context if we
466 // want, and use the AsciiTraceHelper Hook*WithContext functions, but for·
467 // compatibility and simplicity, we just use Config::Connect and let it deal
468 // with the context.
469 //
470 // We need to associate the ipv4/interface with a stream to express interest
471 // in tracing events on that pair, however, we only hook the trace sources·
472 // once to avoid multiple trace sink calls per event (connect is independent
473 // of interface).
474 //
475 if (!AsciiHooked (ipv4))
476 {
477 Ptr<Node> node = ipv4->GetObject<Node> ();
478 std::ostringstream oss;
479
480 //
481 // For the ARP Drop, we are going to use the default trace sink provided b y·
482 // the ascii trace helper. There is actually no AsciiTraceHelper in sight·······
483 // here, but the default trace sinks are actually publicly available stati c·
484 // functions that are always there waiting for just such a case.
485 //
486 oss << "/NodeList/" << node->GetId () << "/$ns3::ArpL3Protocol/Drop";
487 Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::Default DropSinkWithContext, stream));
488
489 //
490 // This has all kinds of parameters coming with, so we have to cook up our
491 // own sink.
492 //
493 oss.str ("");
494 oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv4L3Protocol/Drop";
495 Config::Connect (oss.str (), MakeBoundCallback (&Ipv4L3ProtocolDropSinkWit hContext, stream));
496 }
497
498 g_interfaceStreamMapIpv4[std::make_pair (ipv4, interface)] = stream;
499 }
500
501 } // namespace ns3
502
503 #endif // NS3_CLICK
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b