model: Major API changes

Interest and ContentObject are no longer derived from Header class.
Instead, they are encapsulating payload and, optionally, wire-formatted
Packet object.

Refs #1005 (http://redmine.named-data.net/)
diff --git a/model/cs/content-store-impl.h b/model/cs/content-store-impl.h
index ffe8038..9cd934e 100644
--- a/model/cs/content-store-impl.h
+++ b/model/cs/content-store-impl.h
@@ -44,8 +44,8 @@
   typedef Entry base_type;
 
 public:
-  EntryImpl (Ptr<ContentStore> cs, Ptr<const ContentObject> header, Ptr<const Packet> packet)
-    : Entry (cs, header, packet)
+  EntryImpl (Ptr<ContentStore> cs, Ptr<const ContentObject> data)
+    : Entry (cs, data)
     , item_ (0)
   {
   }
@@ -86,11 +86,11 @@
 
   // from ContentStore
 
-  virtual inline boost::tuple<Ptr<Packet>, Ptr<const ContentObject>, Ptr<const Packet> >
+  virtual inline Ptr<ContentObject>
   Lookup (Ptr<const Interest> interest);
 
   virtual inline bool
-  Add (Ptr<const ContentObject> header, Ptr<const Packet> packet);
+  Add (Ptr<const ContentObject> data);
 
   // virtual bool
   // Remove (Ptr<Interest> header);
@@ -156,7 +156,7 @@
 }
 
 template<class Policy>
-boost::tuple<Ptr<Packet>, Ptr<const ContentObject>, Ptr<const Packet> >
+Ptr<const ContentObject>
 ContentStoreImpl<Policy>::Lookup (Ptr<const Interest> interest)
 {
   NS_LOG_FUNCTION (this << interest->GetName ());
@@ -166,29 +166,27 @@
 
   if (node != this->end ())
     {
-      this->m_cacheHitsTrace (interest, node->payload ()->GetHeader ());
+      this->m_cacheHitsTrace (interest, node->payload ()->GetData ());
 
-      // NS_LOG_DEBUG ("cache hit with " << node->payload ()->GetHeader ()->GetName ());
-      return boost::make_tuple (node->payload ()->GetFullyFormedNdnPacket (),
-                                node->payload ()->GetHeader (),
-                                node->payload ()->GetPacket ());
+      Ptr<ContentObject> copy = Create<ContentObject> (node->payload ()->GetData ());
+      ConstCast<Packet> (copy->GetPayload ())->RemoveAllPacketTags ();
+      return copy;
     }
   else
     {
-      // NS_LOG_DEBUG ("cache miss for " << interest->GetName ());
       this->m_cacheMissesTrace (interest);
-      return boost::tuple<Ptr<Packet>, Ptr<ContentObject>, Ptr<Packet> > (0, 0, 0);
+      return 0;
     }
 }
 
 template<class Policy>
 bool
-ContentStoreImpl<Policy>::Add (Ptr<const ContentObject> header, Ptr<const Packet> packet)
+ContentStoreImpl<Policy>::Add (Ptr<const ContentObject> data)
 {
-  NS_LOG_FUNCTION (this << header->GetName ());
+  NS_LOG_FUNCTION (this << data->GetName ());
 
-  Ptr< entry > newEntry = Create< entry > (this, header, packet);
-  std::pair< typename super::iterator, bool > result = super::insert (header->GetName (), newEntry);
+  Ptr< entry > newEntry = Create< entry > (this, data);
+  std::pair< typename super::iterator, bool > result = super::insert (data->GetName (), newEntry);
 
   if (result.first != super::end ())
     {
diff --git a/model/cs/content-store-nocache.cc b/model/cs/content-store-nocache.cc
index 8814c13..c5749e2 100644
--- a/model/cs/content-store-nocache.cc
+++ b/model/cs/content-store-nocache.cc
@@ -55,15 +55,15 @@
 {
 }
 
-boost::tuple<Ptr<Packet>, Ptr<const ContentObject>, Ptr<const Packet> >
+Ptr<ContentObject>
 Nocache::Lookup (Ptr<const Interest> interest)
 {
   this->m_cacheMissesTrace (interest);
-  return boost::tuple<Ptr<Packet>, Ptr<const ContentObject>, Ptr<const Packet> > (0, 0, 0);
+  return 0;
 }
 
 bool
-Nocache::Add (Ptr<const ContentObject> header, Ptr<const Packet> packet)
+Nocache::Add (Ptr<const ContentObject> data)
 {
   return false;
 }
diff --git a/model/cs/content-store-nocache.h b/model/cs/content-store-nocache.h
index 6d38f40..79d1284 100644
--- a/model/cs/content-store-nocache.h
+++ b/model/cs/content-store-nocache.h
@@ -54,11 +54,11 @@
   virtual
   ~Nocache ();
 
-  virtual boost::tuple<Ptr<Packet>, Ptr<const ContentObject>, Ptr<const Packet> >
+  virtual Ptr<ContentObject>
   Lookup (Ptr<const Interest> interest);
 
   virtual bool
-  Add (Ptr<const ContentObject> header, Ptr<const Packet> packet);
+  Add (Ptr<const ContentObject> data);
 
   virtual void
   Print (std::ostream &os) const;
diff --git a/model/cs/content-store-with-freshness.h b/model/cs/content-store-with-freshness.h
index 81f8856..3ba871c 100644
--- a/model/cs/content-store-with-freshness.h
+++ b/model/cs/content-store-with-freshness.h
@@ -90,9 +90,9 @@
 
 template<class Policy>
 inline bool
-ContentStoreWithFreshness< Policy >::Add (Ptr<const ContentObject> header, Ptr<const Packet> packet)
+ContentStoreWithFreshness< Policy >::Add (Ptr<const ContentObject> data)
 {
-  bool ok = super::Add (header, packet);
+  bool ok = super::Add (data);
   if (!ok) return false;
 
   NS_LOG_DEBUG (header->GetName () << " added to cache");
diff --git a/model/cs/ndn-content-store.cc b/model/cs/ndn-content-store.cc
index c99d7ed..cfe362e 100644
--- a/model/cs/ndn-content-store.cc
+++ b/model/cs/ndn-content-store.cc
@@ -34,7 +34,7 @@
 
 NS_OBJECT_ENSURE_REGISTERED (ContentStore);
 
-TypeId 
+TypeId
 ContentStore::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::ndn::ContentStore")
@@ -60,24 +60,12 @@
 
 //////////////////////////////////////////////////////////////////////
 
-Entry::Entry (Ptr<ContentStore> cs, Ptr<const ContentObject> header, Ptr<const Packet> packet)
+Entry::Entry (Ptr<ContentStore> cs, Ptr<const ContentObject> data)
   : m_cs (cs)
-  , m_header (header)
-  , m_packet (packet->Copy ())
+  , m_data (data)
 {
 }
 
-Ptr<Packet>
-Entry::GetFullyFormedNdnPacket () const
-{
-  static ContentObjectTail tail; ///< \internal for optimization purposes
-
-  Ptr<Packet> packet = m_packet->Copy ();
-  packet->AddHeader (*m_header);
-  packet->AddTrailer (tail);
-  return packet;
-}
-
 const Name&
 Entry::GetName () const
 {
@@ -85,15 +73,9 @@
 }
 
 Ptr<const ContentObject>
-Entry::GetHeader () const
+Entry::GetData () const
 {
-  return m_header;
-}
-
-Ptr<const Packet>
-Entry::GetPacket () const
-{
-  return m_packet;
+  return m_data;
 }
 
 Ptr<ContentStore>
diff --git a/model/cs/ndn-content-store.h b/model/cs/ndn-content-store.h
index 54901d9..66e7667 100644
--- a/model/cs/ndn-content-store.h
+++ b/model/cs/ndn-content-store.h
@@ -36,13 +36,7 @@
 
 class ContentObject;
 class Interest;
-
-typedef Interest InterestHeader;
-typedef ContentObject ContentObjectHeader;
-
 class Name;
-typedef Name NameComponents;
-
 class ContentStore;
 
 namespace cs {
@@ -50,13 +44,6 @@
 /**
  * \ingroup ndn
  * \brief NDN content store entry
- *
- * Content store entry stores separately pseudo header and content of
- * ContentObject packet.  It is responsibility of the caller to
- * construct a fully formed NDN Packet by calling Copy(), AddHeader(),
- * AddTail() on the packet received by GetPacket() method.
- *
- * GetFullyFormedNdnPacket method provided as a convenience
  */
 class Entry : public SimpleRefCount<Entry>
 {
@@ -70,7 +57,7 @@
    * The constructor will make a copy of the supplied packet and calls
    * RemoveHeader and RemoveTail on the copy.
    */
-  Entry (Ptr<ContentStore> cs, Ptr<const ContentObject> header, Ptr<const Packet> packet);
+  Entry (Ptr<ContentStore> cs, Ptr<const ContentObject> data);
 
   /**
    * \brief Get prefix of the stored entry
@@ -84,21 +71,7 @@
    * \returns ContentObject of the stored entry
    */
   Ptr<const ContentObject>
-  GetHeader () const;
-
-  /**
-   * \brief Get content of the stored entry
-   * \returns content of the stored entry
-   */
-  Ptr<const Packet>
-  GetPacket () const;
-
-  /**
-   * \brief Convenience method to create a fully formed Ndn packet from stored header and content
-   * \returns A read-write copy of the packet with ContentObject and ContentObjectTail
-   */
-  Ptr<Packet>
-  GetFullyFormedNdnPacket () const;
+  GetData () const;
 
   /**
    * @brief Get pointer to access store, to which this entry is added
@@ -108,8 +81,7 @@
 
 private:
   Ptr<ContentStore> m_cs; ///< \brief content store to which entry is added
-  Ptr<const ContentObject> m_header; ///< \brief non-modifiable ContentObject
-  Ptr<Packet> m_packet; ///< \brief non-modifiable content of the ContentObject packet
+  Ptr<const ContentObject> m_data; ///< \brief non-modifiable ContentObject
 };
 
 } // namespace cs
@@ -147,7 +119,7 @@
    * If an entry is found, it is promoted to the top of most recent
    * used entries index, \see m_contentStore
    */
-  virtual boost::tuple<Ptr<Packet>, Ptr<const ContentObject>, Ptr<const Packet> >
+  virtual Ptr<ContentObject>
   Lookup (Ptr<const Interest> interest) = 0;
 
   /**
@@ -159,7 +131,7 @@
    * @returns true if an existing entry was updated, false otherwise
    */
   virtual bool
-  Add (Ptr<const ContentObject> header, Ptr<const Packet> packet) = 0;
+  Add (Ptr<const ContentObject> data) = 0;
 
   // /*
   //  * \brief Add a new content to the content store.
diff --git a/model/fw/best-route.cc b/model/fw/best-route.cc
index 21a6b57..f5ab205 100644
--- a/model/fw/best-route.cc
+++ b/model/fw/best-route.cc
@@ -65,17 +65,16 @@
 
 bool
 BestRoute::DoPropagateInterest (Ptr<Face> inFace,
-                                Ptr<const Interest> header,
-                                Ptr<const Packet> origPacket,
+                                Ptr<const Interest> interest,
                                 Ptr<pit::Entry> pitEntry)
 {
-  NS_LOG_FUNCTION (this << header->GetName ());
+  NS_LOG_FUNCTION (this << interest->GetName ());
 
   // No real need to call parent's (green-yellow-red's strategy) method, since it is incorporated
   // in the logic of the BestRoute strategy
   //
   // // Try to work out with just green faces
-  // bool greenOk = super::DoPropagateInterest (inFace, header, origPacket, pitEntry);
+  // bool greenOk = super::DoPropagateInterest (inFace, interest, origPacket, pitEntry);
   // if (greenOk)
   //   return true;
 
@@ -87,7 +86,7 @@
       if (metricFace.GetStatus () == fib::FaceMetric::NDN_FIB_RED) // all non-read faces are in front
         break;
 
-      if (!TrySendOutInterest (inFace, metricFace.GetFace (), header, origPacket, pitEntry))
+      if (!TrySendOutInterest (inFace, metricFace.GetFace (), interest, pitEntry))
         {
           continue;
         }
diff --git a/model/fw/best-route.h b/model/fw/best-route.h
index f7caa19..6648acb 100644
--- a/model/fw/best-route.h
+++ b/model/fw/best-route.h
@@ -58,8 +58,7 @@
   // from super
   virtual bool
   DoPropagateInterest (Ptr<Face> incomingFace,
-                       Ptr<const Interest> header,
-                       Ptr<const Packet> origPacket,
+                       Ptr<const Interest> interest,
                        Ptr<pit::Entry> pitEntry);
 protected:
   static LogComponent g_log;
diff --git a/model/fw/flooding.cc b/model/fw/flooding.cc
index 3672b24..3d93248 100644
--- a/model/fw/flooding.cc
+++ b/model/fw/flooding.cc
@@ -66,8 +66,7 @@
 
 bool
 Flooding::DoPropagateInterest (Ptr<Face> inFace,
-                               Ptr<const Interest> header,
-                               Ptr<const Packet> origPacket,
+                               Ptr<const Interest> interest,
                                Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this);
@@ -80,7 +79,7 @@
       if (metricFace.GetStatus () == fib::FaceMetric::NDN_FIB_RED) // all non-read faces are in the front of the list
         break;
 
-      if (!TrySendOutInterest (inFace, metricFace.GetFace (), header, origPacket, pitEntry))
+      if (!TrySendOutInterest (inFace, metricFace.GetFace (), interest, pitEntry))
         {
           continue;
         }
diff --git a/model/fw/flooding.h b/model/fw/flooding.h
index 5eadabb..f7ce55a 100644
--- a/model/fw/flooding.h
+++ b/model/fw/flooding.h
@@ -60,8 +60,7 @@
   // inherited from  Nacks/ForwardingStrategy
   virtual bool
   DoPropagateInterest (Ptr<Face> inFace,
-                       Ptr<const Interest> header,
-                       Ptr<const Packet> origPacket,
+                       Ptr<const Interest> interest,
                        Ptr<pit::Entry> pitEntry);
 
 protected:
diff --git a/model/fw/green-yellow-red.cc b/model/fw/green-yellow-red.cc
index 5d6a001..cb7fd89 100644
--- a/model/fw/green-yellow-red.cc
+++ b/model/fw/green-yellow-red.cc
@@ -64,8 +64,7 @@
 
 bool
 GreenYellowRed::DoPropagateInterest (Ptr<Face> inFace,
-                                     Ptr<const Interest> header,
-                                     Ptr<const Packet> origPacket,
+                                     Ptr<const Interest> interest,
                                      Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this);
@@ -79,7 +78,7 @@
           metricFace.GetStatus () == fib::FaceMetric::NDN_FIB_YELLOW)
         break; //propagate only to green faces
 
-      if (!TrySendOutInterest (inFace, metricFace.GetFace (), header, origPacket, pitEntry))
+      if (!TrySendOutInterest (inFace, metricFace.GetFace (), interest, pitEntry))
         {
           continue;
         }
@@ -123,11 +122,10 @@
 void
 GreenYellowRed::DidReceiveValidNack (Ptr<Face> inFace,
                                      uint32_t nackCode,
-                                     Ptr<const Interest> header,
-                                     Ptr<const Packet> origPacket,
+                                     Ptr<const Interest> nack,
                                      Ptr<pit::Entry> pitEntry)
 {
-  super::DidReceiveValidNack (inFace, nackCode, header, origPacket, pitEntry);
+  super::DidReceiveValidNack (inFace, nackCode, nack, pitEntry);
 
   if (inFace != 0 &&
       (nackCode == Interest::NACK_CONGESTION ||
diff --git a/model/fw/green-yellow-red.h b/model/fw/green-yellow-red.h
index 1c4dcde..11817bf 100644
--- a/model/fw/green-yellow-red.h
+++ b/model/fw/green-yellow-red.h
@@ -44,8 +44,7 @@
 
   virtual bool
   DoPropagateInterest (Ptr<Face> inFace,
-                       Ptr<const Interest> header,
-                       Ptr<const Packet> origPacket,
+                       Ptr<const Interest> interest,
                        Ptr<pit::Entry> pitEntry);
 
   virtual void
@@ -54,8 +53,7 @@
   virtual void
   DidReceiveValidNack (Ptr<Face> incomingFace,
                        uint32_t nackCode,
-                       Ptr<const Interest> header,
-                       Ptr<const Packet> origPacket,
+                       Ptr<const Interest> nack,
                        Ptr<pit::Entry> pitEntry);
 private:
   typedef Nacks super;
diff --git a/model/fw/nacks.cc b/model/fw/nacks.cc
index 6bafefb..357427c 100644
--- a/model/fw/nacks.cc
+++ b/model/fw/nacks.cc
@@ -75,82 +75,74 @@
 
 void
 Nacks::OnInterest (Ptr<Face> inFace,
-                   Ptr<const Interest> header,
-                   Ptr<const Packet> origPacket)
+                   Ptr<Interest> interest)
 {
-  if (header->GetNack () > 0)
-    OnNack (inFace, header, origPacket/*original packet*/);
+  if (interest->GetNack () > 0)
+    OnNack (inFace, header);
   else
-    super::OnInterest (inFace, header, origPacket/*original packet*/);
+    super::OnInterest (inFace, interest);
 }
 
 void
 Nacks::OnNack (Ptr<Face> inFace,
-               Ptr<const Interest> header,
-               Ptr<const Packet> origPacket)
+               Ptr<Interest> nack)
 {
   // NS_LOG_FUNCTION (inFace << header->GetName ());
-  m_inNacks (header, inFace);
+  m_inNacks (nack, inFace);
 
   Ptr<pit::Entry> pitEntry = m_pit->Lookup (*header);
   if (pitEntry == 0)
     {
       // somebody is doing something bad
-      m_dropNacks (header, inFace);
+      m_dropNacks (nack, inFace);
       return;
     }
 
-  DidReceiveValidNack (inFace, header->GetNack (), header, origPacket, pitEntry);
+  DidReceiveValidNack (inFace, header->GetNack (), nack, pitEntry);
 }
 
 void
 Nacks::DidReceiveDuplicateInterest (Ptr<Face> inFace,
-                                    Ptr<const Interest> header,
-                                    Ptr<const Packet> origPacket,
+                                    Ptr<const Interest> interest,
                                     Ptr<pit::Entry> pitEntry)
 {
-  super::DidReceiveDuplicateInterest (inFace, header, origPacket, pitEntry);
+  super::DidReceiveDuplicateInterest (inFace, interest, pitEntry);
 
   if (m_nacksEnabled)
     {
       NS_LOG_DEBUG ("Sending NACK_LOOP");
-      Ptr<Interest> nackHeader = Create<Interest> (*header);
-      nackHeader->SetNack (Interest::NACK_LOOP);
-      Ptr<Packet> nack = Create<Packet> ();
-      nack->AddHeader (*nackHeader);
+      Ptr<Interest> nack = Create<Interest> (*interest);
+      nack->SetNack (Interest::NACK_LOOP);
 
       FwHopCountTag hopCountTag;
-      if (origPacket->PeekPacketTag (hopCountTag))
+      if (interest->GetPayload ()->PeekPacketTag (hopCountTag))
         {
-     	  nack->AddPacketTag (hopCountTag);
+     	  nack->GetPayload ()->AddPacketTag (hopCountTag);
         }
       else
         {
           NS_LOG_DEBUG ("No FwHopCountTag tag associated with received duplicated Interest");
         }
 
-      inFace->Send (nack);
-      m_outNacks (nackHeader, inFace);
+      inFace->SendInterest (nack);
+      m_outNacks (nack, inFace);
     }
 }
 
 void
 Nacks::DidExhaustForwardingOptions (Ptr<Face> inFace,
-                                    Ptr<const Interest> header,
-                                    Ptr<const Packet> origPacket,
+                                    Ptr<const Interest> interest,
                                     Ptr<pit::Entry> pitEntry)
 {
   if (m_nacksEnabled)
     {
-      Ptr<Packet> packet = Create<Packet> ();
-      Ptr<Interest> nackHeader = Create<Interest> (*header);
-      nackHeader->SetNack (Interest::NACK_GIVEUP_PIT);
-      packet->AddHeader (*nackHeader);
+      Ptr<Interest> nack = Create<Interest> (*header);
+      nack->SetNack (Interest::NACK_GIVEUP_PIT);
 
       FwHopCountTag hopCountTag;
-      if (origPacket->PeekPacketTag (hopCountTag))
+      if (interest->GetPayload ()->PeekPacketTag (hopCountTag))
         {
-     	  packet->AddPacketTag (hopCountTag);
+     	  nack->GetPayload ()->AddPacketTag (hopCountTag);
         }
       else
         {
@@ -159,10 +151,9 @@
 
       BOOST_FOREACH (const pit::IncomingFace &incoming, pitEntry->GetIncoming ())
         {
-          NS_LOG_DEBUG ("Send NACK for " << boost::cref (nackHeader->GetName ()) << " to " << boost::cref (*incoming.m_face));
-          incoming.m_face->Send (packet->Copy ());
-
-          m_outNacks (nackHeader, incoming.m_face);
+          NS_LOG_DEBUG ("Send NACK for " << boost::cref (nack->GetName ()) << " to " << boost::cref (*incoming.m_face));
+          incoming.m_face->SendInterest (nack);
+          m_outNacks (nack, incoming.m_face);
         }
 
       pitEntry->ClearOutgoing (); // to force erasure of the record
@@ -174,11 +165,10 @@
 void
 Nacks::DidReceiveValidNack (Ptr<Face> inFace,
                             uint32_t nackCode,
-                            Ptr<const Interest> header,
-                            Ptr<const Packet> origPacket,
+                            Ptr<const Interest> nack,
                             Ptr<pit::Entry> pitEntry)
 {
-  NS_LOG_DEBUG ("nackCode: " << nackCode << " for [" << header->GetName () << "]");
+  NS_LOG_DEBUG ("nackCode: " << nackCode << " for [" << nack->GetName () << "]");
 
   // If NACK is NACK_GIVEUP_PIT, then neighbor gave up trying to and removed it's PIT entry.
   // So, if we had an incoming entry to this neighbor, then we can remove it now
@@ -198,29 +188,27 @@
           NS_LOG_DEBUG ("Not all outgoing are in vain");
           // suppress
           // Don't do anything, we are still expecting data from some other face
-          m_dropNacks (header, inFace);
+          m_dropNacks (nack, inFace);
           return;
         }
 
-      Ptr<Packet> nonNackInterest = Create<Packet> ();
-      Ptr<Interest> nonNackHeader = Create<Interest> (*header);
-      nonNackHeader->SetNack (Interest::NORMAL_INTEREST);
-      nonNackInterest->AddHeader (*nonNackHeader);
+      Ptr<Interest> interest = Create<Interest> (*nack);
+      interest->SetNack (Interest::NORMAL_INTEREST);
 
       FwHopCountTag hopCountTag;
-      if (origPacket->PeekPacketTag (hopCountTag))
+      if (nack->GetPayload ()->PeekPacketTag (hopCountTag))
         {
-     	  nonNackInterest->AddPacketTag (hopCountTag);
+     	  interest->GetPayload ()->AddPacketTag (hopCountTag);
         }
       else
         {
           NS_LOG_DEBUG ("No FwHopCountTag tag associated with received NACK");
         }
 
-      bool propagated = DoPropagateInterest (inFace, nonNackHeader, nonNackInterest, pitEntry);
+      bool propagated = DoPropagateInterest (inFace, interest, pitEntry);
       if (!propagated)
         {
-          DidExhaustForwardingOptions (inFace, nonNackHeader, nonNackInterest, pitEntry);
+          DidExhaustForwardingOptions (inFace, interest, pitEntry);
         }
     }
 }
diff --git a/model/fw/nacks.h b/model/fw/nacks.h
index 19a9ecb..7855e19 100644
--- a/model/fw/nacks.h
+++ b/model/fw/nacks.h
@@ -43,34 +43,29 @@
   // from super
   virtual void
   OnInterest (Ptr<Face> face,
-              Ptr<const Interest> header,
-              Ptr<const Packet> origPacket);
+              Ptr<Interest> interest);
 
 protected:
   // from super
   virtual void
   DidReceiveDuplicateInterest (Ptr<Face> inFace,
-                               Ptr<const Interest> header,
-                               Ptr<const Packet> packet,
+                               Ptr<const Interest> interest,
                                Ptr<pit::Entry> pitEntry);
 
   // from super
   virtual void
   DidExhaustForwardingOptions (Ptr<Face> inFace,
-                               Ptr<const Interest> header,
-                               Ptr<const Packet> packet,
+                               Ptr<const Interest> interest,
                                Ptr<pit::Entry> pitEntry);
 
   virtual void
   OnNack (Ptr<Face> inFace,
-          Ptr<const Interest> header,
-          Ptr<const Packet> origPacket);
+          Ptr<Interest> nack);
 
   virtual void
   DidReceiveValidNack (Ptr<Face> inFace,
                        uint32_t nackCode,
-                       Ptr<const Interest> header,
-                       Ptr<const Packet> origPacket,
+                       Ptr<const Interest> nack,
                        Ptr<pit::Entry> pitEntry);
   
 protected:  
diff --git a/model/fw/ndn-forwarding-strategy.cc b/model/fw/ndn-forwarding-strategy.cc
index 1d6bcda..ef61593 100644
--- a/model/fw/ndn-forwarding-strategy.cc
+++ b/model/fw/ndn-forwarding-strategy.cc
@@ -143,53 +143,48 @@
 
 void
 ForwardingStrategy::OnInterest (Ptr<Face> inFace,
-                                Ptr<const Interest> header,
-                                Ptr<const Packet> payload)
+                                Ptr<Interest> interest)
 {
-  m_inInterests (header, inFace);
+  m_inInterests (interest, inFace);
 
-  Ptr<pit::Entry> pitEntry = m_pit->Lookup (*header);
+  Ptr<pit::Entry> pitEntry = m_pit->Lookup (*interest);
   bool similarInterest = true;
   if (pitEntry == 0)
     {
       similarInterest = false;
-      pitEntry = m_pit->Create (header);
+      pitEntry = m_pit->Create (interest);
       if (pitEntry != 0)
         {
-          DidCreatePitEntry (inFace, header, origPacket, pitEntry);
+          DidCreatePitEntry (inFace, interest, pitEntry);
         }
       else
         {
-          FailedToCreatePitEntry (inFace, header, origPacket);
+          FailedToCreatePitEntry (inFace, interest);
           return;
         }
     }
 
   bool isDuplicated = true;
-  if (!pitEntry->IsNonceSeen (header->GetNonce ()))
+  if (!pitEntry->IsNonceSeen (interest->GetNonce ()))
     {
-      pitEntry->AddSeenNonce (header->GetNonce ());
+      pitEntry->AddSeenNonce (interest->GetNonce ());
       isDuplicated = false;
     }
 
   if (isDuplicated)
     {
-      DidReceiveDuplicateInterest (inFace, header, origPacket, pitEntry);
+      DidReceiveDuplicateInterest (inFace, interest, pitEntry);
       return;
     }
 
-  Ptr<Packet> contentObject;
-  Ptr<const ContentObject> contentObjectHeader; // used for tracing
-  Ptr<const Packet> payload; // used for tracing
-  boost::tie (contentObject, contentObjectHeader, payload) = m_contentStore->Lookup (header);
+  Ptr<ContentObject> contentObject;
+  contentObject = m_contentStore->Lookup (interest);
   if (contentObject != 0)
     {
-      NS_ASSERT (contentObjectHeader != 0);
-
       FwHopCountTag hopCountTag;
-      if (origPacket->PeekPacketTag (hopCountTag))
+      if (interest->GetPayload ()->PeekPacketTag (hopCountTag))
         {
-          contentObject->AddPacketTag (hopCountTag);
+          contentObject->GetPayload ()->AddPacketTag (hopCountTag);
         }
 
       pitEntry->AddIncoming (inFace/*, Seconds (1.0)*/);
@@ -198,55 +193,49 @@
       WillSatisfyPendingInterest (0, pitEntry);
 
       // Actually satisfy pending interest
-      SatisfyPendingInterest (0, contentObjectHeader, payload, contentObject, pitEntry);
+      SatisfyPendingInterest (0, contentObject, pitEntry);
       return;
     }
 
-  if (similarInterest && ShouldSuppressIncomingInterest (inFace, header, origPacket, pitEntry))
+  if (similarInterest && ShouldSuppressIncomingInterest (inFace, interest, pitEntry))
     {
-      pitEntry->AddIncoming (inFace/*, header->GetInterestLifetime ()*/);
+      pitEntry->AddIncoming (inFace/*, interest->GetInterestLifetime ()*/);
       // update PIT entry lifetime
-      pitEntry->UpdateLifetime (header->GetInterestLifetime ());
+      pitEntry->UpdateLifetime (interest->GetInterestLifetime ());
 
       // Suppress this interest if we're still expecting data from some other face
       NS_LOG_DEBUG ("Suppress interests");
-      m_dropInterests (header, inFace);
+      m_dropInterests (interest, inFace);
 
-      DidSuppressSimilarInterest (inFace, header, origPacket, pitEntry);
+      DidSuppressSimilarInterest (inFace, interest, pitEntry);
       return;
     }
 
   if (similarInterest)
     {
-      DidForwardSimilarInterest (inFace, header, origPacket, pitEntry);
+      DidForwardSimilarInterest (inFace, interest, pitEntry);
     }
 
-  PropagateInterest (inFace, header, origPacket, pitEntry);
+  PropagateInterest (inFace, interest, pitEntry);
 }
 
 void
 ForwardingStrategy::OnData (Ptr<Face> inFace,
-                            Ptr<const ContentObject> header,
-                            Ptr<Packet> payload)
+                            Ptr<ContentObject> data)
 {
-  NS_LOG_FUNCTION (inFace << header->GetName () << payload);
-  m_inData (header, payload, inFace);
+  NS_LOG_FUNCTION (inFace << data->GetName ());
+  m_inData (data, inFace);
 
   // Lookup PIT entry
-  Ptr<pit::Entry> pitEntry = m_pit->Lookup (*header);
+  Ptr<pit::Entry> pitEntry = m_pit->Lookup (*data);
   if (pitEntry == 0)
     {
       bool cached = false;
 
       if (m_cacheUnsolicitedData || (m_cacheUnsolicitedDataFromApps && (inFace->GetFlags () | Face::APPLICATION)))
         {
-          FwHopCountTag hopCountTag;
-
-          Ptr<Packet> payloadCopy = payload->Copy ();
-          payloadCopy->RemovePacketTag (hopCountTag);
-
           // Optimistically add or update entry in the content store
-          cached = m_contentStore->Add (header, payloadCopy);
+          cached = m_contentStore->Add (data);
         }
       else
         {
@@ -254,32 +243,16 @@
           // (unsolicited data packets should not "poison" content store)
 
           //drop dulicated or not requested data packet
-          m_dropData (header, payload, inFace);
+          m_dropData (data, inFace);
         }
 
-      DidReceiveUnsolicitedData (inFace, header, payload, cached);
+      DidReceiveUnsolicitedData (inFace, data, cached);
       return;
     }
   else
     {
-      bool cached = false;
-
-      FwHopCountTag hopCountTag;
-      if (payload->PeekPacketTag (hopCountTag))
-        {
-          Ptr<Packet> payloadCopy = payload->Copy ();
-          payloadCopy->RemovePacketTag (hopCountTag);
-
-          // Add or update entry in the content store
-          cached = m_contentStore->Add (header, payloadCopy);
-        }
-      else
-        {
-          // Add or update entry in the content store
-          cached = m_contentStore->Add (header, payload); // no need for extra copy
-        }
-
-      DidReceiveSolicitedData (inFace, header, payload, cached);
+      bool cached = m_contentStore->Add (data);
+      DidReceiveSolicitedData (inFace, data, cached);
     }
 
   while (pitEntry != 0)
@@ -297,24 +270,21 @@
 
 void
 ForwardingStrategy::DidCreatePitEntry (Ptr<Face> inFace,
-                                       Ptr<const Interest> header,
-                                       Ptr<const Packet> payload,
+                                       Ptr<const Interest> interest,
                                        Ptr<pit::Entry> pitEntrypitEntry)
 {
 }
 
 void
 ForwardingStrategy::FailedToCreatePitEntry (Ptr<Face> inFace,
-                                            Ptr<const Interest> header,
-                                            Ptr<const Packet> payload)
+                                            Ptr<const Interest> interest)
 {
-  m_dropInterests (header, inFace);
+  m_dropInterests (interest, inFace);
 }
 
 void
 ForwardingStrategy::DidReceiveDuplicateInterest (Ptr<Face> inFace,
-                                                 Ptr<const Interest> header,
-                                                 Ptr<const Packet> payload,
+                                                 Ptr<const Interest> interest,
                                                  Ptr<pit::Entry> pitEntry)
 {
   /////////////////////////////////////////////////////////////////////////////////////////
@@ -323,35 +293,32 @@
   //                                                                                     //
   /////////////////////////////////////////////////////////////////////////////////////////
   pitEntry->AddIncoming (inFace);
-  m_dropInterests (header, inFace);
+  m_dropInterests (interest, inFace);
 }
 
 void
 ForwardingStrategy::DidSuppressSimilarInterest (Ptr<Face> face,
-                                                Ptr<const Interest> header,
-                                                Ptr<const Packet> payload,
+                                                Ptr<const Interest> interest,
                                                 Ptr<pit::Entry> pitEntry)
 {
 }
 
 void
 ForwardingStrategy::DidForwardSimilarInterest (Ptr<Face> inFace,
-                                               Ptr<const Interest> header,
-                                               Ptr<const Packet> payload,
+                                               Ptr<const Interest> interest,
                                                Ptr<pit::Entry> pitEntry)
 {
 }
 
 void
 ForwardingStrategy::DidExhaustForwardingOptions (Ptr<Face> inFace,
-                                                 Ptr<const Interest> header,
-                                                 Ptr<const Packet> payload,
+                                                 Ptr<const Interest> interest,
                                                  Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this << boost::cref (*inFace));
   if (pitEntry->AreAllOutgoingInVain ())
     {
-      m_dropInterests (header, inFace);
+      m_dropInterests (interest, inFace);
 
       // All incoming interests cannot be satisfied. Remove them
       pitEntry->ClearIncoming ();
@@ -368,8 +335,7 @@
 
 bool
 ForwardingStrategy::DetectRetransmittedInterest (Ptr<Face> inFace,
-                                                 Ptr<const Interest> header,
-                                                 Ptr<const Packet> payload,
+                                                 Ptr<const Interest> interest,
                                                  Ptr<pit::Entry> pitEntry)
 {
   pit::Entry::in_iterator existingInFace = pitEntry->GetIncoming ().find (inFace);
@@ -387,8 +353,7 @@
 
 void
 ForwardingStrategy::SatisfyPendingInterest (Ptr<Face> inFace,
-                                            Ptr<const ContentObject> header,
-                                            Ptr<const Packet> payload,
+                                            Ptr<const ContentObject> data,
                                             Ptr<pit::Entry> pitEntry)
 {
   if (inFace != 0)
@@ -397,14 +362,14 @@
   //satisfy all pending incoming Interests
   BOOST_FOREACH (const pit::IncomingFace &incoming, pitEntry->GetIncoming ())
     {
-      bool ok = incoming.m_face->SendData (header, payload);
+      bool ok = incoming.m_face->SendData (data);
 
-      DidSendOutData (inFace, incoming.m_face, header, payload, origPacket, pitEntry);
+      DidSendOutData (inFace, incoming.m_face, data, pitEntry);
       NS_LOG_DEBUG ("Satisfy " << *incoming.m_face);
 
       if (!ok)
         {
-          m_dropData (header, payload, incoming.m_face);
+          m_dropData (data, incoming.m_face);
           NS_LOG_DEBUG ("Cannot satisfy data to " << *incoming.m_face);
         }
     }
@@ -421,8 +386,7 @@
 
 void
 ForwardingStrategy::DidReceiveSolicitedData (Ptr<Face> inFace,
-                                             Ptr<const ContentObject> header,
-                                             Ptr<const Packet> payload,
+                                             Ptr<const ContentObject> data,
                                              bool didCreateCacheEntry)
 {
   // do nothing
@@ -430,8 +394,7 @@
 
 void
 ForwardingStrategy::DidReceiveUnsolicitedData (Ptr<Face> inFace,
-                                               Ptr<const ContentObject> header,
-                                               Ptr<const Packet> payload,
+                                               Ptr<const ContentObject> data,
                                                bool didCreateCacheEntry)
 {
   // do nothing
@@ -454,8 +417,7 @@
 
 bool
 ForwardingStrategy::ShouldSuppressIncomingInterest (Ptr<Face> inFace,
-                                                    Ptr<const Interest> header,
-                                                    Ptr<const Packet> payload,
+                                                    Ptr<const Interest> interest,
                                                     Ptr<pit::Entry> pitEntry)
 {
   bool isNew = pitEntry->GetIncoming ().size () == 0 && pitEntry->GetOutgoing ().size () == 0;
@@ -463,7 +425,7 @@
   if (isNew) return false; // never suppress new interests
 
   bool isRetransmitted = m_detectRetransmissions && // a small guard
-                         DetectRetransmittedInterest (inFace, header, origPacket, pitEntry);
+                         DetectRetransmittedInterest (inFace, interest, pitEntry);
 
   if (pitEntry->GetOutgoing ().find (inFace) != pitEntry->GetOutgoing ().end ())
     {
@@ -489,18 +451,17 @@
 
 void
 ForwardingStrategy::PropagateInterest (Ptr<Face> inFace,
-                                       Ptr<const Interest> header,
-                                       Ptr<const Packet> payload,
+                                       Ptr<const Interest> interest,
                                        Ptr<pit::Entry> pitEntry)
 {
   bool isRetransmitted = m_detectRetransmissions && // a small guard
-                         DetectRetransmittedInterest (inFace, header, origPacket, pitEntry);
+                         DetectRetransmittedInterest (inFace, interest, pitEntry);
 
-  pitEntry->AddIncoming (inFace/*, header->GetInterestLifetime ()*/);
+  pitEntry->AddIncoming (inFace/*, interest->GetInterestLifetime ()*/);
   /// @todo Make lifetime per incoming interface
-  pitEntry->UpdateLifetime (header->GetInterestLifetime ());
+  pitEntry->UpdateLifetime (interest->GetInterestLifetime ());
 
-  bool propagated = DoPropagateInterest (inFace, header, payload, origPacket, pitEntry);
+  bool propagated = DoPropagateInterest (inFace, interest, pitEntry);
 
   if (!propagated && isRetransmitted) //give another chance if retransmitted
     {
@@ -508,13 +469,13 @@
       pitEntry->IncreaseAllowedRetxCount ();
 
       // try again
-      propagated = DoPropagateInterest (inFace, header, payload, origPacket, pitEntry);
+      propagated = DoPropagateInterest (inFace, interest, pitEntry);
     }
 
   // if (!propagated)
   //   {
   //     NS_LOG_DEBUG ("++++++++++++++++++++++++++++++++++++++++++++++++++++++");
-  //     NS_LOG_DEBUG ("+++ Not propagated ["<< header->GetName () <<"], but number of outgoing faces: " << pitEntry->GetOutgoing ().size ());
+  //     NS_LOG_DEBUG ("+++ Not propagated ["<< interest->GetName () <<"], but number of outgoing faces: " << pitEntry->GetOutgoing ().size ());
   //     NS_LOG_DEBUG ("++++++++++++++++++++++++++++++++++++++++++++++++++++++");
   //   }
 
@@ -523,15 +484,14 @@
   // ForwardingStrategy failed to find it.
   if (!propagated && pitEntry->AreAllOutgoingInVain ())
     {
-      DidExhaustForwardingOptions (inFace, header, payload, origPacket, pitEntry);
+      DidExhaustForwardingOptions (inFace, interest, pitEntry);
     }
 }
 
 bool
 ForwardingStrategy::CanSendOutInterest (Ptr<Face> inFace,
                                         Ptr<Face> outFace,
-                                        Ptr<const Interest> header,
-                                        Ptr<const Packet> payload,
+                                        Ptr<const Interest> interest,
                                         Ptr<pit::Entry> pitEntry)
 {
   if (outFace == inFace)
@@ -561,11 +521,10 @@
 bool
 ForwardingStrategy::TrySendOutInterest (Ptr<Face> inFace,
                                         Ptr<Face> outFace,
-                                        Ptr<const Interest> header,
-                                        Ptr<const Packet> payload,
+                                        Ptr<const Interest> interest,
                                         Ptr<pit::Entry> pitEntry)
 {
-  if (!CanSendOutInterest (inFace, outFace, header, payload, pitEntry))
+  if (!CanSendOutInterest (inFace, outFace, interest, pitEntry))
     {
       return false;
     }
@@ -573,13 +532,13 @@
   pitEntry->AddOutgoing (outFace);
 
   //transmission
-  bool successSend = outFace->SendInterest (header, payload);
+  bool successSend = outFace->SendInterest (interest);
   if (!successSend)
     {
-      m_dropInterests (header, outFace);
+      m_dropInterests (interest, outFace);
     }
 
-  DidSendOutInterest (inFace, outFace, header, payload, pitEntry);
+  DidSendOutInterest (inFace, outFace, interest, pitEntry);
 
   return true;
 }
@@ -587,21 +546,19 @@
 void
 ForwardingStrategy::DidSendOutInterest (Ptr<Face> inFace,
                                         Ptr<Face> outFace,
-                                        Ptr<const Interest> header,
-                                        Ptr<const Packet> payload,
+                                        Ptr<const Interest> interest,
                                         Ptr<pit::Entry> pitEntry)
 {
-  m_outInterests (header, outFace);
+  m_outInterests (interest, outFace);
 }
 
 void
 ForwardingStrategy::DidSendOutData (Ptr<Face> inFace,
                                     Ptr<Face> outFace,
-                                    Ptr<const ContentObject> header,
-                                    Ptr<const Packet> payload,
+                                    Ptr<const ContentObject> data,
                                     Ptr<pit::Entry> pitEntry)
 {
-  m_outData (header, payload, inFace == 0, outFace);
+  m_outData (data, inFace == 0, outFace);
 }
 
 void
diff --git a/model/fw/ndn-forwarding-strategy.h b/model/fw/ndn-forwarding-strategy.h
index 45ccc55..49b034b 100644
--- a/model/fw/ndn-forwarding-strategy.h
+++ b/model/fw/ndn-forwarding-strategy.h
@@ -49,7 +49,7 @@
     public Object
 {
 public:
-  static TypeId GetTypeId (void);
+  static TypeId GetTypeId ();
 
   /**
    * @brief Helper function to retrieve logging name for the forwarding strategy
@@ -66,27 +66,23 @@
    * \brief Actual processing of incoming Ndn interests. Note, interests do not have payload
    *
    * Processing Interest packets
-   * @param face    incoming face
-   * @param header  deserialized Interest header
-   * @param origPacket  original packet
+   * @param face     incoming face
+   * @param interest Interest packet
    */
   virtual void
   OnInterest (Ptr<Face> face,
-              Ptr<const Interest> header,
-              Ptr<const Packet> payload);
+              Ptr<Interest> interest);
 
   /**
    * \brief Actual processing of incoming Ndn content objects
    *
    * Processing ContentObject packets
    * @param face    incoming face
-   * @param header  deserialized ContentObject header
-   * @param payload data packet payload
+   * @param data    Data packet
    */
   virtual void
   OnData (Ptr<Face> face,
-          Ptr<const ContentObject> header,
-          Ptr<Packet> payload);
+          Ptr<ContentObject> data);
 
   /**
    * @brief Event fired just before PIT entry is removed by timeout
@@ -143,8 +139,7 @@
    */
   virtual void
   DidCreatePitEntry (Ptr<Face> inFace,
-                     Ptr<const Interest> header,
-                     Ptr<const Packet> payload,
+                     Ptr<const Interest> interest,
                      Ptr<pit::Entry> pitEntry);
 
   /**
@@ -153,13 +148,12 @@
    * Note that this call can be called only for non-similar Interest (i.e., there is an attempt to create a new PIT entry).
    * For any non-similar Interests, either FailedToCreatePitEntry or DidCreatePitEntry is called.
    *
-   * @param inFace  incoming face
-   * @param header  deserialized Interest header
+   * @param inFace   incoming face
+   * @param interest Interest packet
    */
   virtual void
   FailedToCreatePitEntry (Ptr<Face> inFace,
-                          Ptr<const Interest> header,
-                          Ptr<const Packet> payload);
+                          Ptr<const Interest> interest);
 
   /**
    * @brief An event that is fired every time a duplicated Interest is received
@@ -167,15 +161,14 @@
    * This even is the last action that is performed before the Interest processing is halted
    *
    * @param inFace  incoming face
-   * @param header  deserialized Interest header
+   * @param interest Interest packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    *
    * @see DidReceiveDuplicateInterest, DidSuppressSimilarInterest, DidForwardSimilarInterest, ShouldSuppressIncomingInterest
    */
   virtual void
   DidReceiveDuplicateInterest (Ptr<Face> inFace,
-                               Ptr<const Interest> header,
-                               Ptr<const Packet> payload,
+                               Ptr<const Interest> interest,
                                Ptr<pit::Entry> pitEntry);
 
   /**
@@ -184,15 +177,14 @@
    * This even is the last action that is performed before the Interest processing is halted
    *
    * @param inFace  incoming face
-   * @param header  deserialized Interest header
+   * @param interest Interest packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    *
    * @see DidReceiveDuplicateInterest, DidForwardSimilarInterest, ShouldSuppressIncomingInterest
    */
   virtual void
   DidSuppressSimilarInterest (Ptr<Face> inFace,
-                              Ptr<const Interest> header,
-                              Ptr<const Packet> payload,
+                              Ptr<const Interest> interest,
                               Ptr<pit::Entry> pitEntry);
 
   /**
@@ -201,15 +193,14 @@
    * This even is fired just before handling the Interest to PropagateInterest method
    *
    * @param inFace  incoming face
-   * @param header  deserialized Interest header
+   * @param interest Interest packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    *
    * @see DidReceiveDuplicateInterest, DidSuppressSimilarInterest, ShouldSuppressIncomingInterest
    */
   virtual void
   DidForwardSimilarInterest (Ptr<Face> inFace,
-                             Ptr<const Interest> header,
-                             Ptr<const Packet> payload,
+                             Ptr<const Interest> interest,
                              Ptr<pit::Entry> pitEntry);
 
   /**
@@ -219,15 +210,14 @@
    * and retransmitted Interest cannot by forwarded.  For more details, refer to the implementation.
    *
    * @param inFace  incoming face
-   * @param header  deserialized Interest header
+   * @param interest Interest header
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    *
    * @see DetectRetransmittedInterest
    */
   virtual void
   DidExhaustForwardingOptions (Ptr<Face> inFace,
-                               Ptr<const Interest> header,
-                               Ptr<const Packet> payload,
+                               Ptr<const Interest> interest,
                                Ptr<pit::Entry> pitEntry);
 
   /**
@@ -239,14 +229,13 @@
    * already has inFace (i.e., a similar interest is received on the same face more than once).
    *
    * @param inFace  incoming face
-   * @param header  deserialized Interest header
+   * @param interest Interest header
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    * @return true if Interest should be considered as retransmitted
    */
   virtual bool
   DetectRetransmittedInterest (Ptr<Face> inFace,
-                               Ptr<const Interest> header,
-                               Ptr<const Packet> payload,
+                               Ptr<const Interest> interest,
                                Ptr<pit::Entry> pitEntry);
 
   /**
@@ -267,44 +256,38 @@
    * Note that when Interest is satisfied from the cache, incoming face will be 0
    *
    * @param inFace  incoming face
-   * @param header  deserialized ContentObject header
-   * @param payload ContentObject payload
+   * @param data    Data packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    */
   virtual void
   SatisfyPendingInterest (Ptr<Face> inFace, // 0 allowed (from cache)
-                          Ptr<const ContentObject> header,
-                          Ptr<const Packet> payload,
+                          Ptr<const ContentObject> data,
                           Ptr<pit::Entry> pitEntry);
 
   /**
    * @brief Event which is fired just after data was send out on the face
    *
-   * @param inFace     incoming face of the ContentObject
+   * @param inFace   incoming face of the ContentObject
    * @param outFace  outgoing face
-   * @param header  deserialized ContentObject header
-   * @param payload ContentObject payload
+   * @param data     Data packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    */
   virtual void
   DidSendOutData (Ptr<Face> inFace,
                   Ptr<Face> outFace,
-                  Ptr<const ContentObject> header,
-                  Ptr<const Packet> payload,
+                  Ptr<const ContentObject> data,
                   Ptr<pit::Entry> pitEntry);
 
   /**
    * @brief Event which is fired every time a requested (solicited) DATA packet (there is an active PIT entry) is received
    *
    * @param inFace  incoming face
-   * @param header  deserialized ContentObject header
-   * @param payload ContentObject payload
+   * @param data    Data packet
    * @param didCreateCacheEntry flag indicating whether a cache entry was added for this data packet or not (e.g., packet already exists in cache)
    */
   virtual void
   DidReceiveSolicitedData (Ptr<Face> inFace,
-                           Ptr<const ContentObject> header,
-                           Ptr<const Packet> payload,
+                           Ptr<const ContentObject> data,
                            bool didCreateCacheEntry);
 
   /**
@@ -314,14 +297,12 @@
    * attribute CacheUnsolicitedData true
    *
    * @param inFace  incoming face
-   * @param header  deserialized ContentObject header
-   * @param payload ContentObject payload
+   * @param data    Data packet
    * @param didCreateCacheEntry flag indicating whether a cache entry was added for this data packet or not (e.g., packet already exists in cache)
    */
   virtual void
   DidReceiveUnsolicitedData (Ptr<Face> inFace,
-                             Ptr<const ContentObject> header,
-                             Ptr<const Packet> payload,
+                             Ptr<const ContentObject> data,
                              bool didCreateCacheEntry);
 
   /**
@@ -333,13 +314,12 @@
    * For more details, refer to the source code.
    *
    * @param inFace  incoming face
-   * @param header  deserialized ContentObject header
+   * @param interest Interest packet
    * @param payload ContentObject payload
    */
   virtual bool
   ShouldSuppressIncomingInterest (Ptr<Face> inFace,
-                                  Ptr<const Interest> header,
-                                  Ptr<const Packet> payload,
+                                  Ptr<const Interest> interest,
                                   Ptr<pit::Entry> pitEntry);
 
   /**
@@ -352,7 +332,7 @@
    *
    * @param inFace     incoming face of the Interest
    * @param outFace    proposed outgoing face of the Interest
-   * @param header     parsed Interest header
+   * @param interest   Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    *
    * @see DetectRetransmittedInterest
@@ -360,8 +340,7 @@
   virtual bool
   CanSendOutInterest (Ptr<Face> inFace,
                       Ptr<Face> outFace,
-                      Ptr<const Interest> header,
-                      Ptr<const Packet> payload,
+                      Ptr<const Interest> interest,
                       Ptr<pit::Entry> pitEntry);
 
   /**
@@ -371,7 +350,7 @@
    *
    * @param inFace     incoming face of the Interest
    * @param outFace    proposed outgoing face of the Interest
-   * @param header     parsed Interest header
+   * @param interest Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    *
    * @see CanSendOutInterest
@@ -379,8 +358,7 @@
   virtual bool
   TrySendOutInterest (Ptr<Face> inFace,
                       Ptr<Face> outFace,
-                      Ptr<const Interest> header,
-                      Ptr<const Packet> payload,
+                      Ptr<const Interest> interest,
                       Ptr<pit::Entry> pitEntry);
 
   /**
@@ -388,13 +366,13 @@
    *
    * @param inFace     incoming face of the Interest
    * @param outFace    outgoing face of the Interest
-   * @param header     parsed Interest header
+   * @param interest Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    */
   virtual void
   DidSendOutInterest (Ptr<Face> inFace,
                       Ptr<Face> outFace,
-                      Ptr<const Interest> header,
+                      Ptr<const Interest> interest,
                       Ptr<pit::Entry> pitEntry);
 
   /**
@@ -404,15 +382,14 @@
    * PIT entry lifetime, calling DoPropagateInterest, and retransmissions (enabled by default).
    *
    * @param inFace     incoming face
-   * @param header     Interest header
+   * @param interest   Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    *
    * @see DoPropagateInterest
    */
   virtual void
   PropagateInterest (Ptr<Face> inFace,
-                     Ptr<const Interest> header,
-                     Ptr<const Packet> payload,
+                     Ptr<const Interest> interest,
                      Ptr<pit::Entry> pitEntry);
 
   /**
@@ -426,7 +403,7 @@
    * PIT entry lifetime, calling DoPropagateInterest, as well as perform retransmissions (enabled by default).
    *
    * @param inFace     incoming face
-   * @param header     Interest header
+   * @param interest   Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    *
    * @return true if interest was successfully propagated, false if all options have failed
@@ -435,8 +412,7 @@
    */
   virtual bool
   DoPropagateInterest (Ptr<Face> inFace,
-                       Ptr<const Interest> header,
-                       Ptr<const Packet> payload,
+                       Ptr<const Interest> interest,
                        Ptr<pit::Entry> pitEntry) = 0;
 
 protected:
@@ -453,27 +429,27 @@
   bool m_cacheUnsolicitedData;
   bool m_detectRetransmissions;
 
-  TracedCallback<Ptr<const Interest>, Ptr<const Packet>,
+  TracedCallback<Ptr<const Interest>,
                  Ptr<const Face> > m_outInterests; ///< @brief Transmitted interests trace
 
-  TracedCallback<Ptr<const Interest>, Ptr<const Packet>,
+  TracedCallback<Ptr<const Interest>,
                  Ptr<const Face> > m_inInterests; ///< @brief trace of incoming Interests
 
-  TracedCallback<Ptr<const Interest>, Ptr<const Packet>,
+  TracedCallback<Ptr<const Interest>,
                  Ptr<const Face> > m_dropInterests; ///< @brief trace of dropped Interests
 
   ////////////////////////////////////////////////////////////////////
   ////////////////////////////////////////////////////////////////////
   ////////////////////////////////////////////////////////////////////
 
-  TracedCallback<Ptr<const ContentObject>, Ptr<const Packet>,
+  TracedCallback<Ptr<const ContentObject>,
                  bool /*from cache*/,
                  Ptr<const Face> > m_outData; ///< @brief trace of outgoing Data
 
-  TracedCallback<Ptr<const ContentObject>, Ptr<const Packet>,
+  TracedCallback<Ptr<const ContentObject>,
                  Ptr<const Face> > m_inData; ///< @brief trace of incoming Data
 
-  TracedCallback<Ptr<const ContentObject>, Ptr<const Packet>,
+  TracedCallback<Ptr<const ContentObject>,
                   Ptr<const Face> > m_dropData;  ///< @brief trace of dropped Data
 
   ////////////////////////////////////////////////////////////////////
diff --git a/model/fw/per-fib-limits.h b/model/fw/per-fib-limits.h
index 633bd5e..560432a 100644
--- a/model/fw/per-fib-limits.h
+++ b/model/fw/per-fib-limits.h
@@ -99,8 +99,7 @@
   virtual bool
   CanSendOutInterest (Ptr<Face> inFace,
                       Ptr<Face> outFace,
-                      Ptr<const Interest> header,
-                      Ptr<const Packet> origPacket,
+                      Ptr<const Interest> interest,
                       Ptr<pit::Entry> pitEntry);
 
   /// \copydoc ForwardingStrategy::WillSatisfyPendingInterest
@@ -141,8 +140,7 @@
 bool
 PerFibLimits<Parent>::CanSendOutInterest (Ptr<Face> inFace,
                                           Ptr<Face> outFace,
-                                          Ptr<const Interest> header,
-                                          Ptr<const Packet> origPacket,
+                                          Ptr<const Interest> interest,
                                           Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
@@ -152,7 +150,7 @@
 
   if (fibLimits->IsBelowLimit ())
     {
-      if (super::CanSendOutInterest (inFace, outFace, header, origPacket, pitEntry))
+      if (super::CanSendOutInterest (inFace, outFace, interest, pitEntry))
         {
           fibLimits->BorrowLimit ();
           return true;
@@ -185,7 +183,7 @@
 template<class Parent>
 void
 PerFibLimits<Parent>::WillSatisfyPendingInterest (Ptr<Face> inFace,
-                                                        Ptr<pit::Entry> pitEntry)
+                                                  Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
 
diff --git a/model/fw/per-out-face-limits.h b/model/fw/per-out-face-limits.h
index 08e892b..fcdd43f 100644
--- a/model/fw/per-out-face-limits.h
+++ b/model/fw/per-out-face-limits.h
@@ -87,8 +87,7 @@
   virtual bool
   CanSendOutInterest (Ptr<Face> inFace,
                       Ptr<Face> outFace,
-                      Ptr<const Interest> header,
-                      Ptr<const Packet> origPacket,
+                      Ptr<const Interest> interest,
                       Ptr<pit::Entry> pitEntry);
   
   /// \copydoc ForwardingStrategy::WillSatisfyPendingInterest
@@ -134,8 +133,7 @@
 bool
 PerOutFaceLimits<Parent>::CanSendOutInterest (Ptr<Face> inFace,
                                               Ptr<Face> outFace,
-                                              Ptr<const Interest> header,
-                                              Ptr<const Packet> origPacket,
+                                              Ptr<const Interest> interest,
                                               Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
@@ -143,7 +141,7 @@
   Ptr<Limits> faceLimits = outFace->template GetObject<Limits> ();
   if (faceLimits->IsBelowLimit ())
     {
-      if (super::CanSendOutInterest (inFace, outFace, header, origPacket, pitEntry))
+      if (super::CanSendOutInterest (inFace, outFace, interest, pitEntry))
         {
           faceLimits->BorrowLimit ();
           return true;
@@ -175,7 +173,7 @@
 template<class Parent>
 void
 PerOutFaceLimits<Parent>::WillSatisfyPendingInterest (Ptr<Face> inFace,
-                                                        Ptr<pit::Entry> pitEntry)
+                                                      Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
 
diff --git a/model/fw/smart-flooding.cc b/model/fw/smart-flooding.cc
index 97faaf7..86ec8ee 100644
--- a/model/fw/smart-flooding.cc
+++ b/model/fw/smart-flooding.cc
@@ -66,14 +66,13 @@
 
 bool
 SmartFlooding::DoPropagateInterest (Ptr<Face> inFace,
-                                    Ptr<const Interest> header,
-                                    Ptr<const Packet> origPacket,
+                                    Ptr<const Interest> interest,
                                     Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this);
 
   // Try to work out with just green faces
-  bool greenOk = super::DoPropagateInterest (inFace, header, origPacket, pitEntry);
+  bool greenOk = super::DoPropagateInterest (inFace, interest, pitEntry);
   if (greenOk)
     return true;
 
@@ -85,7 +84,7 @@
       if (metricFace.GetStatus () == fib::FaceMetric::NDN_FIB_RED) // all non-read faces are in the front of the list
         break;
 
-      if (!TrySendOutInterest (inFace, metricFace.GetFace (), header, origPacket, pitEntry))
+      if (!TrySendOutInterest (inFace, metricFace.GetFace (), interest, pitEntry))
         {
           continue;
         }
diff --git a/model/fw/smart-flooding.h b/model/fw/smart-flooding.h
index e1637aa..9263172 100644
--- a/model/fw/smart-flooding.h
+++ b/model/fw/smart-flooding.h
@@ -55,8 +55,7 @@
   // inherited
   virtual bool
   DoPropagateInterest (Ptr<Face> inFace,
-                       Ptr<const Interest> header,
-                       Ptr<const Packet> origPacket,
+                       Ptr<const Interest> interest,
                        Ptr<pit::Entry> pitEntry);
 
 protected:
diff --git a/model/ndn-common.h b/model/ndn-common.h
new file mode 100644
index 0000000..3581a4c
--- /dev/null
+++ b/model/ndn-common.h
@@ -0,0 +1,17 @@
+/** -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/* 
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ * 
+ * BSD license, See the doc/LICENSE file for more information
+ * 
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_COMMON_H
+#define NDN_COMMON_H
+
+#define NDN_NAMESPACE_BEGIN  namespace ns3 { namespace ndn {
+#define NDN_NAMESPACE_END    } /*ndn*/ } /*ns3*/ 
+
+#endif // NDN_COMMON_H
diff --git a/model/ndn-content-object.cc b/model/ndn-content-object.cc
index 052cd4a..d287ca7 100644
--- a/model/ndn-content-object.cc
+++ b/model/ndn-content-object.cc
@@ -33,22 +33,21 @@
 NS_OBJECT_ENSURE_REGISTERED (ContentObject);
 NS_OBJECT_ENSURE_REGISTERED (ContentObjectTail);
 
-TypeId
-ContentObject::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::ndn::ContentObject")
-    .SetGroupName ("Ndn")
-    .SetParent<Header> ()
-    .AddConstructor<ContentObject> ()
-    ;
-  return tid;
-}
-
 ContentObject::ContentObject ()
   : m_signature (0)
 {
 }
 
+ContentObject::ContentObject (const ContentObject &other)
+  : m_name (Create<Name> (other.GetName ()))
+  , m_freshness (other->GetFreshness ())
+  , m_timestamp (other->GetTimestamp ())
+  , m_signature (other->GetSignature ())
+  , m_payload (other->GetPayload ()->Copy ())
+  , m_wire (0)
+{
+}
+
 void
 ContentObject::SetName (Ptr<Name> name)
 {
@@ -111,114 +110,6 @@
   return m_signature;
 }
 
-uint32_t
-ContentObject::GetSerializedSize () const
-{
-  uint32_t size = 1 + 1 + 2 +
-    ((2 + 2) + (m_name->GetSerializedSize ()) + (2 + 2 + 4 + 2 + 2 + (2 + 0)));
-  if (m_signature != 0)
-    size += 4;
-  
-  NS_LOG_INFO ("Serialize size = " << size);
-  return size;
-}
-
-void
-ContentObject::Serialize (Buffer::Iterator start) const
-{
-  start.WriteU8 (0x80); // version
-  start.WriteU8 (0x01); // packet type
-  start.WriteU16 (GetSerializedSize () - 4); // length
-  
-  if (m_signature != 0)
-    {
-      start.WriteU16 (6); // signature length
-      start.WriteU16 (0xFF00); // "fake" simulator signature
-      start.WriteU32 (m_signature);
-    }
-  else
-    {
-      start.WriteU16 (2); // signature length
-      start.WriteU16 (0); // empty signature
-    }
-
-  // name
-  uint32_t offset = m_name->Serialize (start);
-  NS_LOG_DEBUG ("Offset: " << offset);
-  start.Next (offset);
-
-  // content
-  // for now assume that contentdata length is zero
-  start.WriteU16 (2 + 4 + 2 + 2 + (2 + 0));
-  start.WriteU16 (4 + 2 + 2 + (2 + 0));
-  start.WriteU32 (static_cast<uint32_t> (m_timestamp.ToInteger (Time::S)));
-  start.WriteU16 (static_cast<uint16_t> (m_freshness.ToInteger (Time::S)));
-  start.WriteU16 (0); // reserved 
-  start.WriteU16 (0); // Length (ContentInfoOptions)
-
-  // that's it folks
-}
-
-
-uint32_t
-ContentObject::Deserialize (Buffer::Iterator start)
-{
-  Buffer::Iterator i = start;
-
-  if (i.ReadU8 () != 0x80)
-    throw new ContentObjectException ();
-
-  if (i.ReadU8 () != 0x01)
-    throw new ContentObjectException ();
-
-  i.ReadU16 (); // length
-
-  uint32_t signatureLength = i.ReadU16 ();
-  if (signatureLength == 6)
-    {
-      if (i.ReadU16 () != 0xFF00) // signature type
-        throw new ContentObjectException ();
-      m_signature = i.ReadU32 ();
-    }
-  else if (signatureLength == 2)
-    {
-      if (i.ReadU16 () != 0) // signature type
-        throw new ContentObjectException ();
-      m_signature = 0;
-    }
-  else
-    throw new ContentObjectException ();
-
-  m_name = Create<Name> ();
-  uint32_t offset = m_name->Deserialize (i);
-  i.Next (offset);
-
-  if (i.ReadU16 () != (2 + 4 + 2 + 2 + (2 + 0))) // content length
-    throw new ContentObjectException ();
-
-  if (i.ReadU16 () != (4 + 2 + 2 + (2 + 0))) // Length (content Info)
-    throw new ContentObjectException ();
-
-  m_timestamp = Seconds (i.ReadU32 ());
-  m_freshness = Seconds (i.ReadU16 ());
-
-  if (i.ReadU16 () != 0) // Reserved
-    throw new ContentObjectException ();
-  if (i.ReadU16 () != 0) // Length (ContentInfoOptions)
-    throw new ContentObjectException ();
-
-  NS_ASSERT_MSG (i.GetDistanceFrom (start) == GetSerializedSize (),
-                 "Something wrong with ContentObject::Deserialize");
-  
-  return i.GetDistanceFrom (start);
-}
-  
-TypeId
-ContentObject::GetInstanceTypeId (void) const
-{
-  return GetTypeId ();
-}
-  
 void
 ContentObject::Print (std::ostream &os) const
 {
@@ -226,50 +117,5 @@
   // os << "<ContentObject><Name>" << GetName () << "</Name><Content>";
 }
 
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-ContentObjectTail::ContentObjectTail ()
-{
-}
-
-TypeId
-ContentObjectTail::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::ndn::ContentObjectTail")
-    .SetParent<Trailer> ()
-    .AddConstructor<ContentObjectTail> ()
-    ;
-  return tid;
-}
-
-TypeId
-ContentObjectTail::GetInstanceTypeId (void) const
-{
-  return GetTypeId ();
-}
-
-void
-ContentObjectTail::Print (std::ostream &os) const
-{
-  // os << "</Content></ContentObject>";
-}
-
-uint32_t
-ContentObjectTail::GetSerializedSize (void) const
-{
-  return 0;
-}
-
-void
-ContentObjectTail::Serialize (Buffer::Iterator start) const
-{
-}
-
-uint32_t
-ContentObjectTail::Deserialize (Buffer::Iterator start)
-{
-  return 0;
-}
-
 } // namespace ndn
 } // namespace ns3
diff --git a/model/ndn-content-object.h b/model/ndn-content-object.h
index a5d534c..387fee1 100644
--- a/model/ndn-content-object.h
+++ b/model/ndn-content-object.h
@@ -77,13 +77,18 @@
 {
 public:
   /**
-   * Constructor
+   * @brief Constructor
    *
    * Creates a null header
    **/
   ContentObject ();
 
   /**
+   * @brief Copy constructor
+   */
+  ContentObject (const ContentObject &other);
+
+  /**
    * \brief Set content object name
    *
    * Sets name of the content object
@@ -155,19 +160,49 @@
   GetSignature () const;
 
   //////////////////////////////////////////////////////////////////
+  /**
+   * @brief Get payload of data packet
+   *
+   * This payload can also carry packet tags
+   */
+  void
+  SetPayload (Ptr<Packet> payload);
 
-  static TypeId GetTypeId (void); ///< @brief Get TypeId
-  virtual TypeId GetInstanceTypeId (void) const; ///< @brief Get TypeId of the instance
-  virtual void Print (std::ostream &os) const; ///< @brief Print out information about the Header into the stream
-  virtual uint32_t GetSerializedSize (void) const; ///< @brief Get size necessary to serialize the Header
-  virtual void Serialize (Buffer::Iterator start) const; ///< @brief Serialize the Header
-  virtual uint32_t Deserialize (Buffer::Iterator start); ///< @brief Deserialize the Header
+  /**
+   * @brief Set payload of data packet
+   *
+   * This payload can also carry packet tags
+   */
+  Ptr<const Payload>
+  GetPayload () const;
+  
+  /**
+   * @brief Get wire formatted packet
+   *
+   * If wire formatted packet has not been set before, 0 will be returned
+   */
+  inline Ptr<const Packet>
+  GetWire () const;
 
+  /**
+   * @brief Set (cache) wire formatted packet
+   */
+  inline void
+  SetWire (Ptr<const Packet> packet) const;
+
+private:
+  // NO_ASSIGN
+  ContentObject &
+  operator = (const ContentObject &other) { return *this; }
+  
 private:
   Ptr<Name> m_name;
   Time m_freshness;
   Time m_timestamp;
   uint32_t m_signature; // 0, means no signature, any other value application dependent (not a real signature)
+  Ptr<Packet> m_payload;
+
+  mutable Ptr<const Packet> m_wire;
 };
 
 /**
diff --git a/model/ndn-face.cc b/model/ndn-face.cc
index b5f7c34..5b72044 100644
--- a/model/ndn-face.cc
+++ b/model/ndn-face.cc
@@ -33,6 +33,7 @@
 #include "ns3/pointer.h"
 
 #include "ns3/ndnSIM/utils/ndn-fw-hop-count-tag.h"
+#include "ns3/ndnSIM/model/wire/ndnsim.h"
 
 #include <boost/ref.hpp>
 
@@ -116,7 +117,7 @@
 
 
 bool
-Face::SendInterest (Ptr<const Interest> interest, Ptr<const Packet> packet)
+Face::SendInterest (Ptr<const Interest> interest)
 {
   NS_LOG_FUNCTION (this << interest << packet);
 
@@ -125,14 +126,12 @@
       return false;
     }
 
-  Ptr<Packet> copy = packet->Copy ();
-  copy->AddHeader (*interest);
-
-  return Send (copy);
+  Ptr<Packet> packet = wire::ndnSIM::Interest::ToWire (interest);
+  return Send (packet);
 }
 
 bool
-Face::SendData (Ptr<const ContentObject> data, Ptr<const Packet> packet)
+Face::SendData (Ptr<const ContentObject> data)
 {
   NS_LOG_FUNCTION (this << data << packet);
 
@@ -141,10 +140,8 @@
       return false;
     }
 
-  Ptr<Packet> copy = packet->Copy ();
-  copy->AddHeader (*data);
-  
-  return Send (copy);
+  Ptr<Packet> packet = wire::ndnSIM::Data::ToWire (data);
+  return Send (packet);
 }
 
 bool
@@ -180,17 +177,13 @@
         {
         case HeaderHelper::INTEREST_NDNSIM:
           {
-            Ptr<Interest> interest = Create<Interest> ();
-            packet->RemoveHeader (*header);
-
-            return ReceiveInterest (interest, packet/*payload*/);
+            Ptr<Interest> interest = wire::ndnSIM::Interest::FromWire (packet);
+            return ReceiveInterest (interest);
           }
         case HeaderHelper::CONTENT_OBJECT_NDNSIM:
           {
-            Ptr<ContentObject> data = Create<ContentObject> ();
-            packet->RemoveHeader (*header);
-
-            return ReceiveData (data, packet);
+            Ptr<ContentObject> data = wire::ndnSIM::Data::FromWire (packet);
+            return ReceiveData (data);
           }
         case HeaderHelper::INTEREST_CCNB:
         case HeaderHelper::CONTENT_OBJECT_CCNB:
@@ -209,7 +202,7 @@
 }
 
 bool
-Face::ReceiveInterest (Ptr<Interest> interest, Ptr<Packet> payload)
+Face::ReceiveInterest (Ptr<Interest> interest)
 {
   if (!IsUp ())
     {
@@ -217,12 +210,12 @@
       return false;
     }
 
-  m_upstreamInterestHandler (this, interest, payload);
+  m_upstreamInterestHandler (this, interest);
   return true;
 }
 
 bool
-Face::ReceiveData (Ptr<ContentObject> data, Ptr<Packet> payload)
+Face::ReceiveData (Ptr<ContentObject> data)
 {
   if (!IsUp ())
     {
@@ -230,7 +223,7 @@
       return false;
     }
 
-  m_upstreamDataHandler (this, data, payload);
+  m_upstreamDataHandler (this, data);
   return true;
 }
 
diff --git a/model/ndn-face.h b/model/ndn-face.h
index edcd5d2..5f6c884 100644
--- a/model/ndn-face.h
+++ b/model/ndn-face.h
@@ -68,8 +68,8 @@
    * \param face Face from which packet has been received
    * \param packet Original packet
    */
-  typedef Callback<void, Ptr<Face>, Ptr<Interest>, Ptr<Packet> > InterestHandler;
-  typedef Callback<void, Ptr<Face>, Ptr<ContentObject>, Ptr<Packet> > DataHandler;
+  typedef Callback<void, Ptr<Face>, Ptr<Interest> > InterestHandler;
+  typedef Callback<void, Ptr<Face>, Ptr<ContentObject> > DataHandler;
 
   /**
    * \brief Default constructor
@@ -109,7 +109,7 @@
    * @returns true if interest is considered to be send out (enqueued)
    */
   virtual bool
-  SendInterest (Ptr<const Interest> interest, Ptr<const Packet> packet);
+  SendInterest (Ptr<const Interest> interest);
 
   /**
    * @brief Send out Dat packet through the face
@@ -119,7 +119,7 @@
    * @returns true if Data packet is considered to be send out (enqueued)
    */
   virtual bool
-  SendData (Ptr<const ContentObject> data, Ptr<const Packet> packet);
+  SendData (Ptr<const ContentObject> data);
 
   /**
    * \brief Receive interest from application or another node and forward it up to the NDN stack
@@ -127,7 +127,7 @@
    * By default it is called from inside Receive method, but can be used directly, if appropriate
    */
   virtual bool
-  ReceiveInterest (Ptr<Interest> interest, Ptr<Packet> payload);
+  ReceiveInterest (Ptr<Interest> interest);
 
   /**
    * \brief Receive Data packet from application or another node and forward it up to the NDN stack
@@ -135,7 +135,7 @@
    * By default it is called from inside Receive method, but can be used directly, if appropriate
    */
   virtual bool
-  ReceiveData (Ptr<ContentObject> data, Ptr<Packet> payload);
+  ReceiveData (Ptr<ContentObject> data);
   ////////////////////////////////////////////////////////////////////
 
   /**
diff --git a/model/ndn-interest.cc b/model/ndn-interest.cc
index f0a4f29..195c4f9 100644
--- a/model/ndn-interest.cc
+++ b/model/ndn-interest.cc
@@ -31,24 +31,14 @@
 
 NS_OBJECT_ENSURE_REGISTERED (Interest);
 
-TypeId
-Interest::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::ndn::Interest")
-    .SetGroupName ("Ndn")
-    .SetParent<Header> ()
-    .AddConstructor<Interest> ()
-    ;
-  return tid;
-}
-  
-
 Interest::Interest ()
   : m_name ()
   , m_scope (0xFF)
   , m_interestLifetime (Seconds (0))
   , m_nonce (0)
   , m_nackType (NORMAL_INTEREST)
+  , m_payload (0)
+  , m_wire (0)
 {
 }
 
@@ -58,28 +48,23 @@
   , m_interestLifetime    (interest.m_interestLifetime)
   , m_nonce               (interest.m_nonce)
   , m_nackType            (interest.m_nackType)
+  , m_payload (interest.GetPayload ()->Copy ())
+  , m_wire (0)
 {
 }
 
-Ptr<Interest>
-Interest::GetInterest (Ptr<Packet> packet)
-{
-  Ptr<Interest> interest = Create<Interest> ();
-  packet->RemoveHeader (*interest);
-
-  return interest;
-}
-
 void
 Interest::SetName (Ptr<Name> name)
 {
   m_name = name;
+  m_wire = 0;
 }
 
 void
 Interest::SetName (const Name &name)
 {
   m_name = Create<Name> (name);
+  m_wire = 0;
 }
 
 const Name&
@@ -99,6 +84,7 @@
 Interest::SetScope (int8_t scope)
 {
   m_scope = scope;
+  m_wire = 0;
 }
 
 int8_t
@@ -111,6 +97,7 @@
 Interest::SetInterestLifetime (Time lifetime)
 {
   m_interestLifetime = lifetime;
+  m_wire = 0;
 }
 
 Time
@@ -123,6 +110,7 @@
 Interest::SetNonce (uint32_t nonce)
 {
   m_nonce = nonce;
+  m_wire = 0;
 }
 
 uint32_t
@@ -135,6 +123,7 @@
 Interest::SetNack (uint8_t nackType)
 {
   m_nackType = nackType;
+  m_wire = 0;
 }
 
 uint8_t
@@ -143,82 +132,18 @@
   return m_nackType;
 }
 
-uint32_t
-Interest::GetSerializedSize (void) const
-{
-  size_t size =
-    1/*version*/ + 1 /*type*/ + 2/*length*/ +
-    (4/*nonce*/ + 1/*scope*/ + 1/*nack type*/ + 2/*timestamp*/ +
-     (m_name->GetSerializedSize ()) +
-     (2 + 0)/* selectors */ +
-     (2 + 0)/* options */);
-  NS_LOG_INFO ("Serialize size = " << size);
-
-  return size;
-}
-    
 void
-Interest::Serialize (Buffer::Iterator start) const
+Interest::SetPayload (Ptr<Packet> payload)
 {
-  start.WriteU8 (0x80); // version
-  start.WriteU8 (0x00); // packet type
-
-  start.WriteU16 (GetSerializedSize () - 4);
-
-  start.WriteU32 (m_nonce);
-  start.WriteU8 (m_scope);
-  start.WriteU8 (m_nackType);
-
-  NS_ASSERT_MSG (0 <= m_interestLifetime.ToInteger (Time::S) && m_interestLifetime.ToInteger (Time::S) < 65535,
-                 "Incorrect InterestLifetime (should not be smaller than 0 and larger than 65535");
-  
-  // rounding timestamp value to seconds
-  start.WriteU16 (static_cast<uint16_t> (m_interestLifetime.ToInteger (Time::S)));
-
-  uint32_t offset = m_name->Serialize (start);
-  start.Next (offset);
-  
-  start.WriteU16 (0); // no selectors
-  start.WriteU16 (0); // no options
+  m_payload = payload;
 }
 
-uint32_t
-Interest::Deserialize (Buffer::Iterator start)
+Ptr<const Payload>
+Interest::GetPayload () const
 {
-  Buffer::Iterator i = start;
-  
-  if (i.ReadU8 () != 0x80)
-    throw new InterestException ();
-
-  if (i.ReadU8 () != 0x00)
-    throw new InterestException ();
-
-  i.ReadU16 (); // length, don't need it right now
-  
-  m_nonce = i.ReadU32 ();
-  m_scope = i.ReadU8 ();
-  m_nackType = i.ReadU8 ();
-  
-  m_interestLifetime = Seconds (i.ReadU16 ());
-
-  m_name = Create<Name> ();
-  uint32_t offset = m_name->Deserialize (i);
-  i.Next (offset);
-  
-  i.ReadU16 ();
-  i.ReadU16 ();
-
-  NS_ASSERT (GetSerializedSize () == (i.GetDistanceFrom (start)));
-
-  return i.GetDistanceFrom (start);
+  return m_payload;
 }
 
-TypeId
-Interest::GetInstanceTypeId (void) const
-{
-  return GetTypeId ();
-}
-  
 void
 Interest::Print (std::ostream &os) const
 {
diff --git a/model/ndn-interest.h b/model/ndn-interest.h
index 88d1159..c1fb277 100644
--- a/model/ndn-interest.h
+++ b/model/ndn-interest.h
@@ -40,50 +40,10 @@
 namespace ndn {
 
 /**
-  * @brief NDN Interest and routines to serialize/deserialize
-  *
-  * Optimized and simplified formatting of Interest packets 
-  *
-  *	Interest ::= Nonce 
-  *	     	     Scope 
-  *		     InterestLifetime 
-  *	     	     Name 
-  *	     	     Selectors 
-  *	     	     Options
-  *
-  * Minumum size of the Interest packet: 1 + 4 + 2 + 1 + (2 + 0) + (2 + 0) + (2 + 0) = 14
-  *
-  * Maximum size of the Interest packet: 1 + 4 + 2 + 1 + (2 + 65535) + (2 + 65535) + (2 + 65535) = 196619
-  *
-  * ::
-  *
-  *        0                   1                   2                   3
-  *        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-  *        |                          Nonce                                |
-  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-  *        |     Scope     |   Reserved    |      InterestLifetime         |
-  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-  *        |            Length             |                               |
-  *	   |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
-  *        ~                                                               ~
-  *        ~                            Name                               ~
-  *        |							           |	
-  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-  *        |            Length             |                               |
-  *        |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
-  *        ~                                                               ~
-  *        ~                          Selectors                            ~
-  *        |							            |	
-  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-  *        |            Length             |                               |
-  *	   |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
-  *        ~                                                               ~
-  *        ~                          Options                              ~
-  *        |							           |	
-  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-  * **/
-class Interest : public SimpleRefCount<Interest, Header>
+ * @brief NDN Interest (wire formats are defined in wire/*)
+ *
+ **/
+class Interest : public SimpleRefCount<Interest>
 {
 public:
   /**
@@ -221,50 +181,67 @@
   uint8_t
   GetNack () const;
 
-  //////////////////////////////////////////////////////////////////
-
-  static TypeId GetTypeId (void); ///< @brief Get TypeId of the class
-  virtual TypeId GetInstanceTypeId (void) const; ///< @brief Get TypeId of the instance
-  
   /**
-   * \brief Print Interest packet 
+   * @brief Get virtual "payload" of interest packet
+   *
+   * This payload can carry packet tags
    */
-  virtual void Print (std::ostream &os) const;
-  
-  /**
-   * \brief Get the size of Interest packet
-   * Returns the Interest packet size after serialization
-   */
-  virtual uint32_t GetSerializedSize (void) const;
-  
-  /**
-   * \brief Serialize Interest packet
-   * Serializes Interest packet into Buffer::Iterator
-   * @param[in] start buffer to contain serialized Interest packet
-   */
-  virtual void Serialize (Buffer::Iterator start) const;
-  
-  /**
-   * \brief Deserialize Interest packet
-   * Deserializes Buffer::Iterator into Interest packet
-   * @param[in] start buffer that contains serialized Interest packet
-   */ 
-  virtual uint32_t Deserialize (Buffer::Iterator start);
+  void
+  SetPayload (Ptr<Packet> payload);
 
   /**
-   * @brief Cheat for python bindings
+   * @brief Set virtual "payload" to interest packet
+   *
+   * This payload can carry packet tags
    */
-  static Ptr<Interest>
-  GetInterest (Ptr<Packet> packet);
+  Ptr<const Payload>
+  GetPayload () const;
+  
+  /**
+   * @brief Get wire formatted packet
+   *
+   * If wire formatted packet has not been set before, 0 will be returned
+   */
+  inline Ptr<const Packet>
+  GetWire () const;
+
+  /**
+   * @brief Set (cache) wire formatted packet
+   */
+  inline void
+  SetWire (Ptr<const Packet> packet) const;
+
+private:
+  // NO_ASSIGN
+  Interest &
+  operator = (const Interest &other) { return *this; }
   
 private:
-  Ptr<Name> m_name;    ///< Interest name
-  uint8_t m_scope;                ///< 0xFF not set, 0 local scope, 1 this host, 2 immediate neighborhood
-  Time  m_interestLifetime;      ///< InterestLifetime
-  uint32_t m_nonce;              ///< Nonce. not used if zero
-  uint8_t  m_nackType;           ///< Negative Acknowledgement type
+  Ptr<Name> m_name;         ///< @brief Interest name
+  uint8_t m_scope;          ///< @brief 0xFF not set, 0 local scope, 1 this host, 2 immediate neighborhood
+  Time  m_interestLifetime; ///< @brief InterestLifetime
+  uint32_t m_nonce;         ///< @brief Nonce. not used if zero
+  uint8_t  m_nackType;      ///< @brief Negative Acknowledgement type
+  Ptr<Packet> m_payload;    ///< @brief virtual payload
+
+  mutable Ptr<const Packet> m_wire;
 };
 
+inline Ptr<const Packet>
+Interest::GetWire () const
+{
+  return m_wire;
+}
+
+/**
+ * @brief Set (cache) wire formatted packet
+ */
+inline void
+Interest::SetWire (Ptr<const Packet> packet) const
+{
+  m_wire = packet;
+}
+
 /**
  * @ingroup ndn-exceptions
  * @brief Class for Interest parsing exception 
diff --git a/model/ndn-l3-protocol.cc b/model/ndn-l3-protocol.cc
index 272e445..59993ac 100644
--- a/model/ndn-l3-protocol.cc
+++ b/model/ndn-l3-protocol.cc
@@ -68,7 +68,6 @@
   return s_dataCounter;
 }
 
-
 TypeId
 L3Protocol::GetTypeId (void)
 {
@@ -84,7 +83,7 @@
   return tid;
 }
 
-L3Protocol::L3Protocol()
+L3Protocol::L3Protocol ()
 : m_faceCounter (0)
 {
   NS_LOG_FUNCTION (this);
diff --git a/model/ndn-l3-protocol.h b/model/ndn-l3-protocol.h
index 292de13..406e194 100644
--- a/model/ndn-l3-protocol.h
+++ b/model/ndn-l3-protocol.h
@@ -39,16 +39,11 @@
 
 class Face;
 class ForwardingStrategy;
-class Interest;
-class ContentObject;
-
-typedef Interest InterestHeader;
-typedef ContentObject ContentObjectHeader;
 
 /**
  * \defgroup ndn ndnSIM: NDN simulation module
  *
- * This is a simplified modular implementation of NDN protocol
+ * This is a modular implementation of NDN protocol for NS-3
  */
 /**
  * \ingroup ndn
diff --git a/model/ndn-name.cc b/model/ndn-name.cc
index 1a3da80..083d3d8 100644
--- a/model/ndn-name.cc
+++ b/model/ndn-name.cc
@@ -113,60 +113,6 @@
   return retval;
 }
 
-size_t
-Name::GetSerializedSize () const
-{
-  size_t nameSerializedSize = 2;
-
-  for (std::list<std::string>::const_iterator i = this->begin ();
-       i != this->end ();
-       i++)
-    {
-      nameSerializedSize += 2 + i->size ();
-    }
-  NS_ASSERT_MSG (nameSerializedSize < 30000, "Name is too long (> 30kbytes)");
-
-  return nameSerializedSize;
-}
-
-uint32_t
-Name::Serialize (Buffer::Iterator start) const
-{
-  Buffer::Iterator i = start;
-
-  i.WriteU16 (static_cast<uint16_t> (this->GetSerializedSize ()-2));
-
-  for (std::list<std::string>::const_iterator item = this->begin ();
-       item != this->end ();
-       item++)
-    {
-      i.WriteU16 (static_cast<uint16_t> (item->size ()));
-      i.Write (reinterpret_cast<const uint8_t*> (item->c_str ()), item->size ());
-    }
-
-  return i.GetDistanceFrom (start);
-}
-
-uint32_t
-Name::Deserialize (Buffer::Iterator start)
-{
-  Buffer::Iterator i = start;
-
-  uint16_t nameLength = i.ReadU16 ();
-  while (nameLength > 0)
-    {
-      uint16_t length = i.ReadU16 ();
-      nameLength = nameLength - 2 - length;
-
-      uint8_t tmp[length];
-      i.Read (tmp, length);
-
-      this->Add (string (reinterpret_cast<const char*> (tmp), length));
-    }
-
-  return i.GetDistanceFrom (start);
-}
-
 void
 Name::Print (std::ostream &os) const
 {
diff --git a/model/ndn-name.h b/model/ndn-name.h
index db39ccf..0694f0b 100644
--- a/model/ndn-name.h
+++ b/model/ndn-name.h
@@ -136,26 +136,6 @@
   void Print (std::ostream &os) const;
 
   /**
-   * @brief Get serialized size for ndnSIM packet encoding
-   */
-  size_t
-  GetSerializedSize () const;
-
-  /**
-   * @brief Serialize Name in ndnSIM packet encoding
-   * @param[in] start buffer to contain serialized name
-   */
-  uint32_t
-  Serialize (Buffer::Iterator start) const;
-
-  /**
-   * \brief Deserialize Name in ndnSIM packet encoding
-   * @param[in] start buffer that contains serialized name
-   */
-  uint32_t
-  Deserialize (Buffer::Iterator start);
-
-  /**
    * \brief Returns the size of Name
    */
   inline size_t
diff --git a/model/wire/ndnsim.cc b/model/wire/ndnsim.cc
new file mode 100644
index 0000000..747d264
--- /dev/null
+++ b/model/wire/ndnsim.cc
@@ -0,0 +1,406 @@
+/** -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/* 
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ * 
+ * BSD license, See the doc/LICENSE file for more information
+ * 
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ndnsim.h"
+
+NDN_NAMESPACE_BEGIN
+
+namespace wire {
+namespace ndnSIM {
+
+
+class Name
+{
+public:
+  Name ()
+    : m_name (Create<ndn::Name> ())
+  {
+  }
+  
+  Name (Ptr<ndn::Name> name)
+    : m_name (name)
+  {
+  }
+
+  Ptr<Name>
+  GetName ()
+  {
+    return m_name;
+  }
+  
+  size_t
+  GetSerializedSize () const
+  {
+    size_t nameSerializedSize = 2;
+
+    for (std::list<std::string>::const_iterator i = m_name->begin ();
+         i != m_name->end ();
+         i++)
+      {
+        nameSerializedSize += 2 + i->size ();
+      }
+    NS_ASSERT_MSG (nameSerializedSize < 30000, "Name is too long (> 30kbytes)");
+
+    return nameSerializedSize;
+  }
+
+  uint32_t
+  Serialize (Buffer::Iterator start) const
+  {
+    Buffer::Iterator i = start;
+
+    i.WriteU16 (static_cast<uint16_t> (m_name->GetSerializedSize ()-2));
+
+    for (std::list<std::string>::const_iterator item = m_name->begin ();
+         item != m_name->end ();
+         item++)
+      {
+        i.WriteU16 (static_cast<uint16_t> (item->size ()));
+        i.Write (reinterpret_cast<const uint8_t*> (item->c_str ()), item->size ());
+      }
+
+    return i.GetDistanceFrom (start);
+  }
+
+  uint32_t
+  Deserialize (Buffer::Iterator start)
+  {
+    Buffer::Iterator i = start;
+
+    uint16_t nameLength = i.ReadU16 ();
+    while (nameLength > 0)
+      {
+        uint16_t length = i.ReadU16 ();
+        nameLength = nameLength - 2 - length;
+
+        uint8_t tmp[length];
+        i.Read (tmp, length);
+
+        m_name->Add (string (reinterpret_cast<const char*> (tmp), length));
+      }
+
+    return i.GetDistanceFrom (start);
+  }
+
+private:
+  Ptr<ndn::Name> m_name;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+Interest::Interest ()
+  : m_interest (Create<ndn::Interest> ())
+{
+}
+
+Interest::Interest (Ptr<ndn::Interest> interest)
+  : m_interest (interest)
+{
+}
+
+Ptr<ndn::Interest>
+Interest::GetInterest ()
+{
+  return m_interest;
+}
+
+
+TypeId
+Interest::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ndn::Interest::ndnSIM")
+    .SetGroupName ("Ndn")
+    .AddParent<Header> ()
+    .AddConstructor<Interest> ()
+    ;
+  return tid;
+}
+
+TypeId
+Interest::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+Ptr<Packet>
+Interest::ToWire (Ptr<const ndn::Interest> interest)
+{
+  Ptr<const Packet> p = interest->GetWire ();
+  if (!p)
+    {
+      p = Create<Packet> (*interest->GetPayload ());
+      Interest wireEncoding (interest);
+      p->AddHeader (wireEncoding);
+      interest->SetWire (p);
+    }
+  
+  return p->Copy ();
+}
+
+Ptr<ndn::Interest>
+Interest::FromWire (Ptr<Packet> packet)
+{
+  Ptr<ndn::Interest> interest = Create<ndn::Interest> ();
+  // interest->SetWire (packet->Copy ()); /* not sure if this is needed */
+
+  Interest wireEncoding (interest);
+  packet->RemoveHeader (wireEncoding);
+
+  interest->SetPayload (packet);
+
+  return interest;
+}
+
+uint32_t
+Interest::GetSerializedSize (void) const
+{
+  size_t size =
+    1/*version*/ + 1 /*type*/ + 2/*length*/ +
+    (4/*nonce*/ + 1/*scope*/ + 1/*nack type*/ + 2/*timestamp*/ +
+     (Name (ConstCast<ns3::Name> (m_interest->GetNamePtr ())).GetSerializedSize ()) +
+     (2 + 0)/* selectors */ +
+     (2 + 0)/* options */);
+  
+  NS_LOG_INFO ("Serialize size = " << size);
+  return size;
+}
+    
+void
+Interest::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (0x80); // version
+  start.WriteU8 (0x00); // packet type
+
+  start.WriteU16 (GetSerializedSize () - 4);
+
+  start.WriteU32 (m_nonce);
+  start.WriteU8 (m_scope);
+  start.WriteU8 (m_nackType);
+
+  NS_ASSERT_MSG (0 <= m_interest->GetInterestLifetime.ToInteger (Time::S) && m_interest->GetInterestLifetime.ToInteger (Time::S) < 65535,
+                 "Incorrect InterestLifetime (should not be smaller than 0 and larger than 65535");
+  
+  // rounding timestamp value to seconds
+  start.WriteU16 (static_cast<uint16_t> (m_interest->GetInterestLifetime.ToInteger (Time::S)));
+
+  uint32_t offset = Name (ConstCast<ns3::Name> (m_interest->GetNamePtr ())).Serialize (start);
+  start.Next (offset);
+  
+  start.WriteU16 (0); // no selectors
+  start.WriteU16 (0); // no options
+}
+
+uint32_t
+Interest::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  
+  if (i.ReadU8 () != 0x80)
+    throw new InterestException ();
+
+  if (i.ReadU8 () != 0x00)
+    throw new InterestException ();
+
+  i.ReadU16 (); // length, don't need it right now
+  
+  m_interest->SetNonce (i.ReadU32 ());
+  m_interest->SetScope (i.ReadU8 ());
+  m_interest->SetNackType (i.ReadU8 ());
+
+  m_interest->SetInterestLifetime (Seconds (i.ReadU16 ()));
+
+  Name name;
+  uint32_t offset = name.Deserialize (i);
+  m_interest->SetName (name->GetName ());
+  i.Next (offset);
+  
+  i.ReadU16 ();
+  i.ReadU16 ();
+
+  NS_ASSERT (GetSerializedSize () == (i.GetDistanceFrom (start)));
+
+  return i.GetDistanceFrom (start);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+TypeId
+Data::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ndn::Data::ndnSIM")
+    .SetGroupName ("Ndn")
+    .SetParent<Header> ()
+    .AddConstructor<Data> ()
+    ;
+  return tid;
+}
+
+TypeId
+Data::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+  
+
+Data::Data ()
+  : m_data (Create<ndn::ContentObject> ())
+{
+}
+
+Data::Data (Ptr<ndn::ContentObject> data)
+  : m_data (data)
+{
+}
+
+Ptr<ndn::ContentObject>
+GetData ()
+{
+  return m_data;
+}
+
+Ptr<Packet>
+Data::ToWire (Ptr<const ndn::ContentObject> data)
+{
+  Ptr<const Packet> p = data->GetWire ();
+  if (!p)
+    {
+      p = Create<Packet> (*data->GetPayload ());
+      Data wireEncoding (data);
+      p->AddHeader (wireEncoding);
+      data->SetWire (p);
+    }
+  
+  return p->Copy ();
+}
+
+Ptr<ndn::ContentObject>
+Data::FromWire (Ptr<Packet> packet)
+{
+  Ptr<ndn::ContentObject> data = Create<ndn::ContentObject> ();
+  // data->SetWire (packet->Copy ()); /* not sure if this is needed */
+
+  Data wireEncoding (data);
+  packet->RemoveHeader (wireEncoding);
+
+  data->SetPayload (packet);
+
+  return data;
+}
+
+uint32_t
+Data::GetSerializedSize () const
+{
+  uint32_t size = 1 + 1 + 2 +
+    ((2 + 2) + (Name (ConstCast<ns3::Name> (m_data->GetNamePtr ())).GetSerializedSize ()) + (2 + 2 + 4 + 2 + 2 + (2 + 0)));
+  if (m_data->GetSignature () != 0)
+    size += 4;
+  
+  NS_LOG_INFO ("Serialize size = " << size);
+  return size;
+}
+
+void
+Data::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (0x80); // version
+  start.WriteU8 (0x01); // packet type
+  start.WriteU16 (GetSerializedSize () - 4); // length
+  
+  if (m_data->GetSignature () != 0)
+    {
+      start.WriteU16 (6); // signature length
+      start.WriteU16 (0xFF00); // "fake" simulator signature
+      start.WriteU32 (m_data->GetSignature ());
+    }
+  else
+    {
+      start.WriteU16 (2); // signature length
+      start.WriteU16 (0); // empty signature
+    }
+
+  // name
+  uint32_t offset = Name (ConstCast<ns3::Name> (m_data->GetNamePtr ())).Serialize (start);
+  start.Next (offset);
+
+  // content
+  // for now assume that contentdata length is zero
+  start.WriteU16 (2 + 4 + 2 + 2 + (2 + 0));
+  start.WriteU16 (4 + 2 + 2 + (2 + 0));
+  start.WriteU32 (static_cast<uint32_t> (m_data->GetTimestamp.ToInteger (Time::S)));
+  start.WriteU16 (static_cast<uint16_t> (m_data->GetFreshness.ToInteger (Time::S)));
+  start.WriteU16 (0); // reserved 
+  start.WriteU16 (0); // Length (ContentInfoOptions)
+
+  // that's it folks
+}
+
+uint32_t
+Data::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  if (i.ReadU8 () != 0x80)
+    throw new ContentObjectException ();
+
+  if (i.ReadU8 () != 0x01)
+    throw new ContentObjectException ();
+
+  i.ReadU16 (); // length
+
+  uint32_t signatureLength = i.ReadU16 ();
+  if (signatureLength == 6)
+    {
+      if (i.ReadU16 () != 0xFF00) // signature type
+        throw new ContentObjectException ();
+      m_data.SetSignature (i.ReadU32 ());
+    }
+  else if (signatureLength == 2)
+    {
+      if (i.ReadU16 () != 0) // signature type
+        throw new ContentObjectException ();
+      m_data.SetSignature (0);
+    }
+  else
+    throw new ContentObjectException ();
+
+  Name name;
+  uint32_t offset = name.Deserialize (i);
+  m_data->SetName (name->GetName ());
+  i.Next (offset);
+
+  if (i.ReadU16 () != (2 + 4 + 2 + 2 + (2 + 0))) // content length
+    throw new ContentObjectException ();
+
+  if (i.ReadU16 () != (4 + 2 + 2 + (2 + 0))) // Length (content Info)
+    throw new ContentObjectException ();
+
+  m_data->SetTimestamp (Seconds (i.ReadU32 ()));
+  m_data->SetFreshness (Seconds (i.ReadU16 ()));
+
+  if (i.ReadU16 () != 0) // Reserved
+    throw new ContentObjectException ();
+  if (i.ReadU16 () != 0) // Length (ContentInfoOptions)
+    throw new ContentObjectException ();
+
+  NS_ASSERT_MSG (i.GetDistanceFrom (start) == GetSerializedSize (),
+                 "Something wrong with ContentObject::Deserialize");
+  
+  return i.GetDistanceFrom (start);
+}
+
+}
+}
+
+NDN_NAMESPACE_END
diff --git a/model/wire/ndnsim.h b/model/wire/ndnsim.h
new file mode 100644
index 0000000..bc711dc
--- /dev/null
+++ b/model/wire/ndnsim.h
@@ -0,0 +1,126 @@
+/** -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/* 
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ * 
+ * BSD license, See the doc/LICENSE file for more information
+ * 
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_WIRE_NDNSIM_H
+#define NDN_WIRE_NDNSIM_H
+
+#include "ns3/ndn-common.h"
+#include "ns3/ndn-interest.h"
+#include "ns3/ndn-content-object.h"
+
+NDN_NAMESPACE_BEGIN
+
+namespace wire {
+namespace ndnSIM {
+
+/**
+ * @brief Routines to serialize/deserialize Interest packet in ndnSIM format
+ *
+ * Optimized and simplified formatting of Interest packets 
+ *
+ *	Interest ::= Nonce 
+ *	     	     Scope 
+ *		     InterestLifetime 
+ *	     	     Name 
+ *	     	     Selectors 
+ *	     	     Options
+ *
+ * Minumum size of the Interest packet: 1 + 4 + 2 + 1 + (2 + 0) + (2 + 0) + (2 + 0) = 14
+ *
+ * Maximum size of the Interest packet: 1 + 4 + 2 + 1 + (2 + 65535) + (2 + 65535) + (2 + 65535) = 196619
+ *
+ * ::
+ *
+ *        0                   1                   2                   3
+ *        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *        |                          Nonce                                |
+ *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *        |     Scope     |   Reserved    |      InterestLifetime         |
+ *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *        |            Length             |                               |
+ *	   |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
+ *        ~                                                               ~
+ *        ~                            Name                               ~
+ *        |							           |	
+ *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *        |            Length             |                               |
+ *        |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
+ *        ~                                                               ~
+ *        ~                          Selectors                            ~
+ *        |							            |	
+ *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *        |            Length             |                               |
+ *	   |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
+ *        ~                                                               ~
+ *        ~                          Options                              ~
+ *        |							           |	
+ *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+class Interest : public Header
+{
+public:
+  Interest ();
+  Interest (Ptr<ndn::Interest> interest);
+
+  Ptr<ndn::Interest>
+  GetInterest ();
+
+  static Ptr<Packet>
+  ToWire (Ptr<const ndn::Interest> interest);
+
+  static Ptr<ndn::Interest>
+  FromWire (Ptr<Packet> packet);
+  
+  // from Header
+  static TypeId GetTypeId (void); 
+  virtual TypeId GetInstanceTypeId (void) const; 
+  virtual void Print (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+private:
+  Ptr<ndn::Interest> m_interest;
+};
+
+class Data : Header
+{
+public:
+  Data ();
+  Data (Ptr<ndn::ContentObject> data);
+
+  Ptr<ndn::ContentObject>
+  GetData ();
+
+  static Ptr<Packet>
+  ToWire (Ptr<const ndn::ContentObject> data);
+
+  static Ptr<ndn::ContentObject>
+  FromWire (Ptr<Packet> packet);
+  
+  // from Header
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual void Print (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+private:
+  Ptr<ndn::ContentObject> m_data;  
+};
+
+} // ndnSIM
+} // wire
+
+NDN_NAMESPACE_END
+
+#endif // NDN_WIRE_NDNSIM_H