blob: 3bc5ce98609655fdfb63cbdc728f0217ee2c01a4 [file] [log] [blame]
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyev45b92d42011-08-14 23:11:38 -07002/*
3 * Copyright (c) 2011 UCLA
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 *
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -070018 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
Ilya Moiseenkofbd0a8b2011-10-28 13:07:16 -070019 * Ilya Moiseenko <iliamo@cs.ucla.edu>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070020 */
21
22/**
23 * \ingroup ccnx
24 * \defgroup CcnxStackModel Ccnx Stack Model
25 *
26 * \section CcnxStackTracingModel Tracing in the Ccnx Stack
27 *
28 * The ccnx stack provides a number of trace sources in its various
29 * protocol implementations. These trace sources can be hooked using your own
30 * custom trace code, or you can use our helper functions in some cases to
31 * arrange for tracing to be enabled.
32 *
33 * \subsection CcnxStackCcnxTracingModel Tracing in Ccnx
34 *
35 * The Ccnx layer three protocol provides three trace hooks. These are the
36 * "Tx" (ns3::CcnxL3Protocol::m_txTrace), "Rx" (ns3::CcnxL3Protocol::m_rxTrace)
37 * and "Drop" (ns3::CcnxL3Protocol::m_dropTrace) trace sources.
38 *
39 * The "Tx" trace is fired in a number of situations, all of which indicate that
40 * a given packet is about to be sent down to a given ns3::CcnxFace.
41 *
42 * - \todo list Tx trace events
43 *
44 * The "Rx" trace is fired when a packet is passed from the device up to the
45 * ns3::CcnxL3Protocol::Receive function.
46 *
47 * - In the receive function, the CcnxFaceList is iterated, and if the
48 * CcnxFace corresponding to the receiving device is found to be in the
49 * UP state, the trace is fired.
50 *
51 * The "Drop" trace is fired in any case where the packet is dropped (in both
52 * the transmit and receive paths).
53 *
54 * - \todo list Drop trace events
55 */
56
57#include "ns3/assert.h"
58#include "ns3/log.h"
59#include "ns3/object.h"
60#include "ns3/names.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070061#include "ns3/packet-socket-factory.h"
62#include "ns3/config.h"
63#include "ns3/simulator.h"
64#include "ns3/string.h"
65#include "ns3/net-device.h"
66#include "ns3/callback.h"
67#include "ns3/node.h"
68#include "ns3/core-config.h"
Alexander Afanasyevc74a6022011-08-15 20:01:35 -070069#include "ns3/ccnx-forwarding-strategy.h"
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -070070#include "ns3/ccnx-net-device-face.h"
71#include "ns3/ccnx-l3-protocol.h"
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -070072#include "ns3/ccnx-fib.h"
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -080073#include "ns3/node-list.h"
74#include "ns3/ipv4.h"
75#include "ns3/ipv4-routing-helper.h"
76#include "ns3/ipv4-global-routing-ordered-nexthops.h"
77#include "ns3/global-router-interface.h"
78#include "ns3/ipv4-global-routing-helper.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070079
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -070080#include "ccnx-face-container.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070081#include "ccnx-stack-helper.h"
82#include "ccnx-forwarding-helper.h"
83
84#include <limits>
85#include <map>
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -080086#include <boost/foreach.hpp>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070087
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -080088#define NDN_DEFAULT_DATA_SIZE 1024
89#define NDN_INTEREST_RESET_PERIOD Seconds(0.01)
90
91
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070092NS_LOG_COMPONENT_DEFINE ("CcnxStackHelper");
93
94namespace ns3 {
95
96// Things are going to work differently here with respect to trace
97// file handling than in most places because the Tx and Rx trace
98// sources we are interested in are going to multiplex receive and
99// transmit callbacks for all Ccnx and face pairs through one
100// callback. We want packets to or from each distinct pair to go to
101// an individual file, so we have got to demultiplex the Ccnx and face
102// pair into a corresponding Ptr<PcapFileWrapper> at the callback.
103//
104// A complication in this situation is that the trace sources are
105// hooked on a protocol basis. There is no trace source hooked by an
106// Ccnx and face pair. This means that if we naively proceed to hook,
107// say, a drop trace for a given Ccnx with face 0, and then hook for
108// Ccnx with face 1 we will hook the drop trace twice and get two
109// callbacks per event. What we need to do is to hook the event once,
110// and that will result in a single callback per drop event, and the
111// trace source will provide the face which we filter on in the trace
112// sink.
113//
114// This has got to continue to work properly after the helper has been
115// destroyed; but must be cleaned up at the end of time to avoid
116// leaks. Global maps of protocol/face pairs to file objects seems to
117// fit the bill.
118//
119typedef std::pair<Ptr<Ccnx>, uint32_t> FacePairCcnx;
120typedef std::map<FacePairCcnx, Ptr<PcapFileWrapper> > FaceFileMapCcnx;
121typedef std::map<FacePairCcnx, Ptr<OutputStreamWrapper> > FaceStreamMapCcnx;
122
123static FaceFileMapCcnx g_faceFileMapCcnx; /**< A mapping of Ccnx/face pairs to pcap files */
124static FaceStreamMapCcnx g_faceStreamMapCcnx; /**< A mapping of Ccnx/face pairs to ascii streams */
125
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700126
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700127CcnxStackHelper::CcnxStackHelper ()
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700128 : m_forwardingHelper (Ccnx::NDN_FLOODING)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700129{
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700130}
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700131
132CcnxStackHelper::CcnxStackHelper (Ccnx::ForwardingStrategy strategy)
133 : m_forwardingHelper (strategy)
134{
135}
136
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700137CcnxStackHelper::~CcnxStackHelper ()
138{
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700139}
140
141CcnxStackHelper::CcnxStackHelper (const CcnxStackHelper &o)
142{
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700143}
144
145CcnxStackHelper &
146CcnxStackHelper::operator = (const CcnxStackHelper &o)
147{
148 if (this == &o)
149 {
150 return *this;
151 }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700152 return *this;
153}
154
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700155void
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700156CcnxStackHelper::SetForwardingStrategy (Ccnx::ForwardingStrategy strategy)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700157{
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700158 CcnxForwardingHelper newForwardingHelper (strategy);
159 m_forwardingHelper = newForwardingHelper;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700160}
161
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700162Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700163CcnxStackHelper::Install (NodeContainer c) const
164{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700165 Ptr<CcnxFaceContainer> faces = Create<CcnxFaceContainer> ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700166 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
167 {
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700168 faces->AddAll (Install (*i));
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700169 }
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700170 return faces;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700171}
172
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700173Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700174CcnxStackHelper::InstallAll (void) const
175{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700176 return Install (NodeContainer::GetGlobal ());
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700177}
178
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700179// void
180// CcnxStackHelper::CreateAndAggregateObjectFromTypeId (Ptr<Node> node, const std::string typeId)
181// {
182// ObjectFactory factory;
183// factory.SetTypeId (typeId);
184// Ptr<Object> protocol = factory.Create <Object> ();
185// node->AggregateObject (protocol);
186// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700187
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700188Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700189CcnxStackHelper::Install (Ptr<Node> node) const
190{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700191 // NS_ASSERT_MSG (m_forwarding, "SetForwardingHelper() should be set prior calling Install() method");
192 Ptr<CcnxFaceContainer> faces = Create<CcnxFaceContainer> ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700193
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700194 if (node->GetObject<Ccnx> () != 0)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700195 {
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700196 NS_FATAL_ERROR ("CcnxStackHelper::Install (): Installing "
197 "a CcnxStack to a node with an existing Ccnx object");
198 return 0;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700199 }
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700200
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700201 Ptr<CcnxFib> fib = CreateObject<CcnxFib> ();
202 node->AggregateObject (fib);
203
Ilya Moiseenkofbd0a8b2011-10-28 13:07:16 -0700204 Ptr<CcnxL3Protocol> ccnx = CreateObject<CcnxL3Protocol> ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700205 node->AggregateObject (ccnx);
206
Ilya Moiseenkofbd0a8b2011-10-28 13:07:16 -0700207 Ptr<CcnxPit> pit = ccnx->GetPit();
Ilya Moiseenkoae394872011-11-15 17:56:36 -0800208 NS_LOG_INFO("NODE->GetNDevices()="<<node->GetNDevices());
209
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700210 for (uint32_t index=0; index < node->GetNDevices (); index++)
211 {
Ilya Moiseenkoae394872011-11-15 17:56:36 -0800212 Ptr<PointToPointNetDevice> device = DynamicCast<PointToPointNetDevice>(node->GetDevice(index));
213 if(device == 0)
214 continue;
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700215
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700216 Ptr<CcnxNetDeviceFace> face = Create<CcnxNetDeviceFace> (node->GetDevice (index));
217 face->SetNode (node);
218 uint32_t __attribute__ ((unused)) face_id = ccnx->AddFace (face);
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700219 NS_LOG_LOGIC ("Node " << node->GetId () << ": added CcnxNetDeviceFace as face #" << face_id);
Ilya Moiseenkofbd0a8b2011-10-28 13:07:16 -0700220 // Setup bucket filtering
221 // Assume that we know average data packet size, and this size is equal default size
222 // Set maximum buckets (averaging over 1 second)
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700223
Ilya Moiseenkofbd0a8b2011-10-28 13:07:16 -0700224 DataRateValue dataRate;
225 device->GetAttribute ("DataRate", dataRate);
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700226 NS_LOG_INFO("DataRate for this link is " << dataRate.Get());
Ilya Moiseenko8c193dc2011-11-16 16:00:37 -0800227 pit->maxBucketsPerFace[face->GetId()] = 0.1 * dataRate.Get().GetBitRate () /(NDN_DEFAULT_DATA_SIZE + sizeof(CcnxInterestHeader));
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700228 NS_LOG_INFO("maxBucketsPerFace["<<face->GetId()<<"] = " << pit->maxBucketsPerFace[face->GetId()]);
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800229 pit->leakSize[face->GetId()] = 0.97 * NDN_INTEREST_RESET_PERIOD.ToDouble(Time::S) * dataRate.Get().GetBitRate () / (NDN_DEFAULT_DATA_SIZE + sizeof(CcnxInterestHeader));
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700230 NS_LOG_INFO("pit->leakSize["<<face->GetId()<<"] = " << pit->leakSize[face->GetId()]);
231
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800232 NS_LOG_INFO("Face #" << face_id << " is turned on");
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700233 face->SetUp ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700234 faces->Add (face);
235 }
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700236
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700237 m_forwardingHelper.SetForwarding (ccnx, pit);
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800238
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -0800239 // ccnx->ScheduleLeakage ();
Ilya Moiseenkod83eb0d2011-11-16 15:23:46 -0800240
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700241 return faces;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700242}
243
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700244Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700245CcnxStackHelper::Install (std::string nodeName) const
246{
247 Ptr<Node> node = Names::Find<Node> (nodeName);
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700248 return Install (node);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700249}
250
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700251
252void
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800253CcnxStackHelper::AddRoute (Ptr<Node> node, std::string prefix, Ptr<CcnxFace> face, int32_t metric)
254{
255 Ptr<CcnxFib> fib = node->GetObject<CcnxFib> ();
256
257 CcnxNameComponentsValue prefixValue;
258 prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
259 fib->Add (prefixValue.Get (), face, metric);
260}
261
262void
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700263CcnxStackHelper::AddRoute (std::string nodeName, std::string prefix, uint32_t faceId, int32_t metric)
264{
265 NS_LOG_LOGIC ("[" << nodeName << "]$ route add " << prefix << " via " << faceId << " metric " << metric);
266
267 Ptr<Node> node = Names::Find<Node> (nodeName);
268 NS_ASSERT_MSG (node != 0, "Node [" << nodeName << "] does not exist");
Alexander Afanasyeva4e3f852011-11-15 20:39:33 -0800269
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800270 Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
271 NS_ASSERT_MSG (ccnx != 0, "Ccnx stack should be installed on the node");
272
273 Ptr<CcnxFace> face = ccnx->GetFace (faceId);
274 NS_ASSERT_MSG (face != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
275
276 AddRoute (node, prefix, face, metric);
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700277}
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700278/*
279void
280CcnxStackHelper::AddRoute (Ptr<Node> node, std::string prefix, uint32_t faceId, int32_t metric)
281{
282 NS_LOG_LOGIC ("[" << nodeName << "]$ route add " << prefix << " via " << faceId << " metric " << metric);
283
284 NS_ASSERT_MSG (node != 0, "Node does not exist");
285
286 Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
287 Ptr<CcnxFib> fib = node->GetObject<CcnxFib> ();
288 Ptr<CcnxFace> face = ccnx->GetFace (faceId);
289 NS_ASSERT_MSG (node != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
290
291 CcnxNameComponentsValue prefixValue;
292 prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
293 fib->Add (prefixValue.Get (), face, metric);
294}
295*/
Ilya Moiseenkoae394872011-11-15 17:56:36 -0800296
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700297static void
298CcnxL3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ccnx> ccnx, uint32_t face)
299{
300 NS_LOG_FUNCTION (p << ccnx << face);
301
302 //
303 // Since trace sources are independent of face, if we hook a source
304 // on a particular protocol we will get traces for all of its faces.
305 // We need to filter this to only report faces for which the user
306 // has expressed interest.
307 //
308 FacePairCcnx pair = std::make_pair (ccnx, face);
309 if (g_faceFileMapCcnx.find (pair) == g_faceFileMapCcnx.end ())
310 {
311 NS_LOG_INFO ("Ignoring packet to/from face " << face);
312 return;
313 }
314
315 Ptr<PcapFileWrapper> file = g_faceFileMapCcnx[pair];
316 file->Write (Simulator::Now (), p);
317}
318
319bool
320CcnxStackHelper::PcapHooked (Ptr<Ccnx> ccnx)
321{
322 for (FaceFileMapCcnx::const_iterator i = g_faceFileMapCcnx.begin ();
323 i != g_faceFileMapCcnx.end ();
324 ++i)
325 {
326 if ((*i).first.first == ccnx)
327 {
328 return true;
329 }
330 }
331 return false;
332}
333
334void
335CcnxStackHelper::EnablePcapCcnxInternal (std::string prefix, Ptr<Ccnx> ccnx, uint32_t face, bool explicitFilename)
336{
337 NS_LOG_FUNCTION (prefix << ccnx << face);
338
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700339 //
340 // We have to create a file and a mapping from protocol/face to file
341 // irrespective of how many times we want to trace a particular protocol.
342 //
343 PcapHelper pcapHelper;
344
345 std::string filename;
346 if (explicitFilename)
347 {
348 filename = prefix;
349 }
350 else
351 {
352 filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
353 }
354
355 Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
356
357 //
358 // However, we only hook the trace source once to avoid multiple trace sink
359 // calls per event (connect is independent of face).
360 //
361 if (!PcapHooked (ccnx))
362 {
363 //
364 // Ptr<Ccnx> is aggregated to node and CcnxL3Protocol is aggregated to
365 // node so we can get to CcnxL3Protocol through Ccnx.
366 //
367 Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
368 NS_ASSERT_MSG (ccnxL3Protocol, "CcnxStackHelper::EnablePcapCcnxInternal(): "
369 "m_ccnxEnabled and ccnxL3Protocol inconsistent");
370
371 bool result = ccnxL3Protocol->TraceConnectWithoutContext ("Tx", MakeCallback (&CcnxL3ProtocolRxTxSink));
372 NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal(): "
373 "Unable to connect ccnxL3Protocol \"Tx\"");
374
375 result = ccnxL3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&CcnxL3ProtocolRxTxSink));
376 NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal(): "
377 "Unable to connect ccnxL3Protocol \"Rx\"");
378 // cast result to void, to suppress ‘result’ set but not used compiler-warning
379 // for optimized builds
380 (void) result;
381 }
382
383 g_faceFileMapCcnx[std::make_pair (ccnx, face)] = file;
384}
385
386static void
387CcnxL3ProtocolDropSinkWithoutContext (
388 Ptr<OutputStreamWrapper> stream,
389 Ptr<const Packet> packet,
390 CcnxL3Protocol::DropReason reason,
391 Ptr<Ccnx> ccnx,
392 uint32_t face)
393{
394 //
395 // Since trace sources are independent of face, if we hook a source
396 // on a particular protocol we will get traces for all of its faces.
397 // We need to filter this to only report faces for which the user
398 // has expressed interest.
399 //
400 FacePairCcnx pair = std::make_pair (ccnx, face);
401 if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
402 {
403 NS_LOG_INFO ("Ignoring packet to/from face " << face);
404 return;
405 }
406
407 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *packet << std::endl;
408}
409
410static void
411CcnxL3ProtocolDropSinkWithContext (
412 Ptr<OutputStreamWrapper> stream,
413 std::string context,
414 Ptr<const Packet> packet,
415 CcnxL3Protocol::DropReason reason,
416 Ptr<Ccnx> ccnx,
417 uint32_t face)
418{
419 //
420 // Since trace sources are independent of face, if we hook a source
421 // on a particular protocol we will get traces for all of its faces.
422 // We need to filter this to only report faces for which the user
423 // has expressed interest.
424 //
425 FacePairCcnx pair = std::make_pair (ccnx, face);
426 if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
427 {
428 NS_LOG_INFO ("Ignoring packet to/from face " << face);
429 return;
430 }
431
432 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << "(" << face << ") "
433 << *packet << std::endl;
434}
435
436bool
437CcnxStackHelper::AsciiHooked (Ptr<Ccnx> ccnx)
438{
439 for ( FaceStreamMapCcnx::const_iterator i = g_faceStreamMapCcnx.begin ();
440 i != g_faceStreamMapCcnx.end ();
441 ++i)
442 {
443 if ((*i).first.first == ccnx)
444 {
445 return true;
446 }
447 }
448 return false;
449}
450
451void
452CcnxStackHelper::EnableAsciiCcnxInternal (
453 Ptr<OutputStreamWrapper> stream,
454 std::string prefix,
455 Ptr<Ccnx> ccnx,
456 uint32_t face,
457 bool explicitFilename)
458{
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700459 //
460 // Our trace sinks are going to use packet printing, so we have to
461 // make sure that is turned on.
462 //
463 Packet::EnablePrinting ();
464
465 //
466 // If we are not provided an OutputStreamWrapper, we are expected to create
467 // one using the usual trace filename conventions and hook WithoutContext
468 // since there will be one file per context and therefore the context would
469 // be redundant.
470 //
471 if (stream == 0)
472 {
473 //
474 // Set up an output stream object to deal with private ofstream copy
475 // constructor and lifetime issues. Let the helper decide the actual
476 // name of the file given the prefix.
477 //
478 // We have to create a stream and a mapping from protocol/face to
479 // stream irrespective of how many times we want to trace a particular
480 // protocol.
481 //
482 AsciiTraceHelper asciiTraceHelper;
483
484 std::string filename;
485 if (explicitFilename)
486 {
487 filename = prefix;
488 }
489 else
490 {
491 filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
492 }
493
494 Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
495
496 //
497 // However, we only hook the trace sources once to avoid multiple trace sink
498 // calls per event (connect is independent of face).
499 //
500 if (!AsciiHooked (ccnx))
501 {
502 //
503 // The drop sink for the CcnxL3Protocol uses a different signature than
504 // the default sink, so we have to cook one up for ourselves. We can get
505 // to the Ptr<CcnxL3Protocol> through our Ptr<Ccnx> since they must both
506 // be aggregated to the same node.
507 //
508 Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
509 bool __attribute__ ((unused)) result = ccnxL3Protocol->TraceConnectWithoutContext ("Drop",
510 MakeBoundCallback (&CcnxL3ProtocolDropSinkWithoutContext, theStream));
511 NS_ASSERT_MSG (result == true, "CcnxStackHelper::EanableAsciiCcnxInternal(): "
512 "Unable to connect ccnxL3Protocol \"Drop\"");
513 }
514
515 g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = theStream;
516 return;
517 }
518
519 //
520 // If we are provided an OutputStreamWrapper, we are expected to use it, and
521 // to provide a context. We are free to come up with our own context if we
522 // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
523 // compatibility and simplicity, we just use Config::Connect and let it deal
524 // with the context.
525 //
526 // We need to associate the ccnx/face with a stream to express interest
527 // in tracing events on that pair, however, we only hook the trace sources
528 // once to avoid multiple trace sink calls per event (connect is independent
529 // of face).
530 //
531 if (!AsciiHooked (ccnx))
532 {
533 Ptr<Node> node = ccnx->GetObject<Node> ();
534 std::ostringstream oss;
535
536 //
537 // This has all kinds of parameters coming with, so we have to cook up our
538 // own sink.
539 //
540 oss.str ("");
541 oss << "/NodeList/" << node->GetId () << "/$ns3::CcnxL3Protocol/Drop";
542 Config::Connect (oss.str (), MakeBoundCallback (&CcnxL3ProtocolDropSinkWithContext, stream));
543 }
544
545 g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = stream;
546}
547
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800548void
549CcnxStackHelper::InstallFakeGlobalRoutes ()
550{
551 for (NodeList::Iterator node = NodeList::Begin ();
552 node != NodeList::End ();
553 node ++)
554 {
555 NS_ASSERT_MSG ((*node)->GetObject<Ipv4> () != 0,
556 "InternetStack should be installed on all nodes");
557
558 NS_ASSERT_MSG (Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops>
559 (
560 (*node)->GetObject<Ipv4> ()->GetRoutingProtocol ()
561 ),
562 "InternetStack should have Ipv4GlobalRoutingOrderedNexthops as routing protocol");
563 // Example:
564 //
565 // Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingUnorderedNexthops");
566 // stack.SetRoutingHelper (ipv4RoutingHelper);
567 //
568
569 Ptr<GlobalRouter> globalRouter = (*node)->GetObject<GlobalRouter> ();
570 if (globalRouter == 0) continue;
571
572 globalRouter->InjectRoute (Ipv4Address((*node)->GetId ()), Ipv4Mask("255.255.255.255"));
573 }
574
575 Ipv4GlobalRoutingHelper::PopulateAllPossibleRoutingTables ();
576}
577
578void
579CcnxStackHelper::InstallRouteTo (Ptr<Node> destNode)
580{
581 std::ostringstream destPrefix;
582 destPrefix << "/" << destNode->GetId ();
583
584 Ipv4Address destIpv4 = Ipv4Address(destNode->GetId ());
585
586 for (NodeList::Iterator node = NodeList::Begin ();
587 node != NodeList::End ();
588 node ++)
589 {
590 if (destNode == *node) continue;
591
592 Ptr<Ccnx> ccnx = (*node)->GetObject<Ccnx> ();
593 NS_ASSERT_MSG (ccnx != 0, "CCNx stack should be installed on all nodes");
594
595 Ptr<Ipv4> ipv4 = (*node)->GetObject<Ipv4> ();
596 NS_ASSERT_MSG (ipv4 != 0,
597 "InternetStack should be installed on all nodes");
598
599 Ptr<Ipv4GlobalRoutingOrderedNexthops> routing =
600 Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops> (ipv4->GetRoutingProtocol ());
601 NS_ASSERT_MSG (routing != 0, "Ipv4GlobalRoutingOrderedNexthops should be used in InternetStack");
602
603 Ptr<Ipv4GlobalRoutingOrderedNexthops::EntryContainer>
604 routes = routing->Lookup (destIpv4);
605
606 NS_ASSERT_MSG (routes != 0, "Should not happen... Call the developer");
607
608 BOOST_FOREACH (const Ipv4RoutingTableEntry &entry, *routes)
609 {
610 Ptr<NetDevice> netDevice = ipv4->GetNetDevice (entry.GetInterface ());
611 NS_ASSERT_MSG (netDevice != 0, "Should never happen. Call the popos");
612
613 Ptr<CcnxFace> face = ccnx->GetFaceByNetDevice (netDevice);
614 NS_ASSERT_MSG (face != 0, "Definitely should never happen. Call the president");
615
616 AddRoute (*node, destPrefix.str(), face, entry.GetMetric ());
617 }
618 }
619}
620
621void
622CcnxStackHelper::InstallRoutesToAll ()
623{
624 for (NodeList::Iterator node = NodeList::Begin ();
625 node != NodeList::End ();
626 node ++)
627 {
628 InstallRouteTo (*node);
629 }
630}
631
632
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700633} // namespace ns3