blob: 62c5f821e05380dfd2ab472ed1a5e72bc86a107c [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"
Alexander Afanasyevf9f4eb02011-12-16 01:51:14 -080073#include "../model/ccnx-net-device-face.h"
74#include "../model/ccnx-l3-protocol.h"
75#include "../model/ccnx-fib.h"
Alexander Afanasyev07827182011-12-13 01:07:32 -080076
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"
Alexander Afanasyevf9f4eb02011-12-16 01:51:14 -080082#include "../utils/ipv4-global-routing-ordered-nexthops.h"
83
Alexander Afanasyev11453142011-11-25 16:13:33 -080084#include "ns3/ipv4-routing-helper.h"
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -080085#include "ns3/ipv4-global-routing-helper.h"
Alexander Afanasyev11453142011-11-25 16:13:33 -080086#include "ns3/data-rate.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070087
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -070088#include "ccnx-face-container.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070089#include "ccnx-stack-helper.h"
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070090
91#include <limits>
92#include <map>
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -080093#include <boost/foreach.hpp>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070094
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -080095#define NDN_DEFAULT_DATA_SIZE 1024
Alexander Afanasyeva5bbe0e2011-11-22 17:28:39 -080096
Alexander Afanasyev45b92d42011-08-14 23:11:38 -070097NS_LOG_COMPONENT_DEFINE ("CcnxStackHelper");
98
99namespace ns3 {
100
101// Things are going to work differently here with respect to trace
102// file handling than in most places because the Tx and Rx trace
103// sources we are interested in are going to multiplex receive and
104// transmit callbacks for all Ccnx and face pairs through one
105// callback. We want packets to or from each distinct pair to go to
106// an individual file, so we have got to demultiplex the Ccnx and face
107// pair into a corresponding Ptr<PcapFileWrapper> at the callback.
108//
109// A complication in this situation is that the trace sources are
110// hooked on a protocol basis. There is no trace source hooked by an
111// Ccnx and face pair. This means that if we naively proceed to hook,
112// say, a drop trace for a given Ccnx with face 0, and then hook for
113// Ccnx with face 1 we will hook the drop trace twice and get two
114// callbacks per event. What we need to do is to hook the event once,
115// and that will result in a single callback per drop event, and the
116// trace source will provide the face which we filter on in the trace
117// sink.
118//
119// This has got to continue to work properly after the helper has been
120// destroyed; but must be cleaned up at the end of time to avoid
121// leaks. Global maps of protocol/face pairs to file objects seems to
122// fit the bill.
123//
Alexander Afanasyev11453142011-11-25 16:13:33 -0800124// typedef std::pair<Ptr<Ccnx>, uint32_t> FacePairCcnx;
125// typedef std::map<FacePairCcnx, Ptr<PcapFileWrapper> > FaceFileMapCcnx;
126// typedef std::map<FacePairCcnx, Ptr<OutputStreamWrapper> > FaceStreamMapCcnx;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700127
Alexander Afanasyev11453142011-11-25 16:13:33 -0800128// static FaceFileMapCcnx g_faceFileMapCcnx; /**< A mapping of Ccnx/face pairs to pcap files */
129// static FaceStreamMapCcnx g_faceStreamMapCcnx; /**< A mapping of Ccnx/face pairs to ascii streams */
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700130
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700131
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700132CcnxStackHelper::CcnxStackHelper ()
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800133 : m_limitsEnabled (false)
134 , m_needSetDefaultRoutes (false)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700135{
Alexander Afanasyev11453142011-11-25 16:13:33 -0800136 m_strategyFactory.SetTypeId ("ns3::CcnxFloodingStrategy");
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700137}
138
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700139CcnxStackHelper::~CcnxStackHelper ()
140{
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700141}
142
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700143void
Alexander Afanasyev11453142011-11-25 16:13:33 -0800144CcnxStackHelper::SetForwardingStrategy (std::string strategy)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700145{
Alexander Afanasyev11453142011-11-25 16:13:33 -0800146 m_strategyFactory.SetTypeId (strategy);
147}
148
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800149
150void
151CcnxStackHelper::SetDefaultRoutes (bool needSet)
152{
153 NS_LOG_FUNCTION (this << needSet);
154 m_needSetDefaultRoutes = needSet;
155}
156
Alexander Afanasyev11453142011-11-25 16:13:33 -0800157void
Alexander Afanasyev33d62312012-01-09 13:50:20 -0800158CcnxStackHelper::EnableLimits (bool enable/* = true*/,
159 Time avgRtt/*=Seconds(0.1)*/,
160 uint32_t avgContentObject/*=1100*/,
161 uint32_t avgInterest/*=40*/)
Alexander Afanasyev11453142011-11-25 16:13:33 -0800162{
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800163 NS_LOG_INFO ("EnableLimits: " << enable);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800164 m_limitsEnabled = enable;
Alexander Afanasyev8f5a9bb2011-12-18 19:49:02 -0800165 m_avgRtt = avgRtt;
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800166 m_avgContentObjectSize = avgContentObject;
167 m_avgInterestSize = avgInterest;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700168}
169
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700170Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700171CcnxStackHelper::Install (NodeContainer c) const
172{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700173 Ptr<CcnxFaceContainer> faces = Create<CcnxFaceContainer> ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700174 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
175 {
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700176 faces->AddAll (Install (*i));
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700177 }
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700178 return faces;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700179}
180
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700181Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700182CcnxStackHelper::InstallAll (void) const
183{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700184 return Install (NodeContainer::GetGlobal ());
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700185}
186
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700187Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700188CcnxStackHelper::Install (Ptr<Node> node) const
189{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700190 // NS_ASSERT_MSG (m_forwarding, "SetForwardingHelper() should be set prior calling Install() method");
191 Ptr<CcnxFaceContainer> faces = Create<CcnxFaceContainer> ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700192
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700193 if (node->GetObject<Ccnx> () != 0)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700194 {
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700195 NS_FATAL_ERROR ("CcnxStackHelper::Install (): Installing "
196 "a CcnxStack to a node with an existing Ccnx object");
197 return 0;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700198 }
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700199
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700200 Ptr<CcnxFib> fib = CreateObject<CcnxFib> ();
201 node->AggregateObject (fib);
202
Ilya Moiseenkofbd0a8b2011-10-28 13:07:16 -0700203 Ptr<CcnxL3Protocol> ccnx = CreateObject<CcnxL3Protocol> ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700204 node->AggregateObject (ccnx);
205
Alexander Afanasyevf377b332011-12-16 15:32:12 -0800206 ccnx->SetForwardingStrategy (m_strategyFactory.Create<CcnxForwardingStrategy> ());
Alexander Afanasyev11453142011-11-25 16:13:33 -0800207
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700208 for (uint32_t index=0; index < node->GetNDevices (); index++)
209 {
Alexander Afanasyev11453142011-11-25 16:13:33 -0800210 Ptr<NetDevice> device = node->GetDevice (index);
211 if (DynamicCast<LoopbackNetDevice> (device) != 0)
212 continue; // don't create face for a LoopbackNetDevice
213
Alexander Afanasyevcbe92ae2011-12-16 13:06:18 -0800214 Ptr<CcnxNetDeviceFace> face = CreateObject<CcnxNetDeviceFace> (node, device);
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800215
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800216 ccnx->AddFace (face);
217 NS_LOG_LOGIC ("Node " << node->GetId () << ": added CcnxNetDeviceFace as face #" << *face);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800218
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800219 if (m_needSetDefaultRoutes)
220 {
221 // default route with lowest priority possible
222 AddRoute (node, "/", face, std::numeric_limits<int32_t>::max ());
223 }
224
Alexander Afanasyev11453142011-11-25 16:13:33 -0800225 if (m_limitsEnabled)
226 {
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800227 NS_LOG_INFO ("Limits are enabled");
Alexander Afanasyev11453142011-11-25 16:13:33 -0800228 Ptr<PointToPointNetDevice> p2p = DynamicCast<PointToPointNetDevice> (device);
229 if (p2p == 0)
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800230 {
231 NS_LOG_INFO ("Non p2p interface");
232 continue; // only PointToPointNetDevice supports limits
233 }
Alexander Afanasyev11453142011-11-25 16:13:33 -0800234
235 // Setup bucket filtering
236 // Assume that we know average data packet size, and this size is equal default size
237 // Set maximum buckets (averaging over 1 second)
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700238
Alexander Afanasyev11453142011-11-25 16:13:33 -0800239 DataRateValue dataRate; device->GetAttribute ("DataRate", dataRate);
240
241 NS_LOG_INFO("DataRate for this link is " << dataRate.Get());
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800242
Alexander Afanasyev33d62312012-01-09 13:50:20 -0800243 double maxInterestPackets = 1.0 * dataRate.Get ().GetBitRate () / 8.0 / (m_avgContentObjectSize + m_avgInterestSize);
Alexander Afanasyev8f5a9bb2011-12-18 19:49:02 -0800244 NS_LOG_INFO ("Max packets per second: " << maxInterestPackets);
245 NS_LOG_INFO ("Max burst: " << m_avgRtt.ToDouble (Time::S) * maxInterestPackets);
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800246
247 // Set bucket max to BDP
248 face->SetBucketMax (m_avgRtt.ToDouble (Time::S) * maxInterestPackets); // number of interests allowed
249 face->SetBucketLeak (maxInterestPackets);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800250 }
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700251
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700252 face->SetUp ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700253 faces->Add (face);
254 }
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700255
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700256 return faces;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700257}
258
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700259Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700260CcnxStackHelper::Install (std::string nodeName) const
261{
262 Ptr<Node> node = Names::Find<Node> (nodeName);
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700263 return Install (node);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700264}
265
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700266
267void
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800268CcnxStackHelper::AddRoute (Ptr<Node> node, std::string prefix, Ptr<CcnxFace> face, int32_t metric) const
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800269{
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800270 NS_LOG_LOGIC ("[" << node->GetId () << "]$ route add " << prefix << " via " << *face << " metric " << metric);
271
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800272 Ptr<CcnxFib> fib = node->GetObject<CcnxFib> ();
273
274 CcnxNameComponentsValue prefixValue;
275 prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
276 fib->Add (prefixValue.Get (), face, metric);
277}
278
279void
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800280CcnxStackHelper::AddRoute (std::string nodeName, std::string prefix, uint32_t faceId, int32_t metric) const
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700281{
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700282 Ptr<Node> node = Names::Find<Node> (nodeName);
283 NS_ASSERT_MSG (node != 0, "Node [" << nodeName << "] does not exist");
Alexander Afanasyeva4e3f852011-11-15 20:39:33 -0800284
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800285 Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
286 NS_ASSERT_MSG (ccnx != 0, "Ccnx stack should be installed on the node");
287
288 Ptr<CcnxFace> face = ccnx->GetFace (faceId);
289 NS_ASSERT_MSG (face != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
290
291 AddRoute (node, prefix, face, metric);
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700292}
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800293
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700294/*
Alexander Afanasyev11453142011-11-25 16:13:33 -0800295 void
296 CcnxStackHelper::AddRoute (Ptr<Node> node, std::string prefix, uint32_t faceId, int32_t metric)
297 {
298 NS_LOG_LOGIC ("[" << nodeName << "]$ route add " << prefix << " via " << faceId << " metric " << metric);
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700299
300 NS_ASSERT_MSG (node != 0, "Node does not exist");
301
302 Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
303 Ptr<CcnxFib> fib = node->GetObject<CcnxFib> ();
304 Ptr<CcnxFace> face = ccnx->GetFace (faceId);
305 NS_ASSERT_MSG (node != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
306
307 CcnxNameComponentsValue prefixValue;
308 prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
309 fib->Add (prefixValue.Get (), face, metric);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800310 }
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700311*/
Ilya Moiseenkoae394872011-11-15 17:56:36 -0800312
Alexander Afanasyev11453142011-11-25 16:13:33 -0800313// static void
314// CcnxL3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ccnx> ccnx, uint32_t face)
315// {
316// NS_LOG_FUNCTION (p << ccnx << face);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700317
Alexander Afanasyev11453142011-11-25 16:13:33 -0800318// //
319// // Since trace sources are independent of face, if we hook a source
320// // on a particular protocol we will get traces for all of its faces.
321// // We need to filter this to only report faces for which the user
322// // has expressed interest.
323// //
324// FacePairCcnx pair = std::make_pair (ccnx, face);
325// if (g_faceFileMapCcnx.find (pair) == g_faceFileMapCcnx.end ())
326// {
327// NS_LOG_INFO ("Ignoring packet to/from face " << face);
328// return;
329// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700330
Alexander Afanasyev11453142011-11-25 16:13:33 -0800331// Ptr<PcapFileWrapper> file = g_faceFileMapCcnx[pair];
332// file->Write (Simulator::Now (), p);
333// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700334
Alexander Afanasyev11453142011-11-25 16:13:33 -0800335// bool
336// CcnxStackHelper::PcapHooked (Ptr<Ccnx> ccnx)
337// {
338// for (FaceFileMapCcnx::const_iterator i = g_faceFileMapCcnx.begin ();
339// i != g_faceFileMapCcnx.end ();
340// ++i)
341// {
342// if ((*i).first.first == ccnx)
343// {
344// return true;
345// }
346// }
347// return false;
348// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700349
Alexander Afanasyev11453142011-11-25 16:13:33 -0800350// void
351// CcnxStackHelper::EnablePcapCcnxInternal (std::string prefix, Ptr<Ccnx> ccnx, uint32_t face, bool explicitFilename)
352// {
353// NS_LOG_FUNCTION (prefix << ccnx << face);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700354
Alexander Afanasyev11453142011-11-25 16:13:33 -0800355// //
356// // We have to create a file and a mapping from protocol/face to file
357// // irrespective of how many times we want to trace a particular protocol.
358// //
359// PcapHelper pcapHelper;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700360
Alexander Afanasyev11453142011-11-25 16:13:33 -0800361// std::string filename;
362// if (explicitFilename)
363// {
364// filename = prefix;
365// }
366// else
367// {
368// filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
369// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700370
Alexander Afanasyev11453142011-11-25 16:13:33 -0800371// Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700372
Alexander Afanasyev11453142011-11-25 16:13:33 -0800373// //
374// // However, we only hook the trace source once to avoid multiple trace sink
375// // calls per event (connect is independent of face).
376// //
377// if (!PcapHooked (ccnx))
378// {
379// //
380// // Ptr<Ccnx> is aggregated to node and CcnxL3Protocol is aggregated to
381// // node so we can get to CcnxL3Protocol through Ccnx.
382// //
383// Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
384// NS_ASSERT_MSG (ccnxL3Protocol, "CcnxStackHelper::EnablePcapCcnxInternal(): "
385// "m_ccnxEnabled and ccnxL3Protocol inconsistent");
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700386
Alexander Afanasyev11453142011-11-25 16:13:33 -0800387// bool result = ccnxL3Protocol->TraceConnectWithoutContext ("Tx", MakeCallback (&CcnxL3ProtocolRxTxSink));
388// NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal(): "
389// "Unable to connect ccnxL3Protocol \"Tx\"");
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700390
Alexander Afanasyev11453142011-11-25 16:13:33 -0800391// result = ccnxL3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&CcnxL3ProtocolRxTxSink));
392// NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal(): "
393// "Unable to connect ccnxL3Protocol \"Rx\"");
394// // cast result to void, to suppress ‘result’ set but not used compiler-warning
395// // for optimized builds
396// (void) result;
397// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700398
Alexander Afanasyev11453142011-11-25 16:13:33 -0800399// g_faceFileMapCcnx[std::make_pair (ccnx, face)] = file;
400// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700401
Alexander Afanasyev11453142011-11-25 16:13:33 -0800402// static void
403// CcnxL3ProtocolDropSinkWithoutContext (
404// Ptr<OutputStreamWrapper> stream,
405// Ptr<const Packet> packet,
406// CcnxL3Protocol::DropReason reason,
407// Ptr<Ccnx> ccnx,
408// uint32_t face)
409// {
410// //
411// // Since trace sources are independent of face, if we hook a source
412// // on a particular protocol we will get traces for all of its faces.
413// // We need to filter this to only report faces for which the user
414// // has expressed interest.
415// //
416// FacePairCcnx pair = std::make_pair (ccnx, face);
417// if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
418// {
419// NS_LOG_INFO ("Ignoring packet to/from face " << face);
420// return;
421// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700422
Alexander Afanasyev11453142011-11-25 16:13:33 -0800423// *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *packet << std::endl;
424// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700425
Alexander Afanasyev11453142011-11-25 16:13:33 -0800426// static void
427// CcnxL3ProtocolDropSinkWithContext (
428// Ptr<OutputStreamWrapper> stream,
429// std::string context,
430// Ptr<const Packet> packet,
431// CcnxL3Protocol::DropReason reason,
432// Ptr<Ccnx> ccnx,
433// uint32_t face)
434// {
435// //
436// // Since trace sources are independent of face, if we hook a source
437// // on a particular protocol we will get traces for all of its faces.
438// // We need to filter this to only report faces for which the user
439// // has expressed interest.
440// //
441// FacePairCcnx pair = std::make_pair (ccnx, face);
442// if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
443// {
444// NS_LOG_INFO ("Ignoring packet to/from face " << face);
445// return;
446// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700447
Alexander Afanasyev11453142011-11-25 16:13:33 -0800448// *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << "(" << face << ") "
449// << *packet << std::endl;
450// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700451
Alexander Afanasyev11453142011-11-25 16:13:33 -0800452// bool
453// CcnxStackHelper::AsciiHooked (Ptr<Ccnx> ccnx)
454// {
455// for ( FaceStreamMapCcnx::const_iterator i = g_faceStreamMapCcnx.begin ();
456// i != g_faceStreamMapCcnx.end ();
457// ++i)
458// {
459// if ((*i).first.first == ccnx)
460// {
461// return true;
462// }
463// }
464// return false;
465// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700466
Alexander Afanasyev11453142011-11-25 16:13:33 -0800467// void
468// CcnxStackHelper::EnableAsciiCcnxInternal (
469// Ptr<OutputStreamWrapper> stream,
470// std::string prefix,
471// Ptr<Ccnx> ccnx,
472// uint32_t face,
473// bool explicitFilename)
474// {
475// //
476// // Our trace sinks are going to use packet printing, so we have to
477// // make sure that is turned on.
478// //
479// Packet::EnablePrinting ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700480
Alexander Afanasyev11453142011-11-25 16:13:33 -0800481// //
482// // If we are not provided an OutputStreamWrapper, we are expected to create
483// // one using the usual trace filename conventions and hook WithoutContext
484// // since there will be one file per context and therefore the context would
485// // be redundant.
486// //
487// if (stream == 0)
488// {
489// //
490// // Set up an output stream object to deal with private ofstream copy
491// // constructor and lifetime issues. Let the helper decide the actual
492// // name of the file given the prefix.
493// //
494// // We have to create a stream and a mapping from protocol/face to
495// // stream irrespective of how many times we want to trace a particular
496// // protocol.
497// //
498// AsciiTraceHelper asciiTraceHelper;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700499
Alexander Afanasyev11453142011-11-25 16:13:33 -0800500// std::string filename;
501// if (explicitFilename)
502// {
503// filename = prefix;
504// }
505// else
506// {
507// filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
508// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700509
Alexander Afanasyev11453142011-11-25 16:13:33 -0800510// Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700511
Alexander Afanasyev11453142011-11-25 16:13:33 -0800512// //
513// // However, we only hook the trace sources once to avoid multiple trace sink
514// // calls per event (connect is independent of face).
515// //
516// if (!AsciiHooked (ccnx))
517// {
518// //
519// // The drop sink for the CcnxL3Protocol uses a different signature than
520// // the default sink, so we have to cook one up for ourselves. We can get
521// // to the Ptr<CcnxL3Protocol> through our Ptr<Ccnx> since they must both
522// // be aggregated to the same node.
523// //
524// Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
525// bool __attribute__ ((unused)) result = ccnxL3Protocol->TraceConnectWithoutContext ("Drop",
526// MakeBoundCallback (&CcnxL3ProtocolDropSinkWithoutContext, theStream));
527// NS_ASSERT_MSG (result == true, "CcnxStackHelper::EanableAsciiCcnxInternal(): "
528// "Unable to connect ccnxL3Protocol \"Drop\"");
529// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700530
Alexander Afanasyev11453142011-11-25 16:13:33 -0800531// g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = theStream;
532// return;
533// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700534
Alexander Afanasyev11453142011-11-25 16:13:33 -0800535// //
536// // If we are provided an OutputStreamWrapper, we are expected to use it, and
537// // to provide a context. We are free to come up with our own context if we
538// // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
539// // compatibility and simplicity, we just use Config::Connect and let it deal
540// // with the context.
541// //
542// // We need to associate the ccnx/face with a stream to express interest
543// // in tracing events on that pair, however, we only hook the trace sources
544// // once to avoid multiple trace sink calls per event (connect is independent
545// // of face).
546// //
547// if (!AsciiHooked (ccnx))
548// {
549// Ptr<Node> node = ccnx->GetObject<Node> ();
550// std::ostringstream oss;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700551
Alexander Afanasyev11453142011-11-25 16:13:33 -0800552// //
553// // This has all kinds of parameters coming with, so we have to cook up our
554// // own sink.
555// //
556// oss.str ("");
557// oss << "/NodeList/" << node->GetId () << "/$ns3::CcnxL3Protocol/Drop";
558// Config::Connect (oss.str (), MakeBoundCallback (&CcnxL3ProtocolDropSinkWithContext, stream));
559// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700560
Alexander Afanasyev11453142011-11-25 16:13:33 -0800561// g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = stream;
562// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700563
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800564void
Alexander Afanasyev36d5c2a2012-01-02 19:09:19 -0800565CcnxStackHelper::InstallFakeGlobalRoutesImpl ()
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800566{
567 for (NodeList::Iterator node = NodeList::Begin ();
568 node != NodeList::End ();
569 node ++)
570 {
571 NS_ASSERT_MSG ((*node)->GetObject<Ipv4> () != 0,
572 "InternetStack should be installed on all nodes");
573
574 NS_ASSERT_MSG (Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops>
575 (
576 (*node)->GetObject<Ipv4> ()->GetRoutingProtocol ()
Alexander Afanasyev11453142011-11-25 16:13:33 -0800577 ),
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800578 "InternetStack should have Ipv4GlobalRoutingOrderedNexthops as routing protocol");
579 // Example:
580 //
581 // Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingUnorderedNexthops");
582 // stack.SetRoutingHelper (ipv4RoutingHelper);
583 //
584
585 Ptr<GlobalRouter> globalRouter = (*node)->GetObject<GlobalRouter> ();
586 if (globalRouter == 0) continue;
587
588 globalRouter->InjectRoute (Ipv4Address((*node)->GetId ()), Ipv4Mask("255.255.255.255"));
589 }
Alexander Afanasyev36d5c2a2012-01-02 19:09:19 -0800590}
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800591
Alexander Afanasyev36d5c2a2012-01-02 19:09:19 -0800592void
593CcnxStackHelper::InstallFakeGlobalRoutes ()
594{
595 InstallFakeGlobalRoutesImpl ();
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800596 Ipv4GlobalRoutingHelper::PopulateAllPossibleRoutingTables ();
597}
598
599void
600CcnxStackHelper::InstallRouteTo (Ptr<Node> destNode)
601{
602 std::ostringstream destPrefix;
603 destPrefix << "/" << destNode->GetId ();
604
605 Ipv4Address destIpv4 = Ipv4Address(destNode->GetId ());
606
607 for (NodeList::Iterator node = NodeList::Begin ();
608 node != NodeList::End ();
609 node ++)
610 {
611 if (destNode == *node) continue;
612
613 Ptr<Ccnx> ccnx = (*node)->GetObject<Ccnx> ();
614 NS_ASSERT_MSG (ccnx != 0, "CCNx stack should be installed on all nodes");
615
616 Ptr<Ipv4> ipv4 = (*node)->GetObject<Ipv4> ();
617 NS_ASSERT_MSG (ipv4 != 0,
618 "InternetStack should be installed on all nodes");
619
620 Ptr<Ipv4GlobalRoutingOrderedNexthops> routing =
621 Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops> (ipv4->GetRoutingProtocol ());
622 NS_ASSERT_MSG (routing != 0, "Ipv4GlobalRoutingOrderedNexthops should be used in InternetStack");
623
624 Ptr<Ipv4GlobalRoutingOrderedNexthops::EntryContainer>
625 routes = routing->Lookup (destIpv4);
626
627 NS_ASSERT_MSG (routes != 0, "Should not happen... Call the developer");
628
629 BOOST_FOREACH (const Ipv4RoutingTableEntry &entry, *routes)
630 {
631 Ptr<NetDevice> netDevice = ipv4->GetNetDevice (entry.GetInterface ());
632 NS_ASSERT_MSG (netDevice != 0, "Should never happen. Call the popos");
633
634 Ptr<CcnxFace> face = ccnx->GetFaceByNetDevice (netDevice);
635 NS_ASSERT_MSG (face != 0, "Definitely should never happen. Call the president");
636
637 AddRoute (*node, destPrefix.str(), face, entry.GetMetric ());
638 }
639 }
640}
641
642void
643CcnxStackHelper::InstallRoutesToAll ()
644{
645 for (NodeList::Iterator node = NodeList::Begin ();
646 node != NodeList::End ();
647 node ++)
648 {
649 InstallRouteTo (*node);
650 }
651}
652
653
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700654} // namespace ns3