Bug 671 add packet-info-tag.cc for IP_PKTINFO/IPV6_PKTINFO
authorHajime Tazaki <tazaki@sfc.wide.ad.jp>
Tue, 13 Jul 2010 13:00:55 +0900
changeset 6442 f380cf1aa4d8
parent 6441 f555caf874dc
child 6443 90c0ca4eadea
Bug 671 add packet-info-tag.cc for IP_PKTINFO/IPV6_PKTINFO
src/internet-stack/icmpv4-l4-protocol.cc
src/internet-stack/icmpv4-l4-protocol.h
src/internet-stack/ipv4-end-point.cc
src/internet-stack/ipv4-end-point.h
src/internet-stack/ipv4-l3-protocol.cc
src/internet-stack/ipv4-l4-protocol.h
src/internet-stack/ipv4-raw-socket-impl.cc
src/internet-stack/ipv4-raw-socket-impl.h
src/internet-stack/ipv4-raw-test.cc
src/internet-stack/ipv6-raw-socket-impl.cc
src/internet-stack/nsc-tcp-l4-protocol.cc
src/internet-stack/nsc-tcp-l4-protocol.h
src/internet-stack/nsc-tcp-socket-impl.cc
src/internet-stack/nsc-tcp-socket-impl.h
src/internet-stack/tcp-l4-protocol.cc
src/internet-stack/tcp-l4-protocol.h
src/internet-stack/tcp-socket-impl.cc
src/internet-stack/tcp-socket-impl.h
src/internet-stack/udp-l4-protocol.cc
src/internet-stack/udp-l4-protocol.h
src/internet-stack/udp-socket-impl.cc
src/internet-stack/udp-socket-impl.h
src/node/ipv4-packet-info-tag.cc
src/node/ipv4-packet-info-tag.h
src/node/ipv6-packet-info-tag.cc
src/node/ipv6-packet-info-tag.h
src/node/socket.cc
src/node/socket.h
src/node/wscript
--- a/src/internet-stack/icmpv4-l4-protocol.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/icmpv4-l4-protocol.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -219,23 +219,22 @@
 
 enum Ipv4L4Protocol::RxStatus
 Icmpv4L4Protocol::Receive(Ptr<Packet> p, 
-			  Ipv4Address const &source,
-			  Ipv4Address const &destination,
+                          Ipv4Header const &header,
 			  Ptr<Ipv4Interface> incomingInterface)
 {
-  NS_LOG_FUNCTION (this << p << source << destination << incomingInterface);
+  NS_LOG_FUNCTION (this << p << header << incomingInterface);
 
   Icmpv4Header icmp;
   p->RemoveHeader (icmp);
   switch (icmp.GetType ()) {
   case Icmpv4Header::ECHO:
-    HandleEcho (p, icmp, source, destination);
+    HandleEcho (p, icmp, header.GetSource (), header.GetDestination ());
     break;
   case Icmpv4Header::DEST_UNREACH:
-    HandleDestUnreach (p, icmp, source, destination);
+    HandleDestUnreach (p, icmp, header.GetSource (), header.GetDestination ());
     break;
   case Icmpv4Header::TIME_EXCEEDED:
-    HandleTimeExceeded (p, icmp, source, destination);
+    HandleTimeExceeded (p, icmp, header.GetSource (), header.GetDestination ());
     break;
   default:
     NS_LOG_DEBUG (icmp << " " << *p);
--- a/src/internet-stack/icmpv4-l4-protocol.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/icmpv4-l4-protocol.h	Tue Jul 13 13:00:55 2010 +0900
@@ -25,8 +25,7 @@
   static uint16_t GetStaticProtocolNumber (void);
   virtual int GetProtocolNumber (void) const;
   virtual enum Ipv4L4Protocol::RxStatus Receive(Ptr<Packet> p, 
-						const Ipv4Address &source,
-						const Ipv4Address &destination,
+                                                Ipv4Header const &header,
 						Ptr<Ipv4Interface> incomingInterface);
 
   void SendDestUnreachFragNeeded (Ipv4Header header, Ptr<const Packet> orgData, uint16_t nextHopMtu);
--- a/src/internet-stack/ipv4-end-point.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/ipv4-end-point.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -89,7 +89,7 @@
 }
 
 void 
-Ipv4EndPoint::SetRxCallback (Callback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint16_t> callback)
+Ipv4EndPoint::SetRxCallback (Callback<void,Ptr<Packet>, Ipv4Header, uint16_t, Ptr<Ipv4Interface> > callback)
 {
   m_rxCallback = callback;
 }
@@ -106,17 +106,20 @@
 }
 
 void 
-Ipv4EndPoint::ForwardUp (Ptr<Packet> p, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport)
+Ipv4EndPoint::ForwardUp (Ptr<Packet> p, const Ipv4Header& header, uint16_t sport,
+                         Ptr<Ipv4Interface> incomingInterface)
 {
   if (!m_rxCallback.IsNull ())
     {
-      Simulator::ScheduleNow (&Ipv4EndPoint::DoForwardUp, this, p, saddr, daddr, sport);
+      Simulator::ScheduleNow (&Ipv4EndPoint::DoForwardUp, this, p, header, sport, 
+                              incomingInterface);
     }
 }
 void 
-Ipv4EndPoint::DoForwardUp (Ptr<Packet> p, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport)
+Ipv4EndPoint::DoForwardUp (Ptr<Packet> p, const Ipv4Header& header, uint16_t sport,
+                           Ptr<Ipv4Interface> incomingInterface)
 {
-  m_rxCallback (p, saddr, daddr, sport);
+  m_rxCallback (p, header, sport, incomingInterface);
 }
 
 void 
--- a/src/internet-stack/ipv4-end-point.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/ipv4-end-point.h	Tue Jul 13 13:00:55 2010 +0900
@@ -25,6 +25,8 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/callback.h"
 #include "ns3/net-device.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/ipv4-interface.h"
 
 namespace ns3 {
 
@@ -59,13 +61,14 @@
   Ptr<NetDevice> GetBoundNetDevice (void);
 
   // Called from socket implementations to get notified about important events.
-  void SetRxCallback (Callback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint16_t> callback);
+  void SetRxCallback (Callback<void,Ptr<Packet>, Ipv4Header, uint16_t, Ptr<Ipv4Interface> > callback);
   void SetIcmpCallback (Callback<void,Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> callback);
   void SetDestroyCallback (Callback<void> callback);
 
   // Called from an L4Protocol implementation to notify an endpoint of a
   // packet reception.
-  void ForwardUp (Ptr<Packet> p, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport);
+  void ForwardUp (Ptr<Packet> p, const Ipv4Header& header, uint16_t sport, 
+                  Ptr<Ipv4Interface> incomingInterface);
   // Called from an L4Protocol implementation to notify an endpoint of
   // an icmp message reception.
   void ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, 
@@ -73,7 +76,8 @@
                     uint32_t icmpInfo);
 
 private:
-  void DoForwardUp (Ptr<Packet> p, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport);
+  void DoForwardUp (Ptr<Packet> p, const Ipv4Header& header, uint16_t sport,
+                    Ptr<Ipv4Interface> incomingInterface);
   void DoForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, 
                       uint8_t icmpType, uint8_t icmpCode,
                       uint32_t icmpInfo);
@@ -82,7 +86,7 @@
   Ipv4Address m_peerAddr;
   uint16_t m_peerPort;
   Ptr<NetDevice> m_boundnetdevice;
-  Callback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint16_t> m_rxCallback;
+  Callback<void,Ptr<Packet>, Ipv4Header, uint16_t, Ptr<Ipv4Interface> > m_rxCallback;
   Callback<void,Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback;
   Callback<void> m_destroyCallback;
 };
--- a/src/internet-stack/ipv4-l3-protocol.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/ipv4-l3-protocol.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -480,7 +480,7 @@
     {
       NS_LOG_LOGIC ("Forwarding to raw socket"); 
       Ptr<Ipv4RawSocketImpl> socket = *i;
-      socket->ForwardUp (packet, ipHeader, device);
+      socket->ForwardUp (packet, ipHeader, ipv4Interface);
     }
 
   NS_ASSERT_MSG (m_routingProtocol != 0, "Need a routing protocol object to process packets");
@@ -818,7 +818,7 @@
       // RX_ENDPOINT_UNREACH codepath
       Ptr<Packet> copy = p->Copy ();
       enum Ipv4L4Protocol::RxStatus status = 
-        protocol->Receive (p, ip.GetSource (), ip.GetDestination (), GetInterface (iif));
+        protocol->Receive (p, ip, GetInterface (iif));
       switch (status) {
       case Ipv4L4Protocol::RX_OK:
         // fall through
--- a/src/internet-stack/ipv4-l4-protocol.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/ipv4-l4-protocol.h	Tue Jul 13 13:00:55 2010 +0900
@@ -62,14 +62,14 @@
    * \param p packet to forward up
    * \param source source address of packet received
    * \param destination address of packet received
+   * \param header IPv4 Header information
    * \param incomingInterface the Ipv4Interface on which the packet arrived
    * 
    * Called from lower-level layers to send the packet up
    * in the stack. 
    */
   virtual enum RxStatus Receive(Ptr<Packet> p, 
-                                Ipv4Address const &source,
-                                Ipv4Address const &destination,
+                                Ipv4Header const &header,
                                 Ptr<Ipv4Interface> incomingInterface) = 0;
 
   /**
--- a/src/internet-stack/ipv4-raw-socket-impl.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/ipv4-raw-socket-impl.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -3,6 +3,7 @@
 #include "ipv4-raw-socket-impl.h"
 #include "ipv4-l3-protocol.h"
 #include "icmpv4.h"
+#include "ns3/ipv4-packet-info-tag.h"
 #include "ns3/inet-socket-address.h"
 #include "ns3/node.h"
 #include "ns3/packet.h"
@@ -289,9 +290,9 @@
 }
 
 bool 
-Ipv4RawSocketImpl::ForwardUp (Ptr<const Packet> p, Ipv4Header ipHeader, Ptr<NetDevice> device)
+Ipv4RawSocketImpl::ForwardUp (Ptr<const Packet> p, Ipv4Header ipHeader, Ptr<Ipv4Interface> incomingInterface)
 {
-  NS_LOG_FUNCTION (this << *p << ipHeader << device);
+  NS_LOG_FUNCTION (this << *p << ipHeader << incomingInterface);
   if (m_shutdownRecv)
     {
       return false;
@@ -302,6 +303,14 @@
       ipHeader.GetProtocol () == m_protocol)
     {
       Ptr<Packet> copy = p->Copy ();
+      // Should check via getsockopt ()..
+      if (this->m_recvpktinfo)
+        {
+          Ipv4PacketInfoTag tag;
+          copy->RemovePacketTag (tag);
+          tag.SetRecvIf (incomingInterface->GetDevice ()->GetIfIndex ());
+          copy->AddPacketTag (tag);
+        }
       if (m_protocol == 1)
 	{
 	  Icmpv4Header icmpHeader;
--- a/src/internet-stack/ipv4-raw-socket-impl.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/ipv4-raw-socket-impl.h	Tue Jul 13 13:00:55 2010 +0900
@@ -5,6 +5,7 @@
 #include "ns3/socket.h"
 #include "ns3/ipv4-header.h"
 #include "ns3/ipv4-route.h"
+#include "ns3/ipv4-interface.h"
 #include <list>
 
 namespace ns3 {
@@ -41,7 +42,7 @@
 				Address &fromAddress);
 
   void SetProtocol (uint16_t protocol);
-  bool ForwardUp (Ptr<const Packet> p, Ipv4Header ipHeader, Ptr<NetDevice> device);
+  bool ForwardUp (Ptr<const Packet> p, Ipv4Header ipHeader, Ptr<Ipv4Interface> incomingInterface);
   virtual void SetAllowBroadcast (bool allowBroadcast);
   virtual bool GetAllowBroadcast () const;
 
--- a/src/internet-stack/ipv4-raw-test.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/ipv4-raw-test.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -1,6 +1,6 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2010 Keio University
+ * Copyright (c) 2010 Hajime Tazaki
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
--- a/src/internet-stack/ipv6-raw-socket-impl.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/ipv6-raw-socket-impl.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -26,6 +26,7 @@
 #include "ns3/log.h"
 #include "ns3/ipv6-route.h"
 #include "ns3/ipv6-routing-protocol.h"
+#include "ns3/ipv6-packet-info-tag.h"
 
 #include "ipv6-l3-protocol.h"
 #include "ipv6-raw-socket-impl.h"
@@ -325,6 +326,15 @@
             }
         }
 
+      // Should check via getsockopt ()..
+      if (this->m_recvpktinfo)
+        {
+          Ipv6PacketInfoTag tag;
+          copy->RemovePacketTag (tag);
+          tag.SetRecvIf (device->GetIfIndex ());
+          copy->AddPacketTag (tag);
+        }
+
       copy->AddHeader (hdr);
       struct Data data;
       data.packet = copy;
--- a/src/internet-stack/nsc-tcp-l4-protocol.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/nsc-tcp-l4-protocol.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -302,11 +302,10 @@
 
 Ipv4L4Protocol::RxStatus
 NscTcpL4Protocol::Receive (Ptr<Packet> packet,
-             Ipv4Address const &source,
-             Ipv4Address const &destination,
+             Ipv4Header const &header,
              Ptr<Ipv4Interface> incomingInterface)
 {
-  NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface);
+  NS_LOG_FUNCTION (this << packet << header << incomingInterface);
   Ipv4Header ipHeader;
   uint32_t packetSize = packet->GetSize();
 
@@ -315,8 +314,8 @@
   // a complete IP packet, so we add the IP header back.
   // Since the original header is already gone, we create a new one
   // based on the information we have.
-  ipHeader.SetSource (source);
-  ipHeader.SetDestination (destination);
+  ipHeader.SetSource (header.GetSource ());
+  ipHeader.SetDestination (header.GetDestination ());
   ipHeader.SetProtocol (PROT_NUMBER);
   ipHeader.SetPayloadSize (packetSize);
   ipHeader.SetTtl (1);
@@ -382,7 +381,7 @@
   for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
        endPoint != endPoints.end (); endPoint++) {
           // NSC HACK: (ab)use TcpSocket::ForwardUp for signalling
-          (*endPoint)->ForwardUp (NULL, Ipv4Address(), Ipv4Address(), 0);
+          (*endPoint)->ForwardUp (NULL, Ipv4Header(), 0, 0);
   }
 }
 
--- a/src/internet-stack/nsc-tcp-l4-protocol.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/nsc-tcp-l4-protocol.h	Tue Jul 13 13:00:55 2010 +0900
@@ -82,8 +82,7 @@
    * \param incomingInterface The Ipv4Interface it was received on
    */
   virtual Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
-                                            Ipv4Address const &source,
-                                            Ipv4Address const &destination,
+                                            Ipv4Header const &header,
                                             Ptr<Ipv4Interface> incomingInterface);
 
 protected:
--- a/src/internet-stack/nsc-tcp-socket-impl.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/nsc-tcp-socket-impl.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -466,7 +466,8 @@
 }
 
 void
-NscTcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address saddr, Ipv4Address daddr, uint16_t port)
+NscTcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port,
+                             Ptr<Ipv4Interface> incomingInterface)
 {
   NSCWakeup();
 }
--- a/src/internet-stack/nsc-tcp-socket-impl.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/nsc-tcp-socket-impl.h	Tue Jul 13 13:00:55 2010 +0900
@@ -90,7 +90,8 @@
   friend class Tcp;
   // invoked by Tcp class
   int FinishBind (void);
-  void ForwardUp (Ptr<Packet> p, Ipv4Address saddr, Ipv4Address daddr, uint16_t port);
+  void ForwardUp (Ptr<Packet> p, Ipv4Header header, uint16_t port, 
+                  Ptr<Ipv4Interface> incomingInterface);
   void Destroy (void);
   //methods for state
   bool SendPendingData(void);
--- a/src/internet-stack/tcp-l4-protocol.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/tcp-l4-protocol.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -478,17 +478,16 @@
 
 enum Ipv4L4Protocol::RxStatus
 TcpL4Protocol::Receive (Ptr<Packet> packet,
-             Ipv4Address const &source,
-             Ipv4Address const &destination,
+             Ipv4Header const &ipHeader,
              Ptr<Ipv4Interface> incomingInterface)
 {
-  NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface);
+  NS_LOG_FUNCTION (this << packet << ipHeader << incomingInterface);
 
   TcpHeader tcpHeader;
   if(Node::ChecksumEnabled ())
   {
     tcpHeader.EnableChecksums();
-    tcpHeader.InitializeChecksum (source, destination, PROT_NUMBER);
+    tcpHeader.InitializeChecksum (ipHeader.GetSource (), ipHeader.GetDestination (), PROT_NUMBER);
   }
 
   packet->PeekHeader (tcpHeader);
@@ -507,16 +506,16 @@
 
   NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
   Ipv4EndPointDemux::EndPoints endPoints =
-    m_endPoints->Lookup (destination, tcpHeader.GetDestinationPort (),
-                         source, tcpHeader.GetSourcePort (),incomingInterface);
+    m_endPoints->Lookup (ipHeader.GetDestination (), tcpHeader.GetDestinationPort (),
+                         ipHeader.GetSource (), tcpHeader.GetSourcePort (),incomingInterface);
   if (endPoints.empty ())
   {
     NS_LOG_LOGIC ("  No endpoints matched on TcpL4Protocol "<<this);
     std::ostringstream oss;
     oss<<"  destination IP: ";
-    destination.Print (oss);
+    ipHeader.GetDestination ().Print (oss);
     oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
-    source.Print (oss);
+    ipHeader.GetSource ().Print (oss);
     oss<<" source port: "<<tcpHeader.GetSourcePort ();
     NS_LOG_LOGIC (oss.str ());
 
@@ -539,7 +538,7 @@
           }
         header.SetSourcePort (tcpHeader.GetDestinationPort ());
         header.SetDestinationPort (tcpHeader.GetSourcePort ());
-        SendPacket (rstPacket, header, destination, source);
+        SendPacket (rstPacket, header, ipHeader.GetDestination (), ipHeader.GetSource ());
         return Ipv4L4Protocol::RX_ENDPOINT_CLOSED;
       }
     else
@@ -549,7 +548,8 @@
   }
   NS_ASSERT_MSG (endPoints.size() == 1 , "Demux returned more than one endpoint");
   NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
-  (*endPoints.begin ())->ForwardUp (packet, source, destination, tcpHeader.GetSourcePort ());
+  (*endPoints.begin ())->ForwardUp (packet, ipHeader, tcpHeader.GetSourcePort (), 
+                                    incomingInterface);
   return Ipv4L4Protocol::RX_OK;
 }
 
--- a/src/internet-stack/tcp-l4-protocol.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/tcp-l4-protocol.h	Tue Jul 13 13:00:55 2010 +0900
@@ -100,11 +100,11 @@
    * \param p The Packet to dump the contents into
    * \param source The source's Ipv4Address
    * \param destination The destinations Ipv4Address
+   * \param header IPv4 Header information
    * \param incomingInterface The Ipv4Interface it was received on
    */
   virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
-                                                 Ipv4Address const &source,
-                                                 Ipv4Address const &destination,
+                                                 Ipv4Header const &header,
                                                  Ptr<Ipv4Interface> incomingInterface);
 
 protected:
--- a/src/internet-stack/tcp-socket-impl.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/tcp-socket-impl.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -664,7 +664,8 @@
 }
 
 void
-TcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address saddr, Ipv4Address daddr, uint16_t port)
+TcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port,
+                          Ptr<Ipv4Interface> incomingInterface)
 {
   NS_LOG_DEBUG("Socket " << this << " got forward up" <<
                " dport " << m_endPoint->GetLocalPort() <<
@@ -672,10 +673,10 @@
                " sport " << m_endPoint->GetPeerPort() <<
                " saddr " << m_endPoint->GetPeerAddress());
 
-  NS_LOG_FUNCTION (this << packet << saddr << daddr << port);
+  NS_LOG_FUNCTION (this << packet << header << port);
 
-  Address fromAddress = InetSocketAddress (saddr, port);
-  Address toAddress = InetSocketAddress (daddr, m_endPoint->GetLocalPort());
+  Address fromAddress = InetSocketAddress (header.GetSource (), port);
+  Address toAddress = InetSocketAddress (header.GetDestination (), m_endPoint->GetLocalPort());
 
   TcpHeader tcpHeader;
   packet->RemoveHeader (tcpHeader);
--- a/src/internet-stack/tcp-socket-impl.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/tcp-socket-impl.h	Tue Jul 13 13:00:55 2010 +0900
@@ -28,6 +28,8 @@
 #include "ns3/ptr.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/event-id.h"
+#include "ns3/ipv4-header.h"
+#include "ipv4-interface.h"
 #include "tcp-typedefs.h"
 #include "pending-data.h"
 #include "ns3/sequence-number.h"
@@ -103,7 +105,8 @@
   friend class Tcp;
   // invoked by Tcp class
   int FinishBind (void);
-  void ForwardUp (Ptr<Packet> p, Ipv4Address saddr, Ipv4Address daddr, uint16_t port);
+  void ForwardUp (Ptr<Packet> p, Ipv4Header header, uint16_t port,
+                  Ptr<Ipv4Interface> incomingInterface);
   void Destroy (void);
   int DoSendTo (Ptr<Packet> p, const Address &daddr);
   int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
--- a/src/internet-stack/udp-l4-protocol.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/udp-l4-protocol.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -198,18 +198,17 @@
 
 enum Ipv4L4Protocol::RxStatus
 UdpL4Protocol::Receive(Ptr<Packet> packet, 
-                       Ipv4Address const &source,
-                       Ipv4Address const &destination,
+                       Ipv4Header const &header,
                        Ptr<Ipv4Interface> interface)
 {
-  NS_LOG_FUNCTION (this << packet << source << destination);
+  NS_LOG_FUNCTION (this << packet << header);
   UdpHeader udpHeader;
   if(Node::ChecksumEnabled ())
   {
     udpHeader.EnableChecksums();
   }
 
-  udpHeader.InitializeChecksum (source, destination, PROT_NUMBER);
+  udpHeader.InitializeChecksum (header.GetSource (), header.GetDestination (), PROT_NUMBER);
 
   packet->RemoveHeader (udpHeader);
 
@@ -220,8 +219,8 @@
   }
 
   Ipv4EndPointDemux::EndPoints endPoints =
-    m_endPoints->Lookup (destination, udpHeader.GetDestinationPort (),
-                         source, udpHeader.GetSourcePort (), interface);
+    m_endPoints->Lookup (header.GetDestination (), udpHeader.GetDestinationPort (),
+                         header.GetSource (), udpHeader.GetSourcePort (), interface);
   if (endPoints.empty ())
     {
       NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
@@ -230,7 +229,8 @@
   for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
        endPoint != endPoints.end (); endPoint++)
     {
-      (*endPoint)->ForwardUp (packet->Copy (), source, destination, udpHeader.GetSourcePort ());
+      (*endPoint)->ForwardUp (packet->Copy (), header, udpHeader.GetSourcePort (), 
+                              interface);
     }
   return Ipv4L4Protocol::RX_OK;
 }
--- a/src/internet-stack/udp-l4-protocol.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/udp-l4-protocol.h	Tue Jul 13 13:00:55 2010 +0900
@@ -86,12 +86,12 @@
    * \param p The Packet to dump the contents into
    * \param source The source's Ipv4Address
    * \param destination The destinations Ipv4Address
+   * \param header IPv4 Header information
    * \param interface the interface from which the packet is coming.
    */
   // inherited from Ipv4L4Protocol
   virtual enum Ipv4L4Protocol::RxStatus Receive(Ptr<Packet> p, 
-                                                Ipv4Address const &source,
-                                                Ipv4Address const &destination,
+                                                Ipv4Header const &header,
                                                 Ptr<Ipv4Interface> interface);
 
   /**
--- a/src/internet-stack/udp-socket-impl.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/udp-socket-impl.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -27,6 +27,7 @@
 #include "ns3/ipv4-routing-protocol.h"
 #include "ns3/udp-socket-factory.h"
 #include "ns3/trace-source-accessor.h"
+#include "ns3/ipv4-packet-info-tag.h"
 #include "udp-socket-impl.h"
 #include "udp-l4-protocol.h"
 #include "ipv4-end-point.h"
@@ -609,17 +610,28 @@
 }
 
 void 
-UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address saddr, Ipv4Address daddr, uint16_t port)
+UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port,
+                          Ptr<Ipv4Interface> incomingInterface)
 {
-  NS_LOG_FUNCTION (this << packet << saddr << daddr << port);
+  NS_LOG_FUNCTION (this << packet << header << port);
 
   if (m_shutdownRecv)
     {
       return;
     }
+
+  // Should check via getsockopt ()..
+  if (this->m_recvpktinfo)
+    {
+      Ipv4PacketInfoTag tag;
+      packet->RemovePacketTag (tag);
+      tag.SetRecvIf (incomingInterface->GetDevice ()->GetIfIndex ());
+      packet->AddPacketTag (tag);
+    }
+
   if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
     {
-      Address address = InetSocketAddress (saddr, port);
+      Address address = InetSocketAddress (header.GetSource (), port);
       SocketAddressTag tag;
       tag.SetAddress (address);
       packet->AddPacketTag (tag);
--- a/src/internet-stack/udp-socket-impl.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/internet-stack/udp-socket-impl.h	Tue Jul 13 13:00:55 2010 +0900
@@ -28,6 +28,7 @@
 #include "ns3/ptr.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/udp-socket.h"
+#include "ns3/ipv4-interface.h"
 #include "icmpv4.h"
 
 namespace ns3 {
@@ -100,7 +101,8 @@
   friend class UdpSocketFactory;
   // invoked by Udp class
   int FinishBind (void);
-  void ForwardUp (Ptr<Packet> p, Ipv4Address saddr, Ipv4Address daddr, uint16_t port);
+  void ForwardUp (Ptr<Packet> p, Ipv4Header header, uint16_t port, 
+                  Ptr<Ipv4Interface> incomingInterface);
   void Destroy (void);
   int DoSend (Ptr<Packet> p);
   int DoSendTo (Ptr<Packet> p, const Address &daddr);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-packet-info-tag.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -0,0 +1,284 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hajime Tazaki
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+
+#include <stdint.h>
+#include "ns3/ipv4-address.h"
+#include "ns3/test.h"
+#include "ipv4-packet-info-tag.h"
+
+namespace ns3 {
+
+Ipv4PacketInfoTag::Ipv4PacketInfoTag ()  
+  : m_addr (Ipv4Address ()),
+    m_spec_dst (Ipv4Address ()),
+    m_ifindex (0),
+    m_ttl (0)
+{
+}
+
+void 
+Ipv4PacketInfoTag::SetAddress (Ipv4Address addr)
+{
+  m_addr = addr;
+}
+
+Ipv4Address
+Ipv4PacketInfoTag::GetAddress (void) const
+{
+  return m_addr;
+}
+
+void 
+Ipv4PacketInfoTag::SetLocalAddress (Ipv4Address addr)
+{
+  m_spec_dst = addr;
+}
+
+Ipv4Address
+Ipv4PacketInfoTag::GetLocalAddress (void) const
+{
+  return m_spec_dst;
+}
+
+void 
+Ipv4PacketInfoTag::SetRecvIf (uint32_t ifindex)
+{
+  m_ifindex = ifindex;
+}
+
+uint32_t 
+Ipv4PacketInfoTag::GetRecvIf (void) const
+{
+  return m_ifindex;
+}
+
+void 
+Ipv4PacketInfoTag::SetTtl (uint8_t ttl)
+{
+  m_ttl = ttl;
+}
+
+uint8_t 
+Ipv4PacketInfoTag::GetTtl (void) const
+{
+  return m_ttl;
+}
+
+
+
+TypeId
+Ipv4PacketInfoTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4PacketInfoTag")
+    .SetParent<Tag> ()
+    .AddConstructor<Ipv4PacketInfoTag> ()
+    ;
+  return tid;
+}
+TypeId
+Ipv4PacketInfoTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+uint32_t 
+Ipv4PacketInfoTag::GetSerializedSize (void) const
+{ 
+  return 4 + 4 
+    + sizeof (uint32_t)
+    + sizeof (uint8_t);
+}
+void 
+Ipv4PacketInfoTag::Serialize (TagBuffer i) const
+{ 
+  uint8_t buf[4];
+  m_addr.Serialize (buf);
+  i.Write (buf, 4);
+  m_spec_dst.Serialize (buf);
+  i.Write (buf, 4);
+  i.WriteU32 (m_ifindex);
+  i.WriteU8 (m_ttl);
+}
+void 
+Ipv4PacketInfoTag::Deserialize (TagBuffer i)
+{ 
+  uint8_t buf[4];
+  i.Read (buf, 4);
+  m_addr.Deserialize (buf);
+  i.Read (buf, 4);
+  m_spec_dst.Deserialize (buf);
+  m_ifindex = i.ReadU32 ();
+  m_ttl = i.ReadU8 ();
+}
+void
+Ipv4PacketInfoTag::Print (std::ostream &os) const
+{
+  os << "Ipv4 PKTINFO [DestAddr: " << m_addr;
+  os << ", Local Address:" << m_spec_dst;
+  os << ", RecvIf:" << (uint32_t) m_ifindex;
+  os << ", TTL:" << (uint32_t) m_ttl;
+  os << "] ";
+}
+}//namespace ns3
+
+//-----------------------------------------------------------------------------
+// Unit tests
+//-----------------------------------------------------------------------------
+
+#include "ns3/log.h"
+#include "ns3/abort.h"
+#include "ns3/attribute.h"
+#include "ns3/object-factory.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/csma-helper.h"
+#include "ns3/node-container.h"
+#include "ns3/object-factory.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/udp-socket.h"
+#include "ns3/ipv4-raw-socket-factory.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+
+class Ipv4PacketInfoTagTest: public TestCase 
+{
+public:
+  Ipv4PacketInfoTagTest ();
+private:
+  virtual bool DoRun (void);
+  void RxCb (Ptr<Socket> socket);
+  void DoSendData (Ptr<Socket> socket, std::string to);
+};
+
+Ipv4PacketInfoTagTest::Ipv4PacketInfoTagTest ()
+  : TestCase ("Ipv4PacketInfoTagTest") 
+{}
+
+void
+Ipv4PacketInfoTagTest::RxCb (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  Ptr<Packet> m_receivedPacket;
+
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
+  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
+
+  Ipv4PacketInfoTag tag;
+  bool found;
+  found = m_receivedPacket->RemovePacketTag (tag);
+  NS_ASSERT (found);
+  tag.Print (std::cout);
+}
+
+void
+Ipv4PacketInfoTagTest::DoSendData (Ptr<Socket> socket, std::string to)
+{
+  Address realTo = InetSocketAddress (Ipv4Address (to.c_str()), 200);
+  if (DynamicCast<UdpSocket> (socket) != 0)
+    {
+      NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
+                             123, "XXX");
+    }
+  // Should only Ipv4RawSock
+  else
+    {
+      socket->SendTo (Create<Packet> (123), 0, realTo);
+    }
+}
+
+bool
+Ipv4PacketInfoTagTest::DoRun (void)
+{
+  NodeContainer n;
+  n.Create (2);
+
+  InternetStackHelper internet;
+  internet.Install (n);
+
+  CsmaHelper csma;
+  NetDeviceContainer d = csma.Install (n);
+
+  Ipv4AddressHelper ipv4;
+  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer i = ipv4.Assign (d);
+
+  // IPv4 test
+  Ptr<SocketFactory> factory = n.Get (0)->GetObject<SocketFactory> (UdpSocketFactory::GetTypeId ());
+  Ptr<Socket> socket = factory->CreateSocket ();
+  InetSocketAddress local =  InetSocketAddress (Ipv4Address::GetAny (), 200);
+  socket->Bind (local);
+  socket->SetRecvPktInfo (true);
+  socket->SetRecvCallback (MakeCallback (&ns3::Ipv4PacketInfoTagTest::RxCb, this));
+
+  // receive on loopback 
+  Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+                                  &Ipv4PacketInfoTagTest::DoSendData, this, socket, "127.0.0.1");
+  Simulator::Run ();
+
+  // send from node1 and recved via csma
+  Ptr<SocketFactory> factory2 = n.Get (1)->GetObject<SocketFactory> (UdpSocketFactory::GetTypeId ());
+  Ptr<Socket> socket2 = factory2->CreateSocket ();
+  Simulator::ScheduleWithContext (socket2->GetNode ()->GetId (), Seconds (0),
+                                  &Ipv4PacketInfoTagTest::DoSendData, this, socket, "10.1.1.1");
+  Simulator::Run ();
+
+  // ipv4 w rawsocket
+  factory = n.Get (0)->GetObject<SocketFactory> (Ipv4RawSocketFactory::GetTypeId ());
+  socket = factory->CreateSocket ();
+  local =  InetSocketAddress (Ipv4Address::GetAny (), 0);
+  socket->Bind (local);
+  socket->SetRecvPktInfo (true);
+  socket->SetRecvCallback (MakeCallback (&ns3::Ipv4PacketInfoTagTest::RxCb, this));
+
+  // receive on loopback 
+  Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+                                  &Ipv4PacketInfoTagTest::DoSendData, this, socket, "127.0.0.1");
+  Simulator::Run ();
+
+  // send from node1 and recved via csma
+  factory2 = n.Get (1)->GetObject<SocketFactory> (Ipv4RawSocketFactory::GetTypeId ());
+  socket2 = factory2->CreateSocket ();
+  Simulator::ScheduleWithContext (socket2->GetNode ()->GetId (), Seconds (0),
+                                  &Ipv4PacketInfoTagTest::DoSendData, this, socket, "10.1.1.1");
+  Simulator::Run ();
+
+  return 0;
+}
+
+static class Ipv4PacketInfoTagTestSuite : public TestSuite
+{
+public:
+  Ipv4PacketInfoTagTestSuite ();
+private:
+} g_packetinfotagTests;
+
+Ipv4PacketInfoTagTestSuite::Ipv4PacketInfoTagTestSuite ()
+  : TestSuite ("ipv4-packet-info-tag", UNIT)
+{
+  AddTestCase (new Ipv4PacketInfoTagTest ());
+}
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-packet-info-tag.h	Tue Jul 13 13:00:55 2010 +0900
@@ -0,0 +1,89 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hajime Tazaki
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef __IPV4_PACKET_INFO_TAG_H__
+#define __IPV4_PACKET_INFO_TAG_H__
+
+#include "ns3/tag.h"
+
+namespace ns3 {
+
+
+class Node;
+class Packet;
+
+/**
+ * \brief This class implements Linux struct pktinfo 
+ * in order to deliver ancillary information to the socket interface.
+ * This is used with socket option such as IP_PKTINFO, IP_RECVTTL, 
+ * IP_RECVTOS. See linux manpage ip(7).
+ *
+ * This tag in the send direction is presently not enabled but we
+ * would accept a patch along those lines in the future.
+ */
+class Ipv4PacketInfoTag : public Tag
+{
+public:
+  Ipv4PacketInfoTag ();
+  // Implemented, but not used in the stack yet
+  void SetAddress (Ipv4Address addr);
+  // Implemented, but not used in the stack yet
+  Ipv4Address GetAddress (void) const;
+  // This corresponds to "ipi_spec_dst" in struct in_pktinfo.
+  // Implemented, but not used in the stack yet
+  void SetLocalAddress (Ipv4Address addr);
+  // This corresponds to "ipi_spec_dst" in struct in_pktinfo.
+  // Implemented, but not used in the stack yet
+  Ipv4Address GetLocalAddress (void) const;
+  void SetRecvIf (uint32_t ifindex);
+  uint32_t GetRecvIf (void) const;
+  // Implemented, but not used in the stack yet
+  void SetTtl (uint8_t ttl);
+  // Implemented, but not used in the stack yet
+  uint8_t GetTtl (void) const;
+
+  static TypeId GetTypeId (void);  
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
+
+private:
+  // Linux IP_PKTINFO ip(7) implementation
+  // 
+  // struct in_pktinfo {
+  //   unsigned int   ipi_ifindex;  /* Interface index */
+  //   struct in_addr ipi_spec_dst; /* Local address */
+  //   struct in_addr ipi_addr;     /* Header Destination
+  //                                   address */
+  // };
+
+  Ipv4Address m_addr;
+  Ipv4Address m_spec_dst;
+  uint32_t m_ifindex;
+
+  // Uset for IP_RECVTTL, though not implemented yet.
+  uint8_t m_ttl;
+};
+} //namespace ns3
+
+#endif /* __IPV4_PACKET_INFO_TAG_H__ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-packet-info-tag.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -0,0 +1,294 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hajime Tazaki
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+
+#include <stdint.h>
+#include "ns3/ipv6-address.h"
+#include "ns3/test.h"
+#include "ipv6-packet-info-tag.h"
+
+namespace ns3 {
+
+Ipv6PacketInfoTag::Ipv6PacketInfoTag ()  
+  : m_addr (Ipv6Address ()),
+    m_ifindex (0),
+    m_hoplimit (0),
+    m_tclass (0)
+{
+}
+
+void 
+Ipv6PacketInfoTag::SetAddress (Ipv6Address addr)
+{
+  m_addr = addr;
+}
+
+Ipv6Address
+Ipv6PacketInfoTag::GetAddress (void) const
+{
+  return m_addr;
+}
+
+void 
+Ipv6PacketInfoTag::SetRecvIf (uint32_t ifindex)
+{
+  m_ifindex = ifindex;
+}
+
+uint32_t 
+Ipv6PacketInfoTag::GetRecvIf (void) const
+{
+  return m_ifindex;
+}
+
+void 
+Ipv6PacketInfoTag::SetHoplimit (uint8_t ttl)
+{
+  m_hoplimit = ttl;
+}
+
+uint8_t 
+Ipv6PacketInfoTag::GetHoplimit (void) const
+{
+  return m_hoplimit;
+}
+
+void 
+Ipv6PacketInfoTag::SetTrafficClass (uint8_t tclass)
+{
+  m_tclass = tclass;
+}
+
+uint8_t 
+Ipv6PacketInfoTag::GetTrafficClass (void) const
+{
+  return m_tclass;
+}
+
+
+TypeId
+Ipv6PacketInfoTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv6PacketInfoTag")
+    .SetParent<Tag> ()
+    .AddConstructor<Ipv6PacketInfoTag> ()
+    ;
+  return tid;
+}
+TypeId
+Ipv6PacketInfoTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+uint32_t 
+Ipv6PacketInfoTag::GetSerializedSize (void) const
+{ 
+  return 16
+    + sizeof (uint8_t)
+    + sizeof (uint8_t)
+    + sizeof (uint8_t);
+}
+void 
+Ipv6PacketInfoTag::Serialize (TagBuffer i) const
+{ 
+  uint8_t buf[16];
+  m_addr.Serialize (buf);
+  i.Write (buf, 16);
+  i.WriteU8 (m_ifindex);
+  i.WriteU8 (m_hoplimit);
+  i.WriteU8 (m_tclass);
+}
+void 
+Ipv6PacketInfoTag::Deserialize (TagBuffer i)
+{ 
+  uint8_t buf[16];
+  i.Read (buf, 16);
+  m_addr.Deserialize (buf);
+  m_ifindex = i.ReadU8 ();
+  m_hoplimit = i.ReadU8 ();
+  m_tclass = i.ReadU8 ();
+}
+void
+Ipv6PacketInfoTag::Print (std::ostream &os) const
+{
+  os << "Ipv6 PKTINFO [DestAddr: " << m_addr;
+  os << ", RecvIf:" << (uint32_t) m_ifindex;
+  os << ", TTL:" << (uint32_t) m_hoplimit;
+  os << ", TClass:" << (uint32_t) m_tclass;
+  os << "] ";
+}
+}//namespace ns3
+
+//-----------------------------------------------------------------------------
+// Unit tests
+//-----------------------------------------------------------------------------
+
+#include "ns3/log.h"
+#include "ns3/abort.h"
+#include "ns3/attribute.h"
+#include "ns3/object-factory.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv6-address-helper.h"
+#include "ns3/csma-helper.h"
+#include "ns3/node-container.h"
+#include "ns3/object-factory.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/udp-socket.h"
+#include "ns3/ipv6-raw-socket-factory.h"
+#include "ns3/inet6-socket-address.h"
+#include "ns3/simulator.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+class Ipv6PacketInfoTagTest: public TestCase 
+{
+public:
+  Ipv6PacketInfoTagTest ();
+private:
+  virtual bool DoRun (void);
+  void RxCb (Ptr<Socket> socket);
+  void DoSendData (Ptr<Socket> socket, std::string to);
+};
+
+Ipv6PacketInfoTagTest::Ipv6PacketInfoTagTest ()
+  : TestCase ("Ipv6PacketInfoTagTest") 
+{}
+
+void
+Ipv6PacketInfoTagTest::RxCb (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  Ptr<Packet> m_receivedPacket;
+
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
+  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
+
+  Ipv6PacketInfoTag tag;
+  bool found;
+  found = m_receivedPacket->RemovePacketTag (tag);
+  NS_ASSERT (found);
+  tag.Print (std::cout);
+  std::cout << std::endl;
+}
+
+void
+Ipv6PacketInfoTagTest::DoSendData (Ptr<Socket> socket, std::string to)
+{
+  Address realTo = Inet6SocketAddress (Ipv6Address (to.c_str()), 200);
+  if (DynamicCast<UdpSocket> (socket) != 0)
+    {
+      NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
+                             123, "XXX");
+    }
+  // Should only Ipv6RawSock
+  else
+    {
+      socket->SendTo (Create<Packet> (123), 0, realTo);
+    }
+}
+
+bool
+Ipv6PacketInfoTagTest::DoRun (void)
+{
+  NodeContainer n;
+  n.Create (2);
+
+  InternetStackHelper internet;
+  internet.Install (n);
+
+  CsmaHelper csma;
+  NetDeviceContainer d = csma.Install (n);
+
+  Ipv6AddressHelper ipv6;
+  ipv6.NewNetwork(Ipv6Address("2000:1000:0:2000::"), Ipv6Prefix(64));
+  Ipv6InterfaceContainer i = ipv6.Assign (d);
+
+
+  // ipv6 w rawsocket
+  Ptr<SocketFactory> factory = n.Get (0)->GetObject<SocketFactory> (Ipv6RawSocketFactory::GetTypeId ());
+  Ptr<Socket> socket = factory->CreateSocket ();
+  Inet6SocketAddress local =  Inet6SocketAddress (Ipv6Address::GetAny (), 0);
+  socket->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_ICMPV6));
+  socket->Bind (local);
+  socket->SetRecvPktInfo (true);
+  socket->SetRecvCallback (MakeCallback (&ns3::Ipv6PacketInfoTagTest::RxCb, this));
+
+  // receive on loopback 
+  Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+                                  &Ipv6PacketInfoTagTest::DoSendData, this, socket, "::1");
+  Simulator::Run ();
+
+  // send from node1 and recved via csma
+  Ptr<SocketFactory> factory2 = n.Get (1)->GetObject<SocketFactory> (Ipv6RawSocketFactory::GetTypeId ());
+  Ptr<Socket> socket2 = factory2->CreateSocket ();
+  std::stringstream dst;
+  dst << i.GetAddress (0, 0);
+  Simulator::ScheduleWithContext (socket2->GetNode ()->GetId (), Seconds (0),
+                                  &Ipv6PacketInfoTagTest::DoSendData, this, socket, 
+                                  dst.str ());
+  Simulator::Run ();
+
+#ifdef UDP6_SUPPORTED
+  // IPv6 test
+  factory = n.Get (0)->GetObject<SocketFactory> (UdpSocketFactory::GetTypeId ());
+  socket = factory->CreateSocket ();
+  local =  Inet6SocketAddress (Ipv6Address::GetAny (), 200);
+  socket->Bind (local);
+  socket->SetRecvPktInfo (true);
+  socket->SetRecvCallback (MakeCallback (&ns3::Ipv6PacketInfoTagTest::RxCb, this));
+
+  // receive on loopback 
+  Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+                                  &Ipv6PacketInfoTagTest::DoSendData, this, socket, "::1");
+  Simulator::Run ();
+
+  // send from node1 and recved via csma
+  factory2 = n.Get (1)->GetObject<SocketFactory> (UdpSocketFactory::GetTypeId ());
+  socket2 = factory2->CreateSocket ();
+  Simulator::ScheduleWithContext (socket2->GetNode ()->GetId (), Seconds (0),
+                                  &Ipv6PacketInfoTagTest::DoSendData, this, socket, "10.1.1.1");
+  Simulator::Run ();
+
+#endif  // UDP6_SUPPORTED
+
+  // IPv6 test
+  return 0;
+}
+
+static class Ipv6PacketInfoTagTestSuite : public TestSuite
+{
+public:
+  Ipv6PacketInfoTagTestSuite ();
+private:
+} g_packetinfotagTests;
+
+Ipv6PacketInfoTagTestSuite::Ipv6PacketInfoTagTestSuite ()
+  : TestSuite ("ipv6-packet-info-tag", UNIT)
+{
+  AddTestCase (new Ipv6PacketInfoTagTest ());
+}
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-packet-info-tag.h	Tue Jul 13 13:00:55 2010 +0900
@@ -0,0 +1,94 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hajime Tazaki
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef __IPV6_PACKET_INFO_TAG_H__
+#define __IPV6_PACKET_INFO_TAG_H__
+
+#include "ns3/tag.h"
+
+namespace ns3 {
+
+
+class Node;
+class Packet;
+
+/**
+ * \brief This class implements a tag that carries socket ancillary 
+ * data to the socket interface. This is used like 
+ * socket option of IP_PKTINFO/IPV6_PKTINFO in RFC 3542
+ * See: http://tools.ietf.org/html/rfc3542
+ *
+ * This tag in the send direction is presently not enabled but we
+ * would accept a patch along those lines in the future. To include
+ * the nexthop in the send direction would increase the size of the
+ * tag beyond 20 bytes, so in that case, we recommend that an
+ * additional tag be used to carry the IPv6 next hop address.
+ */
+class Ipv6PacketInfoTag : public Tag
+{
+public:
+  Ipv6PacketInfoTag ();
+  // Implemented, but not used in the stack yet
+  void SetAddress (Ipv6Address addr);
+  // Implemented, but not used in the stack yet
+  Ipv6Address GetAddress (void) const;
+  void SetRecvIf (uint32_t ifindex);
+  uint32_t GetRecvIf (void) const;
+  // Implemented, but not used in the stack yet
+  void SetHoplimit (uint8_t ttl);
+  // Implemented, but not used in the stack yet
+  uint8_t GetHoplimit (void) const;
+  // Implemented, but not used in the stack yet
+  void SetTrafficClass (uint8_t tclass);
+  // Implemented, but not used in the stack yet
+  uint8_t GetTrafficClass (void) const;
+
+  static TypeId GetTypeId (void);  
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
+
+private:
+  /* 
+   * RFC 3542 includes
+   * for outgoing packet,
+   *  1.  the source IPv6 address,
+   *  2.  the outgoing interface index,
+   *  3.  the outgoing hop limit,
+   *  4.  the next hop address, and
+   *  5.  the outgoing traffic class value.
+   *
+   * for incoming packet,
+   *  1.  the destination IPv6 address,
+   *  2.  the arriving interface index,
+   *  3.  the arriving hop limit, and
+   *  4.  the arriving traffic class value.
+  */
+  Ipv6Address m_addr;
+  uint8_t m_ifindex;
+  uint8_t m_hoplimit;
+  uint8_t m_tclass;
+};
+} //namespace ns3
+
+#endif /* __IPV6_PACKET_INFO_TAG_H__ */
+
--- a/src/node/socket.cc	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/node/socket.cc	Tue Jul 13 13:00:55 2010 +0900
@@ -34,6 +34,7 @@
 Socket::Socket (void)
 {
   m_boundnetdevice = 0;
+  m_recvpktinfo = false;
   NS_LOG_FUNCTION_NOARGS ();
 }
 
@@ -324,6 +325,13 @@
   return m_boundnetdevice;
 }
 
+void 
+Socket::SetRecvPktInfo (bool flag)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_recvpktinfo = flag;
+}
+
 /***************************************************************
  *           Socket Tags
  ***************************************************************/
--- a/src/node/socket.h	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/node/socket.h	Tue Jul 13 13:00:55 2010 +0900
@@ -570,6 +570,16 @@
    */
   virtual bool GetAllowBroadcast () const = 0;
 
+  /**
+   * \brief Enable/Disable receive packet information to socket.
+   *
+   * For IP_PKTINFO/IP6_PKTINFO. This method is only usable for 
+   * Raw socket and Datagram Socket. Not supported for Stream socket.
+   *
+   * \param Enable/Disable receive information
+   * \returns nothing
+   */
+  void SetRecvPktInfo (bool flag);
  
 protected:
   void NotifyConnectionSucceeded (void);
@@ -583,6 +593,7 @@
   void NotifyDataRecv (void);
   virtual void DoDispose (void);
   Ptr<NetDevice> m_boundnetdevice;
+  bool m_recvpktinfo;
 private:
   Callback<void, Ptr<Socket> >                   m_connectionSucceeded;
   Callback<void, Ptr<Socket> >                   m_connectionFailed;
--- a/src/node/wscript	Mon Jul 12 11:45:15 2010 +0100
+++ b/src/node/wscript	Tue Jul 13 13:00:55 2010 +0900
@@ -51,6 +51,8 @@
         'radiotap-header.cc',
         'spectrum-phy.cc',
         'spectrum-channel.cc',        
+        'ipv4-packet-info-tag.cc',
+        'ipv6-packet-info-tag.cc',
         ]
 
     headers = bld.new_task_gen('ns3header')
@@ -103,4 +105,6 @@
         'spectrum-phy.h',
         'spectrum-channel.h',
         'phy-mac.h',
+        'ipv4-packet-info-tag.h',
+        'ipv6-packet-info-tag.h',
         ]