helper: Show NetDevice address as LocalUri for NetDevice-based Faces

Change-Id: Iac4ab32345bff9771ceaf5704782f861624ac79b
Refs: #2665
diff --git a/helper/ndn-scenario-helper.cpp b/helper/ndn-scenario-helper.cpp
index 2539af1..af74386 100644
--- a/helper/ndn-scenario-helper.cpp
+++ b/helper/ndn-scenario-helper.cpp
@@ -36,7 +36,8 @@
 }
 
 void
-ScenarioHelper::createTopology(std::initializer_list<std::initializer_list<std::string>/*node clique*/> topology)
+ScenarioHelper::createTopology(std::initializer_list<std::initializer_list<std::string>/*node clique*/> topology,
+                               bool shouldInstallNdnStack)
 {
   if (m_isTopologyInitialized) {
     throw std::logic_error("Topology cannot be created twice");
@@ -57,7 +58,9 @@
     }
   }
 
-  ndnHelper.InstallAll();
+  if (shouldInstallNdnStack) {
+    ndnHelper.InstallAll();
+  }
   m_isTopologyInitialized = true;
 }
 
@@ -133,11 +136,18 @@
 shared_ptr<Face>
 ScenarioHelper::getFace(const std::string& node1, const std::string& node2)
 {
+  Ptr<NetDevice> netDevice = getNetDevice(node1, node2);
+  return netDevice->GetNode()->GetObject<L3Protocol>()->getFaceByNetDevice(netDevice);
+}
+
+Ptr<NetDevice>
+ScenarioHelper::getNetDevice(const std::string& node1, const std::string& node2)
+{
   auto i = links.find(node1);
   if (i != links.end()) {
     auto j = i->second.find(node2);
     if (j != i->second.end()) {
-      return j->second->GetNode()->GetObject<L3Protocol>()->getFaceByNetDevice(j->second);
+      return j->second;
     }
   }
 
diff --git a/helper/ndn-scenario-helper.hpp b/helper/ndn-scenario-helper.hpp
index b939095..292bc85 100644
--- a/helper/ndn-scenario-helper.hpp
+++ b/helper/ndn-scenario-helper.hpp
@@ -108,7 +108,8 @@
    *       });
    */
   void
-  createTopology(std::initializer_list<std::initializer_list<std::string>/*node clique*/> topology);
+  createTopology(std::initializer_list<std::initializer_list<std::string>/*node clique*/> topology,
+                 bool shouldInstallNdnStack = true);
 
   /**
    * @brief Create routes between topology nodes
@@ -158,6 +159,13 @@
   getFace(const std::string& node1, const std::string& node2);
 
   /**
+   * @brief Get NetDevice on the @p node1 pointing towards @p node2
+   * @throw std::invalid_argument if the link does not exist
+   */
+  Ptr<NetDevice>
+  getNetDevice(const std::string& node1, const std::string& node2);
+
+  /**
    * \brief Disable RIB Manager
    */
   void
diff --git a/helper/ndn-stack-helper.cpp b/helper/ndn-stack-helper.cpp
index 4037cf8..3b5571a 100644
--- a/helper/ndn-stack-helper.cpp
+++ b/helper/ndn-stack-helper.cpp
@@ -23,6 +23,7 @@
 #include "ns3/names.h"
 #include "ns3/string.h"
 #include "ns3/point-to-point-net-device.h"
+#include "ns3/point-to-point-channel.h"
 
 #include "model/ndn-l3-protocol.hpp"
 #include "model/ndn-net-device-link-service.hpp"
@@ -222,6 +223,19 @@
     });
 }
 
+std::string
+constructFaceUri(Ptr<NetDevice> netDevice)
+{
+  std::string uri = "netdev://";
+  Address address = netDevice->GetAddress();
+  if (Mac48Address::IsMatchingType(address)) {
+    uri += "[" + boost::lexical_cast<std::string>(Mac48Address::ConvertFrom(address)) + "]";
+  }
+
+  return uri;
+}
+
+
 shared_ptr<Face>
 StackHelper::DefaultNetDeviceCallback(Ptr<Node> node, Ptr<L3Protocol> ndn,
                                       Ptr<NetDevice> netDevice) const
@@ -229,12 +243,10 @@
   NS_LOG_DEBUG("Creating default Face on node " << node->GetId());
 
   auto netDeviceLink = make_unique<NetDeviceLinkService>(node, netDevice);
-  auto transport = make_unique<NullTransport>("netDevice://", "netDevice://");
+  auto transport = make_unique<NullTransport>(constructFaceUri(netDevice), "netdev://[ff:ff:ff:ff:ff:ff]");
   auto face = std::make_shared<Face>(std::move(netDeviceLink), std::move(transport));
   face->setMetric(1);
 
-  // @TODO add netDevice ID
-
   ndn->addFace(face);
   NS_LOG_LOGIC("Node " << node->GetId() << ": added Face as face #"
                        << face->getLocalUri());
@@ -248,13 +260,23 @@
 {
   NS_LOG_DEBUG("Creating point-to-point Face on node " << node->GetId());
 
-  auto netDeviceLink = make_unique<NetDeviceLinkService>(node, device);
-  auto transport = make_unique<NullTransport>("netDevice://", "netDevice://");
+  Ptr<PointToPointNetDevice> netDevice = DynamicCast<PointToPointNetDevice>(device);
+  NS_ASSERT(netDevice != nullptr);
+
+  // access the other end of the link
+  Ptr<PointToPointChannel> channel = DynamicCast<PointToPointChannel>(netDevice->GetChannel());
+  NS_ASSERT(channel != nullptr);
+
+  Ptr<NetDevice> remoteNetDevice = channel->GetDevice(0);
+  if (remoteNetDevice->GetNode() == node)
+    remoteNetDevice = channel->GetDevice(1);
+
+  auto netDeviceLink = make_unique<NetDeviceLinkService>(node, netDevice);
+
+  auto transport = make_unique<NullTransport>(constructFaceUri(netDevice), constructFaceUri(remoteNetDevice));
   auto face = std::make_shared<Face>(std::move(netDeviceLink), std::move(transport));
   face->setMetric(1);
 
-  // @TODO add netDevice ID
-
   ndn->addFace(face);
   NS_LOG_LOGIC("Node " << node->GetId() << ": added Face as face #"
                        << face->getLocalUri());
diff --git a/tests/unit-tests/model/ndn-net-device-face.t.cpp b/tests/unit-tests/model/ndn-net-device-face.t.cpp
index aad8c01..5269ed9 100644
--- a/tests/unit-tests/model/ndn-net-device-face.t.cpp
+++ b/tests/unit-tests/model/ndn-net-device-face.t.cpp
@@ -35,7 +35,12 @@
 
   createTopology({
       {"1", "2"},
-    });
+    }, false);
+
+  getNetDevice("1", "2")->SetAttribute("Address", StringValue("00:00:00:ff:ff:01"));
+  getNetDevice("2", "1")->SetAttribute("Address", StringValue("00:00:00:ff:ff:02"));
+
+  getStackHelper().InstallAll();
 
   addRoutes({
       {"1", "2", "/prefix", 1},
@@ -58,6 +63,14 @@
 
   BOOST_CHECK_EQUAL(getFace("2", "1")->getCounters().nInInterests, 100);
   BOOST_CHECK_EQUAL(getFace("2", "1")->getCounters().nOutData, 100);
+
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(*getFace("1", "2")), "netdev://[00:00:00:ff:ff:01]");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(*getFace("2", "1")), "netdev://[00:00:00:ff:ff:02]");
+
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(getFace("1", "2")->getLocalUri()),  "netdev://[00:00:00:ff:ff:01]");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(getFace("1", "2")->getRemoteUri()), "netdev://[00:00:00:ff:ff:02]");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(getFace("2", "1")->getLocalUri()),  "netdev://[00:00:00:ff:ff:02]");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(getFace("2", "1")->getRemoteUri()), "netdev://[00:00:00:ff:ff:01]");
 }
 
 BOOST_AUTO_TEST_SUITE_END()