NS-3 based Named Data Networking (NDN) simulator
ndnSIM: NDN, CCN, CCNx, content centric networks
API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
ndn-stack-helper.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2 /*
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  *
18  * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
19  * Ilya Moiseenko <iliamo@cs.ucla.edu>
20  */
21 
22 #include "ns3/assert.h"
23 #include "ns3/log.h"
24 #include "ns3/object.h"
25 #include "ns3/names.h"
26 #include "ns3/packet-socket-factory.h"
27 #include "ns3/config.h"
28 #include "ns3/simulator.h"
29 #include "ns3/string.h"
30 #include "ns3/net-device.h"
31 #include "ns3/channel.h"
32 #include "ns3/callback.h"
33 #include "ns3/node.h"
34 #include "ns3/core-config.h"
35 #include "ns3/point-to-point-net-device.h"
36 #include "ns3/point-to-point-helper.h"
37 #include "ns3/callback.h"
38 
39 #include "../model/ndn-net-device-face.h"
40 #include "../model/ndn-l3-protocol.h"
41 
42 #include "ns3/ndn-forwarding-strategy.h"
43 #include "ns3/ndn-fib.h"
44 #include "ns3/ndn-pit.h"
45 #include "ns3/ndn-name.h"
46 #include "ns3/ndn-content-store.h"
47 
48 #include "ns3/node-list.h"
49 // #include "ns3/loopback-net-device.h"
50 
51 #include "ns3/data-rate.h"
52 
53 #include "ndn-face-container.h"
54 #include "ndn-stack-helper.h"
55 
56 #include <limits>
57 #include <map>
58 #include <boost/foreach.hpp>
59 #include <boost/lexical_cast.hpp>
60 
61 NS_LOG_COMPONENT_DEFINE ("ndn.StackHelper");
62 
63 namespace ns3 {
64 namespace ndn {
65 
67  : m_limitsEnabled (false)
68  , m_needSetDefaultRoutes (false)
69 {
70  m_ndnFactory. SetTypeId ("ns3::ndn::L3Protocol");
71  m_strategyFactory. SetTypeId ("ns3::ndn::fw::Flooding");
72  m_contentStoreFactory.SetTypeId ("ns3::ndn::cs::Lru");
73  m_fibFactory. SetTypeId ("ns3::ndn::fib::Default");
74  m_pitFactory. SetTypeId ("ns3::ndn::pit::Persistent");
75 
76  m_netDeviceCallbacks.push_back (std::make_pair (PointToPointNetDevice::GetTypeId (), MakeCallback (&StackHelper::PointToPointNetDeviceCallback, this)));
77  // default callback will be fired if non of others callbacks fit or did the job
78 }
79 
81 {
82 }
83 
84 void
85 StackHelper::SetStackAttributes (const std::string &attr1, const std::string &value1,
86  const std::string &attr2, const std::string &value2,
87  const std::string &attr3, const std::string &value3,
88  const std::string &attr4, const std::string &value4)
89 {
90  if (attr1 != "")
91  m_ndnFactory.Set (attr1, StringValue (value1));
92  if (attr2 != "")
93  m_ndnFactory.Set (attr2, StringValue (value2));
94  if (attr3 != "")
95  m_ndnFactory.Set (attr3, StringValue (value3));
96  if (attr4 != "")
97  m_ndnFactory.Set (attr4, StringValue (value4));
98 }
99 
100 void
101 StackHelper::SetForwardingStrategy (const std::string &strategy,
102  const std::string &attr1, const std::string &value1,
103  const std::string &attr2, const std::string &value2,
104  const std::string &attr3, const std::string &value3,
105  const std::string &attr4, const std::string &value4)
106 {
107  m_strategyFactory.SetTypeId (strategy);
108  if (attr1 != "")
109  m_strategyFactory.Set (attr1, StringValue (value1));
110  if (attr2 != "")
111  m_strategyFactory.Set (attr2, StringValue (value2));
112  if (attr3 != "")
113  m_strategyFactory.Set (attr3, StringValue (value3));
114  if (attr4 != "")
115  m_strategyFactory.Set (attr4, StringValue (value4));
116 }
117 
118 void
119 StackHelper::SetContentStore (const std::string &contentStore,
120  const std::string &attr1, const std::string &value1,
121  const std::string &attr2, const std::string &value2,
122  const std::string &attr3, const std::string &value3,
123  const std::string &attr4, const std::string &value4)
124 {
125  m_contentStoreFactory.SetTypeId (contentStore);
126  if (attr1 != "")
127  m_contentStoreFactory.Set (attr1, StringValue (value1));
128  if (attr2 != "")
129  m_contentStoreFactory.Set (attr2, StringValue (value2));
130  if (attr3 != "")
131  m_contentStoreFactory.Set (attr3, StringValue (value3));
132  if (attr4 != "")
133  m_contentStoreFactory.Set (attr4, StringValue (value4));
134 }
135 
136 void
137 StackHelper::SetPit (const std::string &pitClass,
138  const std::string &attr1, const std::string &value1,
139  const std::string &attr2, const std::string &value2,
140  const std::string &attr3, const std::string &value3,
141  const std::string &attr4, const std::string &value4)
142 {
143  m_pitFactory.SetTypeId (pitClass);
144  if (attr1 != "")
145  m_pitFactory.Set (attr1, StringValue (value1));
146  if (attr2 != "")
147  m_pitFactory.Set (attr2, StringValue (value2));
148  if (attr3 != "")
149  m_pitFactory.Set (attr3, StringValue (value3));
150  if (attr4 != "")
151  m_pitFactory.Set (attr4, StringValue (value4));
152 }
153 
154 void
155 StackHelper::SetFib (const std::string &fibClass,
156  const std::string &attr1, const std::string &value1,
157  const std::string &attr2, const std::string &value2,
158  const std::string &attr3, const std::string &value3,
159  const std::string &attr4, const std::string &value4)
160 {
161  m_fibFactory.SetTypeId (fibClass);
162  if (attr1 != "")
163  m_fibFactory.Set (attr1, StringValue (value1));
164  if (attr2 != "")
165  m_fibFactory.Set (attr2, StringValue (value2));
166  if (attr3 != "")
167  m_fibFactory.Set (attr3, StringValue (value3));
168  if (attr4 != "")
169  m_fibFactory.Set (attr4, StringValue (value4));
170 }
171 
172 void
174 {
175  NS_LOG_FUNCTION (this << needSet);
176  m_needSetDefaultRoutes = needSet;
177 }
178 
179 void
180 StackHelper::EnableLimits (bool enable/* = true*/,
181  Time avgRtt/*=Seconds(0.1)*/,
182  uint32_t avgData/*=1100*/,
183  uint32_t avgInterest/*=40*/)
184 {
185  NS_LOG_INFO ("EnableLimits: " << enable);
186  m_limitsEnabled = enable;
187  m_avgRtt = avgRtt;
188  m_avgDataSize = avgData;
189  m_avgInterestSize = avgInterest;
190 }
191 
192 Ptr<FaceContainer>
193 StackHelper::Install (const NodeContainer &c) const
194 {
195  Ptr<FaceContainer> faces = Create<FaceContainer> ();
196  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
197  {
198  faces->AddAll (Install (*i));
199  }
200  return faces;
201 }
202 
203 Ptr<FaceContainer>
205 {
206  return Install (NodeContainer::GetGlobal ());
207 }
208 
209 Ptr<FaceContainer>
210 StackHelper::Install (Ptr<Node> node) const
211 {
212  // NS_ASSERT_MSG (m_forwarding, "SetForwardingHelper() should be set prior calling Install() method");
213  Ptr<FaceContainer> faces = Create<FaceContainer> ();
214 
215  if (node->GetObject<L3Protocol> () != 0)
216  {
217  NS_FATAL_ERROR ("StackHelper::Install (): Installing "
218  "a NdnStack to a node with an existing Ndn object");
219  return 0;
220  }
221 
222  // Create L3Protocol
223  Ptr<L3Protocol> ndn = m_ndnFactory.Create<L3Protocol> ();
224 
225  // Create and aggregate FIB
226  Ptr<Fib> fib = m_fibFactory.Create<Fib> ();
227  ndn->AggregateObject (fib);
228 
229  // Create and aggregate PIT
230  ndn->AggregateObject (m_pitFactory.Create<Pit> ());
231 
232  // Create and aggregate forwarding strategy
233  ndn->AggregateObject (m_strategyFactory.Create<ForwardingStrategy> ());
234 
235  // Create and aggregate content store
236  ndn->AggregateObject (m_contentStoreFactory.Create<ContentStore> ());
237 
238  // Aggregate L3Protocol on node
239  node->AggregateObject (ndn);
240 
241  for (uint32_t index=0; index < node->GetNDevices (); index++)
242  {
243  Ptr<NetDevice> device = node->GetDevice (index);
244  // This check does not make sense: LoopbackNetDevice is installed only if IP stack is installed,
245  // Normally, ndnSIM works without IP stack, so no reason to check
246  // if (DynamicCast<LoopbackNetDevice> (device) != 0)
247  // continue; // don't create face for a LoopbackNetDevice
248 
249  Ptr<NetDeviceFace> face;
250 
251  for (std::list< std::pair<TypeId, NetDeviceFaceCreateCallback> >::const_iterator item = m_netDeviceCallbacks.begin ();
252  item != m_netDeviceCallbacks.end ();
253  item++)
254  {
255  if (device->GetInstanceTypeId () == item->first ||
256  device->GetInstanceTypeId ().IsChildOf (item->first))
257  {
258  face = item->second (node, ndn, device);
259  if (face != 0)
260  break;
261  }
262  }
263  if (face == 0)
264  {
265  face = DefaultNetDeviceCallback (node, ndn, device);
266  }
267 
268  if (m_needSetDefaultRoutes)
269  {
270  // default route with lowest priority possible
271  AddRoute (node, "/", StaticCast<Face> (face), std::numeric_limits<int32_t>::max ());
272  }
273 
274  face->SetUp ();
275  faces->Add (face);
276  }
277 
278  return faces;
279 }
280 
281 void
282 StackHelper::AddNetDeviceFaceCreateCallback (TypeId netDeviceType, StackHelper::NetDeviceFaceCreateCallback callback)
283 {
284  m_netDeviceCallbacks.push_back (std::make_pair (netDeviceType, callback));
285 }
286 
287 void
288 StackHelper::UpdateNetDeviceFaceCreateCallback (TypeId netDeviceType, NetDeviceFaceCreateCallback callback)
289 {
290  for (NetDeviceCallbackList::iterator i = m_netDeviceCallbacks.begin (); i != m_netDeviceCallbacks.end (); i++)
291  {
292  if (i->first == netDeviceType)
293  {
294  i->second = callback;
295  return;
296  }
297  }
298 }
299 
300 void
301 StackHelper::RemoveNetDeviceFaceCreateCallback (TypeId netDeviceType, NetDeviceFaceCreateCallback callback)
302 {
303  for (NetDeviceCallbackList::iterator i = m_netDeviceCallbacks.begin (); i != m_netDeviceCallbacks.end (); i++)
304  {
305  if (i->first == netDeviceType)
306  {
307  m_netDeviceCallbacks.erase (i);
308  return;
309  }
310  }
311 }
312 
313 Ptr<NetDeviceFace>
314 StackHelper::DefaultNetDeviceCallback (Ptr<Node> node, Ptr<L3Protocol> ndn, Ptr<NetDevice> netDevice) const
315 {
316  NS_LOG_DEBUG ("Creating default NetDeviceFace on node " << node->GetId ());
317 
318  Ptr<NetDeviceFace> face = CreateObject<NetDeviceFace> (node, netDevice);
319 
320  ndn->AddFace (face);
321  NS_LOG_LOGIC ("Node " << node->GetId () << ": added NetDeviceFace as face #" << *face);
322 
323  return face;
324 }
325 
326 Ptr<NetDeviceFace>
327 StackHelper::PointToPointNetDeviceCallback (Ptr<Node> node, Ptr<L3Protocol> ndn, Ptr<NetDevice> device) const
328 {
329  NS_LOG_DEBUG ("Creating point-to-point NetDeviceFace on node " << node->GetId ());
330 
331  Ptr<NetDeviceFace> face = CreateObject<NetDeviceFace> (node, device);
332 
333  ndn->AddFace (face);
334  NS_LOG_LOGIC ("Node " << node->GetId () << ": added NetDeviceFace as face #" << *face);
335 
336  if (m_limitsEnabled)
337  {
338  Ptr<Limits> limits = face->GetObject<Limits> ();
339  if (limits == 0)
340  {
341  NS_FATAL_ERROR ("Limits are enabled, but the selected forwarding strategy does not support limits. Please revise your scenario");
342  exit (1);
343  }
344 
345  NS_LOG_INFO ("Limits are enabled");
346  Ptr<PointToPointNetDevice> p2p = DynamicCast<PointToPointNetDevice> (device);
347  if (p2p != 0)
348  {
349  // Setup bucket filtering
350  // Assume that we know average data packet size, and this size is equal default size
351  // Set maximum buckets (averaging over 1 second)
352 
353  DataRateValue dataRate; device->GetAttribute ("DataRate", dataRate);
354  TimeValue linkDelay; device->GetChannel ()->GetAttribute ("Delay", linkDelay);
355 
356  NS_LOG_INFO("DataRate for this link is " << dataRate.Get());
357 
358  double maxInterestPackets = 1.0 * dataRate.Get ().GetBitRate () / 8.0 / (m_avgDataSize + m_avgInterestSize);
359  // NS_LOG_INFO ("Max packets per second: " << maxInterestPackets);
360  // NS_LOG_INFO ("Max burst: " << m_avgRtt.ToDouble (Time::S) * maxInterestPackets);
361  NS_LOG_INFO ("MaxLimit: " << (int)(m_avgRtt.ToDouble (Time::S) * maxInterestPackets));
362 
363  // Set max to BDP
364  limits->SetLimits (maxInterestPackets, m_avgRtt.ToDouble (Time::S));
365  limits->SetLinkDelay (linkDelay.Get ().ToDouble (Time::S));
366  }
367  }
368 
369  return face;
370 }
371 
372 
373 Ptr<FaceContainer>
374 StackHelper::Install (const std::string &nodeName) const
375 {
376  Ptr<Node> node = Names::Find<Node> (nodeName);
377  return Install (node);
378 }
379 
380 
381 void
382 StackHelper::AddRoute (Ptr<Node> node, const std::string &prefix, Ptr<Face> face, int32_t metric)
383 {
384  NS_LOG_LOGIC ("[" << node->GetId () << "]$ route add " << prefix << " via " << *face << " metric " << metric);
385 
386  Ptr<Fib> fib = node->GetObject<Fib> ();
387 
388  NameValue prefixValue;
389  prefixValue.DeserializeFromString (prefix, MakeNameChecker ());
390  fib->Add (prefixValue.Get (), face, metric);
391 }
392 
393 void
394 StackHelper::AddRoute (Ptr<Node> node, const std::string &prefix, uint32_t faceId, int32_t metric)
395 {
396  Ptr<L3Protocol> ndn = node->GetObject<L3Protocol> ();
397  NS_ASSERT_MSG (ndn != 0, "Ndn stack should be installed on the node");
398 
399  Ptr<Face> face = ndn->GetFace (faceId);
400  NS_ASSERT_MSG (face != 0, "Face with ID [" << faceId << "] does not exist on node [" << node->GetId () << "]");
401 
402  AddRoute (node, prefix, face, metric);
403 }
404 
405 void
406 StackHelper::AddRoute (const std::string &nodeName, const std::string &prefix, uint32_t faceId, int32_t metric)
407 {
408  Ptr<Node> node = Names::Find<Node> (nodeName);
409  NS_ASSERT_MSG (node != 0, "Node [" << nodeName << "] does not exist");
410 
411  Ptr<L3Protocol> ndn = node->GetObject<L3Protocol> ();
412  NS_ASSERT_MSG (ndn != 0, "Ndn stack should be installed on the node");
413 
414  Ptr<Face> face = ndn->GetFace (faceId);
415  NS_ASSERT_MSG (face != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
416 
417  AddRoute (node, prefix, face, metric);
418 }
419 
420 void
421 StackHelper::AddRoute (Ptr<Node> node, const std::string &prefix, Ptr<Node> otherNode, int32_t metric)
422 {
423  for (uint32_t deviceId = 0; deviceId < node->GetNDevices (); deviceId ++)
424  {
425  Ptr<PointToPointNetDevice> netDevice = DynamicCast<PointToPointNetDevice> (node->GetDevice (deviceId));
426  if (netDevice == 0)
427  continue;
428 
429  Ptr<Channel> channel = netDevice->GetChannel ();
430  if (channel == 0)
431  continue;
432 
433  if (channel->GetDevice (0)->GetNode () == otherNode ||
434  channel->GetDevice (1)->GetNode () == otherNode)
435  {
436  Ptr<L3Protocol> ndn = node->GetObject<L3Protocol> ();
437  NS_ASSERT_MSG (ndn != 0, "Ndn stack should be installed on the node");
438 
439  Ptr<Face> face = ndn->GetFaceByNetDevice (netDevice);
440  NS_ASSERT_MSG (face != 0, "There is no face associated with the p2p link");
441 
442  AddRoute (node, prefix, face, metric);
443 
444  return;
445  }
446  }
447 
448  NS_FATAL_ERROR ("Cannot add route: Node# " << node->GetId () << " and Node# " << otherNode->GetId () << " are not connected");
449 }
450 
451 void
452 StackHelper::AddRoute (const std::string &nodeName, const std::string &prefix, const std::string &otherNodeName, int32_t metric)
453 {
454  Ptr<Node> node = Names::Find<Node> (nodeName);
455  NS_ASSERT_MSG (node != 0, "Node [" << nodeName << "] does not exist");
456 
457  Ptr<Node> otherNode = Names::Find<Node> (otherNodeName);
458  NS_ASSERT_MSG (otherNode != 0, "Node [" << otherNodeName << "] does not exist");
459 
460  AddRoute (node, prefix, otherNode, metric);
461 }
462 
463 
464 } // namespace ndn
465 } // namespace ns3
Base class for NDN content store.
virtual Ptr< fib::Entry > Add(const Name &prefix, Ptr< Face > face, int32_t metric)=0
Add or update FIB entry.
Class implementing Pending Interests Table.
Definition: ndn-pit.h:60
void SetDefaultRoutes(bool needSet)
Set flag indicating necessity to install default routes in FIB.
StackHelper()
Create a new NdnStackHelper with a default NDN_FLOODING forwarding stategy.
void RemoveNetDeviceFaceCreateCallback(TypeId netDeviceType, NetDeviceFaceCreateCallback callback)
Remove callback to create and configure instance of the face, based on supplied Ptr and Ptr
Implementation network-layer of NDN stack.
void SetContentStore(const std::string &contentStoreClass, const std::string &attr1="", const std::string &value1="", const std::string &attr2="", const std::string &value2="", const std::string &attr3="", const std::string &value3="", const std::string &attr4="", const std::string &value4="")
Set content store class and its attributes.
Ptr< FaceContainer > InstallAll() const
Install Ndn stack on all nodes in the simulation.
void UpdateNetDeviceFaceCreateCallback(TypeId netDeviceType, NetDeviceFaceCreateCallback callback)
Update callback to create and configure instance of the face, based on supplied Ptr and Ptr
void SetStackAttributes(const std::string &attr1="", const std::string &value1="", const std::string &attr2="", const std::string &value2="", const std::string &attr3="", const std::string &value3="", const std::string &attr4="", const std::string &value4="")
Set parameters of NdnL3Protocol.
void AddNetDeviceFaceCreateCallback(TypeId netDeviceType, NetDeviceFaceCreateCallback callback)
Add callback to create and configure instance of the face, based on supplied Ptr and Ptr
Class implementing FIB functionality.
Definition: ndn-fib.h:44
virtual ~StackHelper()
Destroy the NdnStackHelper.
static void AddRoute(const std::string &nodeName, const std::string &prefix, uint32_t faceId, int32_t metric)
Add forwarding entry to FIB.
void EnableLimits(bool enable=true, Time avgRtt=Seconds(0.1), uint32_t avgData=1100, uint32_t avgInterest=40)
Enable Interest limits (disabled by default)
void SetForwardingStrategy(const std::string &forwardingStrategyClass, const std::string &attr1="", const std::string &value1="", const std::string &attr2="", const std::string &value2="", const std::string &attr3="", const std::string &value3="", const std::string &attr4="", const std::string &value4="")
Set forwarding strategy class and its attributes.
void SetPit(const std::string &pitClass, const std::string &attr1="", const std::string &value1="", const std::string &attr2="", const std::string &value2="", const std::string &attr3="", const std::string &value3="", const std::string &attr4="", const std::string &value4="")
Set PIT class and its attributes.
Ptr< FaceContainer > Install(const std::string &nodeName) const
Install Ndn stack on the node.
Abstract base class for Ndn forwarding strategies.
void SetFib(const std::string &fibClass, const std::string &attr1="", const std::string &value1="", const std::string &attr2="", const std::string &value2="", const std::string &attr3="", const std::string &value3="", const std::string &attr4="", const std::string &value4="")
Set FIB class and its attributes.