helper: Experimental extension of ndn::StackHelper to enable customization of NetDeviceFace (e.g., creating of custom faces based on different NetDevice's)
diff --git a/helper/ndn-stack-helper.cc b/helper/ndn-stack-helper.cc
index 5f7f7a6..04ceb46 100644
--- a/helper/ndn-stack-helper.cc
+++ b/helper/ndn-stack-helper.cc
@@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
- * Ilya Moiseenko <iliamo@cs.ucla.edu>
+ * Ilya Moiseenko <iliamo@cs.ucla.edu>
*/
#include "ns3/assert.h"
@@ -34,6 +34,7 @@
#include "ns3/core-config.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/point-to-point-helper.h"
+#include "ns3/callback.h"
#include "../model/ndn-net-device-face.h"
#include "../model/ndn-l3-protocol.h"
@@ -61,7 +62,7 @@
namespace ns3 {
namespace ndn {
-
+
StackHelper::StackHelper ()
: m_limitsEnabled (false)
, m_needSetDefaultRoutes (false)
@@ -71,8 +72,11 @@
m_contentStoreFactory.SetTypeId ("ns3::ndn::cs::Lru");
m_fibFactory. SetTypeId ("ns3::ndn::fib::Default");
m_pitFactory. SetTypeId ("ns3::ndn::pit::Persistent");
+
+ m_netDeviceCallbacks.push_back (std::make_pair (PointToPointNetDevice::GetTypeId (), MakeCallback (&StackHelper::PointToPointNetDeviceCallback, this)));
+ // default callback will be fired if non of others callbacks fit or did the job
}
-
+
StackHelper::~StackHelper ()
{
}
@@ -93,7 +97,7 @@
m_ndnFactory.Set (attr4, StringValue (value4));
}
-void
+void
StackHelper::SetForwardingStrategy (const std::string &strategy,
const std::string &attr1, const std::string &value1,
const std::string &attr2, const std::string &value2,
@@ -207,10 +211,10 @@
{
// NS_ASSERT_MSG (m_forwarding, "SetForwardingHelper() should be set prior calling Install() method");
Ptr<FaceContainer> faces = Create<FaceContainer> ();
-
+
if (node->GetObject<L3Protocol> () != 0)
{
- NS_FATAL_ERROR ("StackHelper::Install (): Installing "
+ NS_FATAL_ERROR ("StackHelper::Install (): Installing "
"a NdnStack to a node with an existing Ndn object");
return 0;
}
@@ -224,7 +228,7 @@
// Create and aggregate PIT
ndn->AggregateObject (m_pitFactory.Create<Pit> ());
-
+
// Create and aggregate forwarding strategy
ndn->AggregateObject (m_strategyFactory.Create<ForwardingStrategy> ());
@@ -233,7 +237,7 @@
// Aggregate L3Protocol on node
node->AggregateObject (ndn);
-
+
for (uint32_t index=0; index < node->GetNDevices (); index++)
{
Ptr<NetDevice> device = node->GetDevice (index);
@@ -242,7 +246,24 @@
// if (DynamicCast<LoopbackNetDevice> (device) != 0)
// continue; // don't create face for a LoopbackNetDevice
- Ptr<NetDeviceFace> face = CreateObject<NetDeviceFace> (node, device);
+ Ptr<NetDeviceFace> face;
+
+ for (std::list< std::pair<TypeId, NetDeviceFaceCreateCallback> >::const_iterator item = m_netDeviceCallbacks.begin ();
+ item != m_netDeviceCallbacks.end ();
+ item++)
+ {
+ if (device->GetInstanceTypeId () == item->first ||
+ device->GetInstanceTypeId ().IsChildOf (item->first))
+ {
+ face = item->second (node, device);
+ if (face != 0)
+ break;
+ }
+ }
+ if (face == 0)
+ {
+ face = DefaultNetDeviceCallback (node, device);
+ }
ndn->AddFace (face);
NS_LOG_LOGIC ("Node " << node->GetId () << ": added NetDeviceFace as face #" << *face);
@@ -250,49 +271,75 @@
if (m_needSetDefaultRoutes)
{
// default route with lowest priority possible
- AddRoute (node, "/", StaticCast<Face> (face), std::numeric_limits<int32_t>::max ());
+ AddRoute (node, "/", StaticCast<Face> (face), std::numeric_limits<int32_t>::max ());
}
-
- if (m_limitsEnabled)
- {
- Ptr<Limits> limits = face->GetObject<Limits> ();
- if (limits == 0)
- {
- NS_FATAL_ERROR ("Limits are enabled, but the selected forwarding strategy does not support limits. Please revise your scenario");
- exit (1);
- }
-
- NS_LOG_INFO ("Limits are enabled");
- Ptr<PointToPointNetDevice> p2p = DynamicCast<PointToPointNetDevice> (device);
- if (p2p != 0)
- {
- // Setup bucket filtering
- // Assume that we know average data packet size, and this size is equal default size
- // Set maximum buckets (averaging over 1 second)
-
- DataRateValue dataRate; device->GetAttribute ("DataRate", dataRate);
- TimeValue linkDelay; device->GetChannel ()->GetAttribute ("Delay", linkDelay);
-
- NS_LOG_INFO("DataRate for this link is " << dataRate.Get());
- double maxInterestPackets = 1.0 * dataRate.Get ().GetBitRate () / 8.0 / (m_avgContentObjectSize + m_avgInterestSize);
- // NS_LOG_INFO ("Max packets per second: " << maxInterestPackets);
- // NS_LOG_INFO ("Max burst: " << m_avgRtt.ToDouble (Time::S) * maxInterestPackets);
- NS_LOG_INFO ("MaxLimit: " << (int)(m_avgRtt.ToDouble (Time::S) * maxInterestPackets));
-
- // Set max to BDP
- limits->SetLimits (maxInterestPackets, m_avgRtt.ToDouble (Time::S));
- limits->SetLinkDelay (linkDelay.Get ().ToDouble (Time::S));
- }
- }
-
face->SetUp ();
faces->Add (face);
}
-
+
return faces;
}
+void
+StackHelper::AddNetDeviceFaceCreateCallback (TypeId netDeviceType, StackHelper::NetDeviceFaceCreateCallback callback)
+{
+ m_netDeviceCallbacks.push_back (std::make_pair (netDeviceType, callback));
+}
+
+
+Ptr<NetDeviceFace>
+StackHelper::DefaultNetDeviceCallback (Ptr<Node> node, Ptr<NetDevice> netDevice) const
+{
+ NS_LOG_DEBUG ("Creating default NetDeviceFace on node " << node->GetId ());
+
+ return CreateObject<NetDeviceFace> (node, netDevice);
+}
+
+Ptr<NetDeviceFace>
+StackHelper::PointToPointNetDeviceCallback (Ptr<Node> node, Ptr<NetDevice> device) const
+{
+ NS_LOG_DEBUG ("Creating point-to-point NetDeviceFace on node " << node->GetId ());
+
+ Ptr<NetDeviceFace> face = CreateObject<NetDeviceFace> (node, device);
+
+ if (m_limitsEnabled)
+ {
+ Ptr<Limits> limits = face->GetObject<Limits> ();
+ if (limits == 0)
+ {
+ NS_FATAL_ERROR ("Limits are enabled, but the selected forwarding strategy does not support limits. Please revise your scenario");
+ exit (1);
+ }
+
+ NS_LOG_INFO ("Limits are enabled");
+ Ptr<PointToPointNetDevice> p2p = DynamicCast<PointToPointNetDevice> (device);
+ if (p2p != 0)
+ {
+ // Setup bucket filtering
+ // Assume that we know average data packet size, and this size is equal default size
+ // Set maximum buckets (averaging over 1 second)
+
+ DataRateValue dataRate; device->GetAttribute ("DataRate", dataRate);
+ TimeValue linkDelay; device->GetChannel ()->GetAttribute ("Delay", linkDelay);
+
+ NS_LOG_INFO("DataRate for this link is " << dataRate.Get());
+
+ double maxInterestPackets = 1.0 * dataRate.Get ().GetBitRate () / 8.0 / (m_avgContentObjectSize + m_avgInterestSize);
+ // NS_LOG_INFO ("Max packets per second: " << maxInterestPackets);
+ // NS_LOG_INFO ("Max burst: " << m_avgRtt.ToDouble (Time::S) * maxInterestPackets);
+ NS_LOG_INFO ("MaxLimit: " << (int)(m_avgRtt.ToDouble (Time::S) * maxInterestPackets));
+
+ // Set max to BDP
+ limits->SetLimits (maxInterestPackets, m_avgRtt.ToDouble (Time::S));
+ limits->SetLinkDelay (linkDelay.Get ().ToDouble (Time::S));
+ }
+ }
+
+ return face;
+}
+
+
Ptr<FaceContainer>
StackHelper::Install (const std::string &nodeName) const
{
@@ -330,7 +377,7 @@
{
Ptr<Node> node = Names::Find<Node> (nodeName);
NS_ASSERT_MSG (node != 0, "Node [" << nodeName << "] does not exist");
-
+
Ptr<L3Protocol> ndn = node->GetObject<L3Protocol> ();
NS_ASSERT_MSG (ndn != 0, "Ndn stack should be installed on the node");