blob: 0809d58de144872f0787c3e9ce49a8fd9b50e5c3 [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 Afanasyev07827182011-12-13 01:07:32 -080069#include "ns3/point-to-point-net-device.h"
70#include "ns3/point-to-point-helper.h"
71
72#include "../model/ccnx-forwarding-strategy.h"
73
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -070074#include "ns3/ccnx-net-device-face.h"
75#include "ns3/ccnx-l3-protocol.h"
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -070076#include "ns3/ccnx-fib.h"
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -080077#include "ns3/node-list.h"
Alexander Afanasyev11453142011-11-25 16:13:33 -080078#include "ns3/loopback-net-device.h"
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -080079#include "ns3/global-router-interface.h"
Alexander Afanasyev11453142011-11-25 16:13:33 -080080#include "ns3/ipv4.h"
81#include "ns3/ipv4-global-routing.h"
82#include "ns3/ipv4-global-routing-ordered-nexthops.h"
83#include "ns3/ipv4-routing-helper.h"
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -080084#include "ns3/ipv4-global-routing-helper.h"
Alexander Afanasyev11453142011-11-25 16:13:33 -080085#include "ns3/data-rate.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070086
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -070087#include "ccnx-face-container.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070088#include "ccnx-stack-helper.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070089
90#include <limits>
91#include <map>
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -080092#include <boost/foreach.hpp>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070093
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -080094#define NDN_DEFAULT_DATA_SIZE 1024
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -080095
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070096NS_LOG_COMPONENT_DEFINE ("CcnxStackHelper");
97
98namespace ns3 {
99
100// Things are going to work differently here with respect to trace
101// file handling than in most places because the Tx and Rx trace
102// sources we are interested in are going to multiplex receive and
103// transmit callbacks for all Ccnx and face pairs through one
104// callback. We want packets to or from each distinct pair to go to
105// an individual file, so we have got to demultiplex the Ccnx and face
106// pair into a corresponding Ptr<PcapFileWrapper> at the callback.
107//
108// A complication in this situation is that the trace sources are
109// hooked on a protocol basis. There is no trace source hooked by an
110// Ccnx and face pair. This means that if we naively proceed to hook,
111// say, a drop trace for a given Ccnx with face 0, and then hook for
112// Ccnx with face 1 we will hook the drop trace twice and get two
113// callbacks per event. What we need to do is to hook the event once,
114// and that will result in a single callback per drop event, and the
115// trace source will provide the face which we filter on in the trace
116// sink.
117//
118// This has got to continue to work properly after the helper has been
119// destroyed; but must be cleaned up at the end of time to avoid
120// leaks. Global maps of protocol/face pairs to file objects seems to
121// fit the bill.
122//
Alexander Afanasyev11453142011-11-25 16:13:33 -0800123// typedef std::pair<Ptr<Ccnx>, uint32_t> FacePairCcnx;
124// typedef std::map<FacePairCcnx, Ptr<PcapFileWrapper> > FaceFileMapCcnx;
125// typedef std::map<FacePairCcnx, Ptr<OutputStreamWrapper> > FaceStreamMapCcnx;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700126
Alexander Afanasyev11453142011-11-25 16:13:33 -0800127// static FaceFileMapCcnx g_faceFileMapCcnx; /**< A mapping of Ccnx/face pairs to pcap files */
128// static FaceStreamMapCcnx g_faceStreamMapCcnx; /**< A mapping of Ccnx/face pairs to ascii streams */
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700129
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700130
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700131CcnxStackHelper::CcnxStackHelper ()
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800132 : m_limitsEnabled (false)
133 , m_needSetDefaultRoutes (false)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700134{
Alexander Afanasyev11453142011-11-25 16:13:33 -0800135 m_strategyFactory.SetTypeId ("ns3::CcnxFloodingStrategy");
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700136}
137
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700138CcnxStackHelper::~CcnxStackHelper ()
139{
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700140}
141
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700142void
Alexander Afanasyev11453142011-11-25 16:13:33 -0800143CcnxStackHelper::SetForwardingStrategy (std::string strategy)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700144{
Alexander Afanasyev11453142011-11-25 16:13:33 -0800145 m_strategyFactory.SetTypeId (strategy);
146}
147
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800148
149void
150CcnxStackHelper::SetDefaultRoutes (bool needSet)
151{
152 NS_LOG_FUNCTION (this << needSet);
153 m_needSetDefaultRoutes = needSet;
154}
155
Alexander Afanasyev11453142011-11-25 16:13:33 -0800156void
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800157CcnxStackHelper::EnableLimits (bool enable/* = true*/, Time avgRtt/*=Seconds(0.1)*/, uint32_t avgContentObject/*=1100*/, uint32_t avgInterest/*=40*/)
Alexander Afanasyev11453142011-11-25 16:13:33 -0800158{
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800159 NS_LOG_INFO ("EnableLimits: " << enable);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800160 m_limitsEnabled = enable;
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800161 m_avgContentObjectSize = avgContentObject;
162 m_avgInterestSize = avgInterest;
163 m_avgRtt = avgRtt;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700164}
165
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700166Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700167CcnxStackHelper::Install (NodeContainer c) const
168{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700169 Ptr<CcnxFaceContainer> faces = Create<CcnxFaceContainer> ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700170 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
171 {
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700172 faces->AddAll (Install (*i));
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700173 }
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700174 return faces;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700175}
176
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700177Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700178CcnxStackHelper::InstallAll (void) const
179{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700180 return Install (NodeContainer::GetGlobal ());
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700181}
182
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700183Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700184CcnxStackHelper::Install (Ptr<Node> node) const
185{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700186 // NS_ASSERT_MSG (m_forwarding, "SetForwardingHelper() should be set prior calling Install() method");
187 Ptr<CcnxFaceContainer> faces = Create<CcnxFaceContainer> ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700188
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700189 if (node->GetObject<Ccnx> () != 0)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700190 {
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700191 NS_FATAL_ERROR ("CcnxStackHelper::Install (): Installing "
192 "a CcnxStack to a node with an existing Ccnx object");
193 return 0;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700194 }
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700195
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700196 Ptr<CcnxFib> fib = CreateObject<CcnxFib> ();
197 node->AggregateObject (fib);
198
Ilya Moiseenkofbd0a8b2011-10-28 13:07:16 -0700199 Ptr<CcnxL3Protocol> ccnx = CreateObject<CcnxL3Protocol> ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700200 node->AggregateObject (ccnx);
201
Alexander Afanasyev11453142011-11-25 16:13:33 -0800202 ccnx->SetForwardingStrategy
203 (DynamicCast<CcnxForwardingStrategy> (m_strategyFactory.Create<Object> ()));
204
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700205 for (uint32_t index=0; index < node->GetNDevices (); index++)
206 {
Alexander Afanasyev11453142011-11-25 16:13:33 -0800207 Ptr<NetDevice> device = node->GetDevice (index);
208 if (DynamicCast<LoopbackNetDevice> (device) != 0)
209 continue; // don't create face for a LoopbackNetDevice
210
211 Ptr<CcnxNetDeviceFace> face = Create<CcnxNetDeviceFace> (node, device);
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800212
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800213 ccnx->AddFace (face);
214 NS_LOG_LOGIC ("Node " << node->GetId () << ": added CcnxNetDeviceFace as face #" << *face);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800215
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800216 if (m_needSetDefaultRoutes)
217 {
218 // default route with lowest priority possible
219 AddRoute (node, "/", face, std::numeric_limits<int32_t>::max ());
220 }
221
Alexander Afanasyev11453142011-11-25 16:13:33 -0800222 if (m_limitsEnabled)
223 {
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800224 NS_LOG_INFO ("Limits are enabled");
Alexander Afanasyev11453142011-11-25 16:13:33 -0800225 Ptr<PointToPointNetDevice> p2p = DynamicCast<PointToPointNetDevice> (device);
226 if (p2p == 0)
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800227 {
228 NS_LOG_INFO ("Non p2p interface");
229 continue; // only PointToPointNetDevice supports limits
230 }
Alexander Afanasyev11453142011-11-25 16:13:33 -0800231
232 // Setup bucket filtering
233 // Assume that we know average data packet size, and this size is equal default size
234 // Set maximum buckets (averaging over 1 second)
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700235
Alexander Afanasyev11453142011-11-25 16:13:33 -0800236 DataRateValue dataRate; device->GetAttribute ("DataRate", dataRate);
237
238 NS_LOG_INFO("DataRate for this link is " << dataRate.Get());
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800239
240 double maxInterestPackets = 1.0 * dataRate.Get ().GetBitRate () / 8.0 / m_avgContentObjectSize;
241 NS_LOG_INFO ("BucketMax: " << maxInterestPackets);
242
243 // Set bucket max to BDP
244 face->SetBucketMax (m_avgRtt.ToDouble (Time::S) * maxInterestPackets); // number of interests allowed
245 face->SetBucketLeak (maxInterestPackets);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800246 }
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700247
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700248 face->SetUp ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700249 faces->Add (face);
250 }
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700251
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700252 return faces;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700253}
254
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700255Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700256CcnxStackHelper::Install (std::string nodeName) const
257{
258 Ptr<Node> node = Names::Find<Node> (nodeName);
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700259 return Install (node);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700260}
261
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700262
263void
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800264CcnxStackHelper::AddRoute (Ptr<Node> node, std::string prefix, Ptr<CcnxFace> face, int32_t metric) const
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800265{
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800266 NS_LOG_LOGIC ("[" << node->GetId () << "]$ route add " << prefix << " via " << *face << " metric " << metric);
267
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800268 Ptr<CcnxFib> fib = node->GetObject<CcnxFib> ();
269
270 CcnxNameComponentsValue prefixValue;
271 prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
272 fib->Add (prefixValue.Get (), face, metric);
273}
274
275void
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800276CcnxStackHelper::AddRoute (std::string nodeName, std::string prefix, uint32_t faceId, int32_t metric) const
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700277{
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700278 Ptr<Node> node = Names::Find<Node> (nodeName);
279 NS_ASSERT_MSG (node != 0, "Node [" << nodeName << "] does not exist");
Alexander Afanasyeva4e3f852011-11-15 20:39:33 -0800280
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800281 Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
282 NS_ASSERT_MSG (ccnx != 0, "Ccnx stack should be installed on the node");
283
284 Ptr<CcnxFace> face = ccnx->GetFace (faceId);
285 NS_ASSERT_MSG (face != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
286
287 AddRoute (node, prefix, face, metric);
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700288}
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800289
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700290/*
Alexander Afanasyev11453142011-11-25 16:13:33 -0800291 void
292 CcnxStackHelper::AddRoute (Ptr<Node> node, std::string prefix, uint32_t faceId, int32_t metric)
293 {
294 NS_LOG_LOGIC ("[" << nodeName << "]$ route add " << prefix << " via " << faceId << " metric " << metric);
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700295
296 NS_ASSERT_MSG (node != 0, "Node does not exist");
297
298 Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
299 Ptr<CcnxFib> fib = node->GetObject<CcnxFib> ();
300 Ptr<CcnxFace> face = ccnx->GetFace (faceId);
301 NS_ASSERT_MSG (node != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
302
303 CcnxNameComponentsValue prefixValue;
304 prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
305 fib->Add (prefixValue.Get (), face, metric);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800306 }
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700307*/
Ilya Moiseenkoae394872011-11-15 17:56:36 -0800308
Alexander Afanasyev11453142011-11-25 16:13:33 -0800309// static void
310// CcnxL3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ccnx> ccnx, uint32_t face)
311// {
312// NS_LOG_FUNCTION (p << ccnx << face);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700313
Alexander Afanasyev11453142011-11-25 16:13:33 -0800314// //
315// // Since trace sources are independent of face, if we hook a source
316// // on a particular protocol we will get traces for all of its faces.
317// // We need to filter this to only report faces for which the user
318// // has expressed interest.
319// //
320// FacePairCcnx pair = std::make_pair (ccnx, face);
321// if (g_faceFileMapCcnx.find (pair) == g_faceFileMapCcnx.end ())
322// {
323// NS_LOG_INFO ("Ignoring packet to/from face " << face);
324// return;
325// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700326
Alexander Afanasyev11453142011-11-25 16:13:33 -0800327// Ptr<PcapFileWrapper> file = g_faceFileMapCcnx[pair];
328// file->Write (Simulator::Now (), p);
329// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700330
Alexander Afanasyev11453142011-11-25 16:13:33 -0800331// bool
332// CcnxStackHelper::PcapHooked (Ptr<Ccnx> ccnx)
333// {
334// for (FaceFileMapCcnx::const_iterator i = g_faceFileMapCcnx.begin ();
335// i != g_faceFileMapCcnx.end ();
336// ++i)
337// {
338// if ((*i).first.first == ccnx)
339// {
340// return true;
341// }
342// }
343// return false;
344// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700345
Alexander Afanasyev11453142011-11-25 16:13:33 -0800346// void
347// CcnxStackHelper::EnablePcapCcnxInternal (std::string prefix, Ptr<Ccnx> ccnx, uint32_t face, bool explicitFilename)
348// {
349// NS_LOG_FUNCTION (prefix << ccnx << face);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700350
Alexander Afanasyev11453142011-11-25 16:13:33 -0800351// //
352// // We have to create a file and a mapping from protocol/face to file
353// // irrespective of how many times we want to trace a particular protocol.
354// //
355// PcapHelper pcapHelper;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700356
Alexander Afanasyev11453142011-11-25 16:13:33 -0800357// std::string filename;
358// if (explicitFilename)
359// {
360// filename = prefix;
361// }
362// else
363// {
364// filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
365// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700366
Alexander Afanasyev11453142011-11-25 16:13:33 -0800367// Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700368
Alexander Afanasyev11453142011-11-25 16:13:33 -0800369// //
370// // However, we only hook the trace source once to avoid multiple trace sink
371// // calls per event (connect is independent of face).
372// //
373// if (!PcapHooked (ccnx))
374// {
375// //
376// // Ptr<Ccnx> is aggregated to node and CcnxL3Protocol is aggregated to
377// // node so we can get to CcnxL3Protocol through Ccnx.
378// //
379// Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
380// NS_ASSERT_MSG (ccnxL3Protocol, "CcnxStackHelper::EnablePcapCcnxInternal(): "
381// "m_ccnxEnabled and ccnxL3Protocol inconsistent");
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700382
Alexander Afanasyev11453142011-11-25 16:13:33 -0800383// bool result = ccnxL3Protocol->TraceConnectWithoutContext ("Tx", MakeCallback (&CcnxL3ProtocolRxTxSink));
384// NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal(): "
385// "Unable to connect ccnxL3Protocol \"Tx\"");
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700386
Alexander Afanasyev11453142011-11-25 16:13:33 -0800387// result = ccnxL3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&CcnxL3ProtocolRxTxSink));
388// NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal(): "
389// "Unable to connect ccnxL3Protocol \"Rx\"");
390// // cast result to void, to suppress ‘result’ set but not used compiler-warning
391// // for optimized builds
392// (void) result;
393// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700394
Alexander Afanasyev11453142011-11-25 16:13:33 -0800395// g_faceFileMapCcnx[std::make_pair (ccnx, face)] = file;
396// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700397
Alexander Afanasyev11453142011-11-25 16:13:33 -0800398// static void
399// CcnxL3ProtocolDropSinkWithoutContext (
400// Ptr<OutputStreamWrapper> stream,
401// Ptr<const Packet> packet,
402// CcnxL3Protocol::DropReason reason,
403// Ptr<Ccnx> ccnx,
404// uint32_t face)
405// {
406// //
407// // Since trace sources are independent of face, if we hook a source
408// // on a particular protocol we will get traces for all of its faces.
409// // We need to filter this to only report faces for which the user
410// // has expressed interest.
411// //
412// FacePairCcnx pair = std::make_pair (ccnx, face);
413// if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
414// {
415// NS_LOG_INFO ("Ignoring packet to/from face " << face);
416// return;
417// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700418
Alexander Afanasyev11453142011-11-25 16:13:33 -0800419// *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *packet << std::endl;
420// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700421
Alexander Afanasyev11453142011-11-25 16:13:33 -0800422// static void
423// CcnxL3ProtocolDropSinkWithContext (
424// Ptr<OutputStreamWrapper> stream,
425// std::string context,
426// Ptr<const Packet> packet,
427// CcnxL3Protocol::DropReason reason,
428// Ptr<Ccnx> ccnx,
429// uint32_t face)
430// {
431// //
432// // Since trace sources are independent of face, if we hook a source
433// // on a particular protocol we will get traces for all of its faces.
434// // We need to filter this to only report faces for which the user
435// // has expressed interest.
436// //
437// FacePairCcnx pair = std::make_pair (ccnx, face);
438// if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
439// {
440// NS_LOG_INFO ("Ignoring packet to/from face " << face);
441// return;
442// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700443
Alexander Afanasyev11453142011-11-25 16:13:33 -0800444// *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << "(" << face << ") "
445// << *packet << std::endl;
446// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700447
Alexander Afanasyev11453142011-11-25 16:13:33 -0800448// bool
449// CcnxStackHelper::AsciiHooked (Ptr<Ccnx> ccnx)
450// {
451// for ( FaceStreamMapCcnx::const_iterator i = g_faceStreamMapCcnx.begin ();
452// i != g_faceStreamMapCcnx.end ();
453// ++i)
454// {
455// if ((*i).first.first == ccnx)
456// {
457// return true;
458// }
459// }
460// return false;
461// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700462
Alexander Afanasyev11453142011-11-25 16:13:33 -0800463// void
464// CcnxStackHelper::EnableAsciiCcnxInternal (
465// Ptr<OutputStreamWrapper> stream,
466// std::string prefix,
467// Ptr<Ccnx> ccnx,
468// uint32_t face,
469// bool explicitFilename)
470// {
471// //
472// // Our trace sinks are going to use packet printing, so we have to
473// // make sure that is turned on.
474// //
475// Packet::EnablePrinting ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700476
Alexander Afanasyev11453142011-11-25 16:13:33 -0800477// //
478// // If we are not provided an OutputStreamWrapper, we are expected to create
479// // one using the usual trace filename conventions and hook WithoutContext
480// // since there will be one file per context and therefore the context would
481// // be redundant.
482// //
483// if (stream == 0)
484// {
485// //
486// // Set up an output stream object to deal with private ofstream copy
487// // constructor and lifetime issues. Let the helper decide the actual
488// // name of the file given the prefix.
489// //
490// // We have to create a stream and a mapping from protocol/face to
491// // stream irrespective of how many times we want to trace a particular
492// // protocol.
493// //
494// AsciiTraceHelper asciiTraceHelper;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700495
Alexander Afanasyev11453142011-11-25 16:13:33 -0800496// std::string filename;
497// if (explicitFilename)
498// {
499// filename = prefix;
500// }
501// else
502// {
503// filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
504// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700505
Alexander Afanasyev11453142011-11-25 16:13:33 -0800506// Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700507
Alexander Afanasyev11453142011-11-25 16:13:33 -0800508// //
509// // However, we only hook the trace sources once to avoid multiple trace sink
510// // calls per event (connect is independent of face).
511// //
512// if (!AsciiHooked (ccnx))
513// {
514// //
515// // The drop sink for the CcnxL3Protocol uses a different signature than
516// // the default sink, so we have to cook one up for ourselves. We can get
517// // to the Ptr<CcnxL3Protocol> through our Ptr<Ccnx> since they must both
518// // be aggregated to the same node.
519// //
520// Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
521// bool __attribute__ ((unused)) result = ccnxL3Protocol->TraceConnectWithoutContext ("Drop",
522// MakeBoundCallback (&CcnxL3ProtocolDropSinkWithoutContext, theStream));
523// NS_ASSERT_MSG (result == true, "CcnxStackHelper::EanableAsciiCcnxInternal(): "
524// "Unable to connect ccnxL3Protocol \"Drop\"");
525// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700526
Alexander Afanasyev11453142011-11-25 16:13:33 -0800527// g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = theStream;
528// return;
529// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700530
Alexander Afanasyev11453142011-11-25 16:13:33 -0800531// //
532// // If we are provided an OutputStreamWrapper, we are expected to use it, and
533// // to provide a context. We are free to come up with our own context if we
534// // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
535// // compatibility and simplicity, we just use Config::Connect and let it deal
536// // with the context.
537// //
538// // We need to associate the ccnx/face with a stream to express interest
539// // in tracing events on that pair, however, we only hook the trace sources
540// // once to avoid multiple trace sink calls per event (connect is independent
541// // of face).
542// //
543// if (!AsciiHooked (ccnx))
544// {
545// Ptr<Node> node = ccnx->GetObject<Node> ();
546// std::ostringstream oss;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700547
Alexander Afanasyev11453142011-11-25 16:13:33 -0800548// //
549// // This has all kinds of parameters coming with, so we have to cook up our
550// // own sink.
551// //
552// oss.str ("");
553// oss << "/NodeList/" << node->GetId () << "/$ns3::CcnxL3Protocol/Drop";
554// Config::Connect (oss.str (), MakeBoundCallback (&CcnxL3ProtocolDropSinkWithContext, stream));
555// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700556
Alexander Afanasyev11453142011-11-25 16:13:33 -0800557// g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = stream;
558// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700559
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800560void
561CcnxStackHelper::InstallFakeGlobalRoutes ()
562{
563 for (NodeList::Iterator node = NodeList::Begin ();
564 node != NodeList::End ();
565 node ++)
566 {
567 NS_ASSERT_MSG ((*node)->GetObject<Ipv4> () != 0,
568 "InternetStack should be installed on all nodes");
569
570 NS_ASSERT_MSG (Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops>
571 (
572 (*node)->GetObject<Ipv4> ()->GetRoutingProtocol ()
Alexander Afanasyev11453142011-11-25 16:13:33 -0800573 ),
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800574 "InternetStack should have Ipv4GlobalRoutingOrderedNexthops as routing protocol");
575 // Example:
576 //
577 // Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingUnorderedNexthops");
578 // stack.SetRoutingHelper (ipv4RoutingHelper);
579 //
580
581 Ptr<GlobalRouter> globalRouter = (*node)->GetObject<GlobalRouter> ();
582 if (globalRouter == 0) continue;
583
584 globalRouter->InjectRoute (Ipv4Address((*node)->GetId ()), Ipv4Mask("255.255.255.255"));
585 }
586
587 Ipv4GlobalRoutingHelper::PopulateAllPossibleRoutingTables ();
588}
589
590void
591CcnxStackHelper::InstallRouteTo (Ptr<Node> destNode)
592{
593 std::ostringstream destPrefix;
594 destPrefix << "/" << destNode->GetId ();
595
596 Ipv4Address destIpv4 = Ipv4Address(destNode->GetId ());
597
598 for (NodeList::Iterator node = NodeList::Begin ();
599 node != NodeList::End ();
600 node ++)
601 {
602 if (destNode == *node) continue;
603
604 Ptr<Ccnx> ccnx = (*node)->GetObject<Ccnx> ();
605 NS_ASSERT_MSG (ccnx != 0, "CCNx stack should be installed on all nodes");
606
607 Ptr<Ipv4> ipv4 = (*node)->GetObject<Ipv4> ();
608 NS_ASSERT_MSG (ipv4 != 0,
609 "InternetStack should be installed on all nodes");
610
611 Ptr<Ipv4GlobalRoutingOrderedNexthops> routing =
612 Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops> (ipv4->GetRoutingProtocol ());
613 NS_ASSERT_MSG (routing != 0, "Ipv4GlobalRoutingOrderedNexthops should be used in InternetStack");
614
615 Ptr<Ipv4GlobalRoutingOrderedNexthops::EntryContainer>
616 routes = routing->Lookup (destIpv4);
617
618 NS_ASSERT_MSG (routes != 0, "Should not happen... Call the developer");
619
620 BOOST_FOREACH (const Ipv4RoutingTableEntry &entry, *routes)
621 {
622 Ptr<NetDevice> netDevice = ipv4->GetNetDevice (entry.GetInterface ());
623 NS_ASSERT_MSG (netDevice != 0, "Should never happen. Call the popos");
624
625 Ptr<CcnxFace> face = ccnx->GetFaceByNetDevice (netDevice);
626 NS_ASSERT_MSG (face != 0, "Definitely should never happen. Call the president");
627
628 AddRoute (*node, destPrefix.str(), face, entry.GetMetric ());
629 }
630 }
631}
632
633void
634CcnxStackHelper::InstallRoutesToAll ()
635{
636 for (NodeList::Iterator node = NodeList::Begin ();
637 node != NodeList::End ();
638 node ++)
639 {
640 InstallRouteTo (*node);
641 }
642}
643
644
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700645} // namespace ns3