bug 1359 TCP cannot receive ICMP
authorTommaso Pecorella <tommaso.pecorella@unifi.it>
Thu, 27 Sep 2012 13:29:03 -0400
changeset 9095 8462a1160246
parent 9094 900fd8faab0d
child 9096 94215be61edf
bug 1359 TCP cannot receive ICMP
src/internet/model/tcp-l4-protocol.cc
src/internet/model/tcp-l4-protocol.h
src/internet/model/tcp-socket-base.cc
src/internet/model/tcp-socket-base.h
--- a/src/internet/model/tcp-l4-protocol.cc	Tue Sep 25 14:08:22 2012 -0700
+++ b/src/internet/model/tcp-l4-protocol.cc	Thu Sep 27 13:29:03 2012 -0400
@@ -285,6 +285,60 @@
   m_endPoints6->DeAllocate (endPoint);
 }
 
+void 
+TcpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv4Address payloadSource,Ipv4Address payloadDestination,
+                            const uint8_t payload[8])
+{
+  NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo 
+                        << payloadSource << payloadDestination);
+  uint16_t src, dst;
+  src = payload[0] << 8;
+  src |= payload[1];
+  dst = payload[2] << 8;
+  dst |= payload[3];
+
+  Ipv4EndPoint *endPoint = m_endPoints->SimpleLookup (payloadSource, src, payloadDestination, dst);
+  if (endPoint != 0)
+    {
+      endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
+    }
+  else
+    {
+      NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
+                    ", destination="<<payloadDestination<<
+                    ", src=" << src << ", dst=" << dst);
+    }
+}
+
+void 
+TcpL4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv6Address payloadSource,Ipv6Address payloadDestination,
+                            const uint8_t payload[8])
+{
+  NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo 
+                        << payloadSource << payloadDestination);
+  uint16_t src, dst;
+  src = payload[0] << 8;
+  src |= payload[1];
+  dst = payload[2] << 8;
+  dst |= payload[3];
+
+  Ipv6EndPoint *endPoint = m_endPoints6->SimpleLookup (payloadSource, src, payloadDestination, dst);
+  if (endPoint != 0)
+    {
+      endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
+    }
+  else
+    {
+      NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
+                    ", destination="<<payloadDestination<<
+                    ", src=" << src << ", dst=" << dst);
+    }
+}
+
 enum IpL4Protocol::RxStatus
 TcpL4Protocol::Receive (Ptr<Packet> packet,
                         Ipv4Header const &ipHeader,
--- a/src/internet/model/tcp-l4-protocol.h	Tue Sep 25 14:08:22 2012 -0700
+++ b/src/internet/model/tcp-l4-protocol.h	Thu Sep 27 13:29:03 2012 -0400
@@ -119,6 +119,26 @@
                                                  Ipv6Address &dst,
                                                  Ptr<Ipv6Interface> interface);
 
+  /**
+   * \brief Receive an ICMP packet
+   * \param icmpSource The IP address of the source of the packet.
+   * \param icmpTtl The time to live from the IP header
+   * \param icmpType The type of the message from the ICMP header
+   * \param icmpCode The message code from the ICMP header
+   * \param icmpInfo 32-bit integer carrying informational value of varying semantics.
+   * \param payloadSource The IP source address from the IP header of the packet
+   * \param payloadDestination The IP destination address from the IP header of the packet
+   * \param payload Payload of the ICMP packet
+   */
+  virtual void ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv4Address payloadSource,Ipv4Address payloadDestination,
+                            const uint8_t payload[8]);
+  virtual void ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv6Address payloadSource,Ipv6Address payloadDestination,
+                            const uint8_t payload[8]);
+
   // From IpL4Protocol
   virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
   virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
--- a/src/internet/model/tcp-socket-base.cc	Tue Sep 25 14:08:22 2012 -0700
+++ b/src/internet/model/tcp-socket-base.cc	Thu Sep 27 13:29:03 2012 -0400
@@ -75,6 +75,14 @@
                    UintegerValue (65535),
                    MakeUintegerAccessor (&TcpSocketBase::m_maxWinSize),
                    MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
+                   CallbackValue (),
+                   MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback),
+                   MakeCallbackChecker ())
+    .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
+                   CallbackValue (),
+                   MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback6),
+                   MakeCallbackChecker ())                   
     .AddTraceSource ("RTO",
                      "Retransmission timeout",
                      MakeTraceSourceAccessor (&TcpSocketBase::m_rto))
@@ -640,11 +648,13 @@
   if (m_endPoint != 0)
     {
       m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSocketBase> (this)));
+      m_endPoint->SetIcmpCallback (MakeCallback (&TcpSocketBase::ForwardIcmp, Ptr<TcpSocketBase> (this)));
       m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<TcpSocketBase> (this)));
     }
   if (m_endPoint6 != 0)
     {
       m_endPoint6->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp6, Ptr<TcpSocketBase> (this)));
+      m_endPoint6->SetIcmpCallback (MakeCallback (&TcpSocketBase::ForwardIcmp6, Ptr<TcpSocketBase> (this)));
       m_endPoint6->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy6, Ptr<TcpSocketBase> (this)));
     }
 
@@ -772,6 +782,32 @@
   DoForwardUp (packet, saddr, daddr, port);
 }
 
+void
+TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode,
+                            uint32_t icmpInfo)
+{
+  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
+                   (uint32_t)icmpCode << icmpInfo);
+  if (!m_icmpCallback.IsNull ())
+    {
+      m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
+    }
+}
+
+void
+TcpSocketBase::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode,
+                            uint32_t icmpInfo)
+{
+  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
+                   (uint32_t)icmpCode << icmpInfo);
+  if (!m_icmpCallback6.IsNull ())
+    {
+      m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
+    }
+}
+
 /** The real function to handle the incoming packet from lower layers. This is
     wrapped by ForwardUp() so that this function can be overloaded by daughter
     classes. */
--- a/src/internet/model/tcp-socket-base.h	Tue Sep 25 14:08:22 2012 -0700
+++ b/src/internet/model/tcp-socket-base.h	Thu Sep 27 13:29:03 2012 -0400
@@ -138,6 +138,8 @@
   void ForwardUp6 (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port);
   virtual void DoForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port, Ptr<Ipv4Interface> incomingInterface); //Get a pkt from L3
   virtual void DoForwardUp (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port); // Ipv6 version
+  void ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo);
+  void ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo);  
   bool SendPendingData (bool withAck = false); // Send as much as the window allows
   uint32_t SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck); // Send a data packet
   void SendEmptyPacket (uint8_t flags); // Send a empty packet that carries a flag, e.g. ACK
@@ -211,6 +213,8 @@
   Ipv6EndPoint*       m_endPoint6;
   Ptr<Node>           m_node;
   Ptr<TcpL4Protocol>  m_tcp;
+  Callback<void, Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback;
+  Callback<void, Ipv6Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback6;
 
   // Round trip time estimation
   Ptr<RttEstimator> m_rtt;