blob: 9699c386b6928519c8969b01f37121c5604d1f28 [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 Afanasyevc39f0b42011-11-28 12:51:12 -0800158CcnxStackHelper::EnableLimits (bool enable/* = true*/, Time avgRtt/*=Seconds(0.1)*/, uint32_t avgContentObject/*=1100*/, uint32_t avgInterest/*=40*/)
Alexander Afanasyev11453142011-11-25 16:13:33 -0800159{
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800160 NS_LOG_INFO ("EnableLimits: " << enable);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800161 m_limitsEnabled = enable;
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800162 m_avgContentObjectSize = avgContentObject;
163 m_avgInterestSize = avgInterest;
164 m_avgRtt = avgRtt;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700165}
166
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700167Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700168CcnxStackHelper::Install (NodeContainer c) const
169{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700170 Ptr<CcnxFaceContainer> faces = Create<CcnxFaceContainer> ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700171 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
172 {
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700173 faces->AddAll (Install (*i));
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700174 }
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700175 return faces;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700176}
177
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700178Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700179CcnxStackHelper::InstallAll (void) const
180{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700181 return Install (NodeContainer::GetGlobal ());
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700182}
183
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700184Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700185CcnxStackHelper::Install (Ptr<Node> node) const
186{
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700187 // NS_ASSERT_MSG (m_forwarding, "SetForwardingHelper() should be set prior calling Install() method");
188 Ptr<CcnxFaceContainer> faces = Create<CcnxFaceContainer> ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700189
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700190 if (node->GetObject<Ccnx> () != 0)
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700191 {
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700192 NS_FATAL_ERROR ("CcnxStackHelper::Install (): Installing "
193 "a CcnxStack to a node with an existing Ccnx object");
194 return 0;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700195 }
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700196
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700197 Ptr<CcnxFib> fib = CreateObject<CcnxFib> ();
198 node->AggregateObject (fib);
199
Ilya Moiseenkofbd0a8b2011-10-28 13:07:16 -0700200 Ptr<CcnxL3Protocol> ccnx = CreateObject<CcnxL3Protocol> ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700201 node->AggregateObject (ccnx);
202
Alexander Afanasyev11453142011-11-25 16:13:33 -0800203 ccnx->SetForwardingStrategy
204 (DynamicCast<CcnxForwardingStrategy> (m_strategyFactory.Create<Object> ()));
205
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700206 for (uint32_t index=0; index < node->GetNDevices (); index++)
207 {
Alexander Afanasyev11453142011-11-25 16:13:33 -0800208 Ptr<NetDevice> device = node->GetDevice (index);
209 if (DynamicCast<LoopbackNetDevice> (device) != 0)
210 continue; // don't create face for a LoopbackNetDevice
211
Alexander Afanasyevcbe92ae2011-12-16 13:06:18 -0800212 Ptr<CcnxNetDeviceFace> face = CreateObject<CcnxNetDeviceFace> (node, device);
Alexander Afanasyev19426ef2011-11-23 20:55:28 -0800213
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800214 ccnx->AddFace (face);
215 NS_LOG_LOGIC ("Node " << node->GetId () << ": added CcnxNetDeviceFace as face #" << *face);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800216
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800217 if (m_needSetDefaultRoutes)
218 {
219 // default route with lowest priority possible
220 AddRoute (node, "/", face, std::numeric_limits<int32_t>::max ());
221 }
222
Alexander Afanasyev11453142011-11-25 16:13:33 -0800223 if (m_limitsEnabled)
224 {
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800225 NS_LOG_INFO ("Limits are enabled");
Alexander Afanasyev11453142011-11-25 16:13:33 -0800226 Ptr<PointToPointNetDevice> p2p = DynamicCast<PointToPointNetDevice> (device);
227 if (p2p == 0)
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800228 {
229 NS_LOG_INFO ("Non p2p interface");
230 continue; // only PointToPointNetDevice supports limits
231 }
Alexander Afanasyev11453142011-11-25 16:13:33 -0800232
233 // Setup bucket filtering
234 // Assume that we know average data packet size, and this size is equal default size
235 // Set maximum buckets (averaging over 1 second)
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700236
Alexander Afanasyev11453142011-11-25 16:13:33 -0800237 DataRateValue dataRate; device->GetAttribute ("DataRate", dataRate);
238
239 NS_LOG_INFO("DataRate for this link is " << dataRate.Get());
Alexander Afanasyevc39f0b42011-11-28 12:51:12 -0800240
241 double maxInterestPackets = 1.0 * dataRate.Get ().GetBitRate () / 8.0 / m_avgContentObjectSize;
242 NS_LOG_INFO ("BucketMax: " << maxInterestPackets);
243
244 // Set bucket max to BDP
245 face->SetBucketMax (m_avgRtt.ToDouble (Time::S) * maxInterestPackets); // number of interests allowed
246 face->SetBucketLeak (maxInterestPackets);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800247 }
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700248
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700249 face->SetUp ();
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700250 faces->Add (face);
251 }
Ilya Moiseenko25f7d4d2011-09-29 18:41:06 -0700252
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700253 return faces;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700254}
255
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700256Ptr<CcnxFaceContainer>
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700257CcnxStackHelper::Install (std::string nodeName) const
258{
259 Ptr<Node> node = Names::Find<Node> (nodeName);
Alexander Afanasyev0ab833e2011-08-18 15:49:13 -0700260 return Install (node);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700261}
262
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700263
264void
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800265CcnxStackHelper::AddRoute (Ptr<Node> node, std::string prefix, Ptr<CcnxFace> face, int32_t metric) const
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800266{
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800267 NS_LOG_LOGIC ("[" << node->GetId () << "]$ route add " << prefix << " via " << *face << " metric " << metric);
268
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800269 Ptr<CcnxFib> fib = node->GetObject<CcnxFib> ();
270
271 CcnxNameComponentsValue prefixValue;
272 prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
273 fib->Add (prefixValue.Get (), face, metric);
274}
275
276void
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800277CcnxStackHelper::AddRoute (std::string nodeName, std::string prefix, uint32_t faceId, int32_t metric) const
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700278{
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700279 Ptr<Node> node = Names::Find<Node> (nodeName);
280 NS_ASSERT_MSG (node != 0, "Node [" << nodeName << "] does not exist");
Alexander Afanasyeva4e3f852011-11-15 20:39:33 -0800281
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800282 Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
283 NS_ASSERT_MSG (ccnx != 0, "Ccnx stack should be installed on the node");
284
285 Ptr<CcnxFace> face = ccnx->GetFace (faceId);
286 NS_ASSERT_MSG (face != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
287
288 AddRoute (node, prefix, face, metric);
Alexander Afanasyevc5a23e22011-09-07 00:37:36 -0700289}
Alexander Afanasyev4a5c2c12011-12-12 18:50:57 -0800290
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700291/*
Alexander Afanasyev11453142011-11-25 16:13:33 -0800292 void
293 CcnxStackHelper::AddRoute (Ptr<Node> node, std::string prefix, uint32_t faceId, int32_t metric)
294 {
295 NS_LOG_LOGIC ("[" << nodeName << "]$ route add " << prefix << " via " << faceId << " metric " << metric);
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700296
297 NS_ASSERT_MSG (node != 0, "Node does not exist");
298
299 Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
300 Ptr<CcnxFib> fib = node->GetObject<CcnxFib> ();
301 Ptr<CcnxFace> face = ccnx->GetFace (faceId);
302 NS_ASSERT_MSG (node != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
303
304 CcnxNameComponentsValue prefixValue;
305 prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
306 fib->Add (prefixValue.Get (), face, metric);
Alexander Afanasyev11453142011-11-25 16:13:33 -0800307 }
Ilya Moiseenkoc9266042011-11-02 17:49:21 -0700308*/
Ilya Moiseenkoae394872011-11-15 17:56:36 -0800309
Alexander Afanasyev11453142011-11-25 16:13:33 -0800310// static void
311// CcnxL3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ccnx> ccnx, uint32_t face)
312// {
313// NS_LOG_FUNCTION (p << ccnx << face);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700314
Alexander Afanasyev11453142011-11-25 16:13:33 -0800315// //
316// // Since trace sources are independent of face, if we hook a source
317// // on a particular protocol we will get traces for all of its faces.
318// // We need to filter this to only report faces for which the user
319// // has expressed interest.
320// //
321// FacePairCcnx pair = std::make_pair (ccnx, face);
322// if (g_faceFileMapCcnx.find (pair) == g_faceFileMapCcnx.end ())
323// {
324// NS_LOG_INFO ("Ignoring packet to/from face " << face);
325// return;
326// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700327
Alexander Afanasyev11453142011-11-25 16:13:33 -0800328// Ptr<PcapFileWrapper> file = g_faceFileMapCcnx[pair];
329// file->Write (Simulator::Now (), p);
330// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700331
Alexander Afanasyev11453142011-11-25 16:13:33 -0800332// bool
333// CcnxStackHelper::PcapHooked (Ptr<Ccnx> ccnx)
334// {
335// for (FaceFileMapCcnx::const_iterator i = g_faceFileMapCcnx.begin ();
336// i != g_faceFileMapCcnx.end ();
337// ++i)
338// {
339// if ((*i).first.first == ccnx)
340// {
341// return true;
342// }
343// }
344// return false;
345// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700346
Alexander Afanasyev11453142011-11-25 16:13:33 -0800347// void
348// CcnxStackHelper::EnablePcapCcnxInternal (std::string prefix, Ptr<Ccnx> ccnx, uint32_t face, bool explicitFilename)
349// {
350// NS_LOG_FUNCTION (prefix << ccnx << face);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700351
Alexander Afanasyev11453142011-11-25 16:13:33 -0800352// //
353// // We have to create a file and a mapping from protocol/face to file
354// // irrespective of how many times we want to trace a particular protocol.
355// //
356// PcapHelper pcapHelper;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700357
Alexander Afanasyev11453142011-11-25 16:13:33 -0800358// std::string filename;
359// if (explicitFilename)
360// {
361// filename = prefix;
362// }
363// else
364// {
365// filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
366// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700367
Alexander Afanasyev11453142011-11-25 16:13:33 -0800368// Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700369
Alexander Afanasyev11453142011-11-25 16:13:33 -0800370// //
371// // However, we only hook the trace source once to avoid multiple trace sink
372// // calls per event (connect is independent of face).
373// //
374// if (!PcapHooked (ccnx))
375// {
376// //
377// // Ptr<Ccnx> is aggregated to node and CcnxL3Protocol is aggregated to
378// // node so we can get to CcnxL3Protocol through Ccnx.
379// //
380// Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
381// NS_ASSERT_MSG (ccnxL3Protocol, "CcnxStackHelper::EnablePcapCcnxInternal(): "
382// "m_ccnxEnabled and ccnxL3Protocol inconsistent");
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700383
Alexander Afanasyev11453142011-11-25 16:13:33 -0800384// bool result = ccnxL3Protocol->TraceConnectWithoutContext ("Tx", MakeCallback (&CcnxL3ProtocolRxTxSink));
385// NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal(): "
386// "Unable to connect ccnxL3Protocol \"Tx\"");
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700387
Alexander Afanasyev11453142011-11-25 16:13:33 -0800388// result = ccnxL3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&CcnxL3ProtocolRxTxSink));
389// NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal(): "
390// "Unable to connect ccnxL3Protocol \"Rx\"");
391// // cast result to void, to suppress ‘result’ set but not used compiler-warning
392// // for optimized builds
393// (void) result;
394// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700395
Alexander Afanasyev11453142011-11-25 16:13:33 -0800396// g_faceFileMapCcnx[std::make_pair (ccnx, face)] = file;
397// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700398
Alexander Afanasyev11453142011-11-25 16:13:33 -0800399// static void
400// CcnxL3ProtocolDropSinkWithoutContext (
401// Ptr<OutputStreamWrapper> stream,
402// Ptr<const Packet> packet,
403// CcnxL3Protocol::DropReason reason,
404// Ptr<Ccnx> ccnx,
405// uint32_t face)
406// {
407// //
408// // Since trace sources are independent of face, if we hook a source
409// // on a particular protocol we will get traces for all of its faces.
410// // We need to filter this to only report faces for which the user
411// // has expressed interest.
412// //
413// FacePairCcnx pair = std::make_pair (ccnx, face);
414// if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
415// {
416// NS_LOG_INFO ("Ignoring packet to/from face " << face);
417// return;
418// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700419
Alexander Afanasyev11453142011-11-25 16:13:33 -0800420// *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *packet << std::endl;
421// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700422
Alexander Afanasyev11453142011-11-25 16:13:33 -0800423// static void
424// CcnxL3ProtocolDropSinkWithContext (
425// Ptr<OutputStreamWrapper> stream,
426// std::string context,
427// Ptr<const Packet> packet,
428// CcnxL3Protocol::DropReason reason,
429// Ptr<Ccnx> ccnx,
430// uint32_t face)
431// {
432// //
433// // Since trace sources are independent of face, if we hook a source
434// // on a particular protocol we will get traces for all of its faces.
435// // We need to filter this to only report faces for which the user
436// // has expressed interest.
437// //
438// FacePairCcnx pair = std::make_pair (ccnx, face);
439// if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
440// {
441// NS_LOG_INFO ("Ignoring packet to/from face " << face);
442// return;
443// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700444
Alexander Afanasyev11453142011-11-25 16:13:33 -0800445// *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << "(" << face << ") "
446// << *packet << std::endl;
447// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700448
Alexander Afanasyev11453142011-11-25 16:13:33 -0800449// bool
450// CcnxStackHelper::AsciiHooked (Ptr<Ccnx> ccnx)
451// {
452// for ( FaceStreamMapCcnx::const_iterator i = g_faceStreamMapCcnx.begin ();
453// i != g_faceStreamMapCcnx.end ();
454// ++i)
455// {
456// if ((*i).first.first == ccnx)
457// {
458// return true;
459// }
460// }
461// return false;
462// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700463
Alexander Afanasyev11453142011-11-25 16:13:33 -0800464// void
465// CcnxStackHelper::EnableAsciiCcnxInternal (
466// Ptr<OutputStreamWrapper> stream,
467// std::string prefix,
468// Ptr<Ccnx> ccnx,
469// uint32_t face,
470// bool explicitFilename)
471// {
472// //
473// // Our trace sinks are going to use packet printing, so we have to
474// // make sure that is turned on.
475// //
476// Packet::EnablePrinting ();
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700477
Alexander Afanasyev11453142011-11-25 16:13:33 -0800478// //
479// // If we are not provided an OutputStreamWrapper, we are expected to create
480// // one using the usual trace filename conventions and hook WithoutContext
481// // since there will be one file per context and therefore the context would
482// // be redundant.
483// //
484// if (stream == 0)
485// {
486// //
487// // Set up an output stream object to deal with private ofstream copy
488// // constructor and lifetime issues. Let the helper decide the actual
489// // name of the file given the prefix.
490// //
491// // We have to create a stream and a mapping from protocol/face to
492// // stream irrespective of how many times we want to trace a particular
493// // protocol.
494// //
495// AsciiTraceHelper asciiTraceHelper;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700496
Alexander Afanasyev11453142011-11-25 16:13:33 -0800497// std::string filename;
498// if (explicitFilename)
499// {
500// filename = prefix;
501// }
502// else
503// {
504// filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
505// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700506
Alexander Afanasyev11453142011-11-25 16:13:33 -0800507// Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700508
Alexander Afanasyev11453142011-11-25 16:13:33 -0800509// //
510// // However, we only hook the trace sources once to avoid multiple trace sink
511// // calls per event (connect is independent of face).
512// //
513// if (!AsciiHooked (ccnx))
514// {
515// //
516// // The drop sink for the CcnxL3Protocol uses a different signature than
517// // the default sink, so we have to cook one up for ourselves. We can get
518// // to the Ptr<CcnxL3Protocol> through our Ptr<Ccnx> since they must both
519// // be aggregated to the same node.
520// //
521// Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
522// bool __attribute__ ((unused)) result = ccnxL3Protocol->TraceConnectWithoutContext ("Drop",
523// MakeBoundCallback (&CcnxL3ProtocolDropSinkWithoutContext, theStream));
524// NS_ASSERT_MSG (result == true, "CcnxStackHelper::EanableAsciiCcnxInternal(): "
525// "Unable to connect ccnxL3Protocol \"Drop\"");
526// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700527
Alexander Afanasyev11453142011-11-25 16:13:33 -0800528// g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = theStream;
529// return;
530// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700531
Alexander Afanasyev11453142011-11-25 16:13:33 -0800532// //
533// // If we are provided an OutputStreamWrapper, we are expected to use it, and
534// // to provide a context. We are free to come up with our own context if we
535// // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
536// // compatibility and simplicity, we just use Config::Connect and let it deal
537// // with the context.
538// //
539// // We need to associate the ccnx/face with a stream to express interest
540// // in tracing events on that pair, however, we only hook the trace sources
541// // once to avoid multiple trace sink calls per event (connect is independent
542// // of face).
543// //
544// if (!AsciiHooked (ccnx))
545// {
546// Ptr<Node> node = ccnx->GetObject<Node> ();
547// std::ostringstream oss;
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700548
Alexander Afanasyev11453142011-11-25 16:13:33 -0800549// //
550// // This has all kinds of parameters coming with, so we have to cook up our
551// // own sink.
552// //
553// oss.str ("");
554// oss << "/NodeList/" << node->GetId () << "/$ns3::CcnxL3Protocol/Drop";
555// Config::Connect (oss.str (), MakeBoundCallback (&CcnxL3ProtocolDropSinkWithContext, stream));
556// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700557
Alexander Afanasyev11453142011-11-25 16:13:33 -0800558// g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = stream;
559// }
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700560
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800561void
562CcnxStackHelper::InstallFakeGlobalRoutes ()
563{
564 for (NodeList::Iterator node = NodeList::Begin ();
565 node != NodeList::End ();
566 node ++)
567 {
568 NS_ASSERT_MSG ((*node)->GetObject<Ipv4> () != 0,
569 "InternetStack should be installed on all nodes");
570
571 NS_ASSERT_MSG (Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops>
572 (
573 (*node)->GetObject<Ipv4> ()->GetRoutingProtocol ()
Alexander Afanasyev11453142011-11-25 16:13:33 -0800574 ),
Alexander Afanasyev52e9aa92011-11-15 20:23:20 -0800575 "InternetStack should have Ipv4GlobalRoutingOrderedNexthops as routing protocol");
576 // Example:
577 //
578 // Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingUnorderedNexthops");
579 // stack.SetRoutingHelper (ipv4RoutingHelper);
580 //
581
582 Ptr<GlobalRouter> globalRouter = (*node)->GetObject<GlobalRouter> ();
583 if (globalRouter == 0) continue;
584
585 globalRouter->InjectRoute (Ipv4Address((*node)->GetId ()), Ipv4Mask("255.255.255.255"));
586 }
587
588 Ipv4GlobalRoutingHelper::PopulateAllPossibleRoutingTables ();
589}
590
591void
592CcnxStackHelper::InstallRouteTo (Ptr<Node> destNode)
593{
594 std::ostringstream destPrefix;
595 destPrefix << "/" << destNode->GetId ();
596
597 Ipv4Address destIpv4 = Ipv4Address(destNode->GetId ());
598
599 for (NodeList::Iterator node = NodeList::Begin ();
600 node != NodeList::End ();
601 node ++)
602 {
603 if (destNode == *node) continue;
604
605 Ptr<Ccnx> ccnx = (*node)->GetObject<Ccnx> ();
606 NS_ASSERT_MSG (ccnx != 0, "CCNx stack should be installed on all nodes");
607
608 Ptr<Ipv4> ipv4 = (*node)->GetObject<Ipv4> ();
609 NS_ASSERT_MSG (ipv4 != 0,
610 "InternetStack should be installed on all nodes");
611
612 Ptr<Ipv4GlobalRoutingOrderedNexthops> routing =
613 Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops> (ipv4->GetRoutingProtocol ());
614 NS_ASSERT_MSG (routing != 0, "Ipv4GlobalRoutingOrderedNexthops should be used in InternetStack");
615
616 Ptr<Ipv4GlobalRoutingOrderedNexthops::EntryContainer>
617 routes = routing->Lookup (destIpv4);
618
619 NS_ASSERT_MSG (routes != 0, "Should not happen... Call the developer");
620
621 BOOST_FOREACH (const Ipv4RoutingTableEntry &entry, *routes)
622 {
623 Ptr<NetDevice> netDevice = ipv4->GetNetDevice (entry.GetInterface ());
624 NS_ASSERT_MSG (netDevice != 0, "Should never happen. Call the popos");
625
626 Ptr<CcnxFace> face = ccnx->GetFaceByNetDevice (netDevice);
627 NS_ASSERT_MSG (face != 0, "Definitely should never happen. Call the president");
628
629 AddRoute (*node, destPrefix.str(), face, entry.GetMetric ());
630 }
631 }
632}
633
634void
635CcnxStackHelper::InstallRoutesToAll ()
636{
637 for (NodeList::Iterator node = NodeList::Begin ();
638 node != NodeList::End ();
639 node ++)
640 {
641 InstallRouteTo (*node);
642 }
643}
644
645
Alexander Afanasyev45b92d42011-08-14 23:11:38 -0700646} // namespace ns3