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");
diff --git a/helper/ndn-stack-helper.h b/helper/ndn-stack-helper.h
index 0c036d4..25764d9 100644
--- a/helper/ndn-stack-helper.h
+++ b/helper/ndn-stack-helper.h
@@ -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>
*/
#ifndef NDN_STACK_HELPER_H
@@ -57,14 +57,14 @@
* attribute or a set of functionality that may be of interest to many other
* classes.
*/
-class StackHelper
+class StackHelper
{
public:
/**
* \brief Create a new NdnStackHelper with a default NDN_FLOODING forwarding stategy
*/
StackHelper();
-
+
/**
* \brief Destroy the NdnStackHelper
*/
@@ -78,8 +78,8 @@
const std::string &attr2 = "", const std::string &value2 = "",
const std::string &attr3 = "", const std::string &value3 = "",
const std::string &attr4 = "", const std::string &value4 = "");
-
-
+
+
/**
* @brief Set forwarding strategy class and its attributes
* @param forwardingStrategyClass string containing name of the forwarding strategy class
@@ -116,7 +116,7 @@
const std::string &attr2 = "", const std::string &value2 = "",
const std::string &attr3 = "", const std::string &value3 = "",
const std::string &attr4 = "", const std::string &value4 = "");
-
+
/**
* @brief Set FIB class and its attributes
* @param pitClass string, representing class of FIB
@@ -128,6 +128,21 @@
const std::string &attr3 = "", const std::string &value3 = "",
const std::string &attr4 = "", const std::string &value4 = "");
+ typedef Callback< Ptr<NetDeviceFace>, Ptr<Node>, Ptr<NetDevice> > NetDeviceFaceCreateCallback;
+
+ /**
+ * @brief Add callback to create and configure instance of the face, based on supplied Ptr<Node> and Ptr<NetDevice>
+ *
+ * It is possible to set up several callbacks for different NetDevice types.
+ *
+ * Currently, there is only one specialized callback for PointToPointNetDevice, which creates face and sets limits (if enabled)
+ * based on PointToPoint link parameters
+ *
+ * If none of the callbacks fit the TypeId of NetDevice, a default callback is used (DefaultNetDeviceCallback)
+ */
+ void
+ AddNetDeviceFaceCreateCallback (TypeId netDeviceType, NetDeviceFaceCreateCallback callback);
+
/**
* @brief Enable Interest limits (disabled by default)
*
@@ -138,13 +153,13 @@
*/
void
EnableLimits (bool enable = true, Time avgRtt=Seconds(0.1), uint32_t avgContentObject=1100, uint32_t avgInterest=40);
-
+
/**
* \brief Install Ndn stack on the node
*
* This method will assert if called on a node that already has Ndn object
* installed on it
- *
+ *
* \param nodeName The name of the node on which to install the stack.
*
* \returns list of installed faces in the form of a smart pointer
@@ -158,7 +173,7 @@
*
* This method will assert if called on a node that already has Ndn object
* installed on it
- *
+ *
* \param node The node on which to install the stack.
*
* \returns list of installed faces in the form of a smart pointer
@@ -172,7 +187,7 @@
*
* The program will assert if this method is called on a container with a node
* that already has an ndn object aggregated to it.
- *
+ *
* \param c NodeContainer that holds the set of nodes on which to install the
* new stacks.
*
@@ -245,7 +260,7 @@
*/
static void
AddRoute (const std::string &nodeName, const std::string &prefix, const std::string &otherNodeName, int32_t metric);
-
+
/**
* \brief Set flag indicating necessity to install default routes in FIB
*/
@@ -253,21 +268,30 @@
SetDefaultRoutes (bool needSet);
private:
+ Ptr<NetDeviceFace>
+ DefaultNetDeviceCallback (Ptr<Node> node, Ptr<NetDevice> netDevice) const;
+
+ Ptr<NetDeviceFace>
+ PointToPointNetDeviceCallback (Ptr<Node> node, Ptr<NetDevice> netDevice) const;
+
+private:
StackHelper (const StackHelper &);
StackHelper &operator = (const StackHelper &o);
-
+
private:
ObjectFactory m_ndnFactory;
ObjectFactory m_strategyFactory;
ObjectFactory m_contentStoreFactory;
ObjectFactory m_pitFactory;
ObjectFactory m_fibFactory;
-
+
bool m_limitsEnabled;
Time m_avgRtt;
uint32_t m_avgContentObjectSize;
uint32_t m_avgInterestSize;
- bool m_needSetDefaultRoutes;
+ bool m_needSetDefaultRoutes;
+
+ std::list< std::pair<TypeId, NetDeviceFaceCreateCallback> > m_netDeviceCallbacks;
};
} // namespace ndn