model: Enabling face operations based on NFD's face

Refs: #2215
diff --git a/model/ndn-net-device-face.cpp b/model/ndn-net-device-face.cpp
index ae9de5d..03d95db 100644
--- a/model/ndn-net-device-face.cpp
+++ b/model/ndn-net-device-face.cpp
@@ -22,6 +22,8 @@
 #include "ndn-net-device-face.hpp"
 #include "ndn-l3-protocol.hpp"
 
+#include "ndn-ns3.hpp"
+
 #include "ns3/net-device.h"
 #include "ns3/log.h"
 #include "ns3/packet.h"
@@ -32,29 +34,39 @@
 #include "ns3/point-to-point-net-device.h"
 #include "ns3/channel.h"
 
+#include "../utils/ndn-fw-hop-count-tag.hpp"
+
 NS_LOG_COMPONENT_DEFINE("ndn.NetDeviceFace");
 
 namespace ns3 {
 namespace ndn {
 
-/**
- * By default, Ndn face are created in the "down" state.  Before
- * becoming useable, the user must invoke SetUp on the face
- */
 NetDeviceFace::NetDeviceFace(Ptr<Node> node, const Ptr<NetDevice>& netDevice)
-  // : Face(node)
-  : m_netDevice(netDevice)
+  : Face(FaceUri("netDeviceFace://"), FaceUri("netDeviceFace://"))
+  , m_node(node)
+  , m_netDevice(netDevice)
 {
   NS_LOG_FUNCTION(this << netDevice);
 
-  // SetMetric(1); // default metric
+  setMetric(1); // default metric
 
   NS_ASSERT_MSG(m_netDevice != 0, "NetDeviceFace needs to be assigned a valid NetDevice");
+
+  m_node->RegisterProtocolHandler(MakeCallback(&NetDeviceFace::receiveFromNetDevice, this),
+                                  L3Protocol::ETHERNET_FRAME_TYPE, m_netDevice,
+                                  true /*promiscuous mode*/);
 }
 
 NetDeviceFace::~NetDeviceFace()
 {
   NS_LOG_FUNCTION_NOARGS();
+
+  m_node->UnregisterProtocolHandler(MakeCallback(&NetDeviceFace::receiveFromNetDevice, this));
+}
+
+void
+NetDeviceFace::close()
+{
 }
 
 Ptr<NetDevice>
@@ -63,21 +75,70 @@
   return m_netDevice;
 }
 
-bool
-NetDeviceFace::Send(Ptr<Packet> packet)
+void
+NetDeviceFace::send(Ptr<Packet> packet)
 {
-  return false;
+  NS_ASSERT_MSG(packet->GetSize() <= m_netDevice->GetMtu(),
+                "Packet size " << packet->GetSize() << " exceeds device MTU "
+                               << m_netDevice->GetMtu());
+
+  FwHopCountTag tag;
+  packet->RemovePacketTag(tag);
+  tag.Increment();
+  packet->AddPacketTag(tag);
+
+  m_netDevice->Send(packet, m_netDevice->GetBroadcast(), L3Protocol::ETHERNET_FRAME_TYPE);
+}
+
+void
+NetDeviceFace::sendInterest(const Interest& interest)
+{
+  NS_LOG_FUNCTION(this << &interest);
+
+  this->onSendInterest(interest);
+
+  Ptr<Packet> packet = Convert::ToPacket(interest);
+  send(packet);
+}
+
+void
+NetDeviceFace::sendData(const Data& data)
+{
+  NS_LOG_FUNCTION(this << &data);
+
+  this->onSendData(data);
+
+  Ptr<Packet> packet = Convert::ToPacket(data);
+  send(packet);
 }
 
 // callback
 void
-NetDeviceFace::ReceiveFromNetDevice(Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol,
+NetDeviceFace::receiveFromNetDevice(Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol,
                                     const Address& from, const Address& to,
                                     NetDevice::PacketType packetType)
 {
   NS_LOG_FUNCTION(device << p << protocol << from << to << packetType);
-  // Receive(p);
+
+  Ptr<Packet> packet = p->Copy();
+  try {
+    uint32_t type = Convert::getPacketType(p);
+    if (type == ::ndn::tlv::Interest) {
+      shared_ptr<const Interest> i = Convert::FromPacket<Interest>(packet);
+      this->onReceiveInterest(*i);
+    }
+    else if (type == ::ndn::tlv::Data) {
+      shared_ptr<const Data> d = Convert::FromPacket<Data>(packet);
+      this->onReceiveData(*d);
+    }
+    else {
+      NS_LOG_ERROR("Unsupported TLV packet");
+    }
+  }
+  catch (::ndn::tlv::Error&) {
+    NS_LOG_ERROR("Unrecognized TLV packet");
+  }
 }
 
-} // namespace ndnsim
+} // namespace ndn
 } // namespace ns3