# HG changeset patch # User Fabian Mauchle # Date 1258971405 -3600 # Node ID 28d8e04ab7901063e0cf6bed0785c991ee7f0d33 # Parent 547ae5e7d3d01757d8ee7f2b9424bd50d9a8160d Tcp bug: cloned tcp socket uses wrong source address diff -r 547ae5e7d3d0 -r 28d8e04ab790 src/internet-stack/ipv4-end-point.cc --- a/src/internet-stack/ipv4-end-point.cc Thu Nov 19 14:57:17 2009 +0100 +++ b/src/internet-stack/ipv4-end-point.cc Mon Nov 23 11:16:45 2009 +0100 @@ -76,7 +76,7 @@ } void -Ipv4EndPoint::SetRxCallback (Callback, Ipv4Address, uint16_t> callback) +Ipv4EndPoint::SetRxCallback (Callback, Ipv4Address, Ipv4Address, uint16_t> callback) { m_rxCallback = callback; } @@ -93,17 +93,17 @@ } void -Ipv4EndPoint::ForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport) +Ipv4EndPoint::ForwardUp (Ptr p, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport) { if (!m_rxCallback.IsNull ()) { - Simulator::ScheduleNow (&Ipv4EndPoint::DoForwardUp, this, p, saddr, sport); + Simulator::ScheduleNow (&Ipv4EndPoint::DoForwardUp, this, p, saddr, daddr, sport); } } void -Ipv4EndPoint::DoForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport) +Ipv4EndPoint::DoForwardUp (Ptr p, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport) { - m_rxCallback (p, saddr, sport); + m_rxCallback (p, saddr, daddr, sport); } void diff -r 547ae5e7d3d0 -r 28d8e04ab790 src/internet-stack/ipv4-end-point.h --- a/src/internet-stack/ipv4-end-point.h Thu Nov 19 14:57:17 2009 +0100 +++ b/src/internet-stack/ipv4-end-point.h Mon Nov 23 11:16:45 2009 +0100 @@ -55,13 +55,13 @@ void SetPeer (Ipv4Address address, uint16_t port); // Called from socket implementations to get notified about important events. - void SetRxCallback (Callback, Ipv4Address, uint16_t> callback); + void SetRxCallback (Callback, Ipv4Address, Ipv4Address, uint16_t> callback); void SetIcmpCallback (Callback callback); void SetDestroyCallback (Callback callback); // Called from an L4Protocol implementation to notify an endpoint of a // packet reception. - void ForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport); + void ForwardUp (Ptr p, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport); // Called from an L4Protocol implementation to notify an endpoint of // an icmp message reception. void ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, @@ -69,7 +69,7 @@ uint32_t icmpInfo); private: - void DoForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport); + void DoForwardUp (Ptr p, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport); void DoForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo); @@ -77,7 +77,7 @@ uint16_t m_localPort; Ipv4Address m_peerAddr; uint16_t m_peerPort; - Callback, Ipv4Address, uint16_t> m_rxCallback; + Callback, Ipv4Address, Ipv4Address, uint16_t> m_rxCallback; Callback m_icmpCallback; Callback m_destroyCallback; }; diff -r 547ae5e7d3d0 -r 28d8e04ab790 src/internet-stack/tcp-l4-protocol.cc --- a/src/internet-stack/tcp-l4-protocol.cc Thu Nov 19 14:57:17 2009 +0100 +++ b/src/internet-stack/tcp-l4-protocol.cc Mon Nov 23 11:16:45 2009 +0100 @@ -542,7 +542,7 @@ } NS_ASSERT_MSG (endPoints.size() == 1 , "Demux returned more than one endpoint"); NS_LOG_LOGIC ("TcpL4Protocol "<ForwardUp (packet, source, tcpHeader.GetSourcePort ()); + (*endPoints.begin ())->ForwardUp (packet, source, destination, tcpHeader.GetSourcePort ()); return Ipv4L4Protocol::RX_OK; } diff -r 547ae5e7d3d0 -r 28d8e04ab790 src/internet-stack/tcp-socket-impl.cc --- a/src/internet-stack/tcp-socket-impl.cc Thu Nov 19 14:57:17 2009 +0100 +++ b/src/internet-stack/tcp-socket-impl.cc Mon Nov 23 11:16:45 2009 +0100 @@ -68,8 +68,6 @@ m_endPoint (0), m_node (0), m_tcp (0), - m_localAddress (Ipv4Address::GetZero ()), - m_localPort (0), m_errno (ERROR_NOTERROR), m_shutdownSend (false), m_shutdownRecv (false), @@ -107,10 +105,6 @@ m_endPoint (0), m_node (sock.m_node), m_tcp (sock.m_tcp), - m_remoteAddress (sock.m_remoteAddress), - m_remotePort (sock.m_remotePort), - m_localAddress (sock.m_localAddress), - m_localPort (sock.m_localPort), m_errno (sock.m_errno), m_shutdownSend (sock.m_shutdownSend), m_shutdownRecv (sock.m_shutdownRecv), @@ -264,8 +258,6 @@ } m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr(this))); m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr(this))); - m_localAddress = m_endPoint->GetLocalAddress (); - m_localPort = m_endPoint->GetLocalPort (); return 0; } @@ -375,13 +367,12 @@ NS_ASSERT (m_endPoint != 0); } InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - m_remoteAddress = transport.GetIpv4 (); - m_remotePort = transport.GetPort (); + m_endPoint->SetPeer(transport.GetIpv4 (), transport.GetPort ()); if (ipv4->GetRoutingProtocol () != 0) { Ipv4Header header; - header.SetDestination (m_remoteAddress); + header.SetDestination (m_endPoint->GetPeerAddress()); Socket::SocketErrno errno_; Ptr route; uint32_t oif = 0; //specify non-zero if bound to a source address @@ -394,7 +385,7 @@ } else { - NS_LOG_LOGIC ("TcpSocketImpl::Connect(): Route to " << m_remoteAddress << " does not exist"); + NS_LOG_LOGIC ("TcpSocketImpl::Connect(): Route to " << m_endPoint->GetPeerAddress() << " does not exist"); NS_LOG_ERROR (errno_); m_errno = errno_; return -1; @@ -600,7 +591,7 @@ } } SocketAddressTag tag; - tag.SetAddress (InetSocketAddress (m_remoteAddress, m_remotePort)); + tag.SetAddress (InetSocketAddress (m_endPoint->GetPeerAddress(), m_endPoint->GetPeerPort())); outPacket->AddPacketTag (tag); return outPacket; } @@ -636,12 +627,12 @@ TcpSocketImpl::GetSockName (Address &address) const { NS_LOG_FUNCTION_NOARGS (); - address = InetSocketAddress(m_localAddress, m_localPort); + address = InetSocketAddress(m_endPoint->GetLocalAddress(), m_endPoint->GetLocalPort()); return 0; } void -TcpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) +TcpSocketImpl::ForwardUp (Ptr packet, Ipv4Address saddr, Ipv4Address daddr, uint16_t port) { NS_LOG_DEBUG("Socket " << this << " got forward up" << " dport " << m_endPoint->GetLocalPort() << @@ -649,7 +640,11 @@ " sport " << m_endPoint->GetPeerPort() << " saddr " << m_endPoint->GetPeerAddress()); - NS_LOG_FUNCTION (this << packet << ipv4 << port); + NS_LOG_FUNCTION (this << packet << saddr << daddr << port); + + Address fromAddress = InetSocketAddress (saddr, port); + Address toAddress = InetSocketAddress (daddr, m_endPoint->GetLocalPort()); + if (m_shutdownRecv) { return; @@ -675,11 +670,10 @@ Events_t event = SimulationSingleton::Get ()->FlagsEvent (tcpHeader.GetFlags () ); Actions_t action = ProcessEvent (event); //updates the state - Address address = InetSocketAddress (ipv4, port); NS_LOG_DEBUG("Socket " << this << " processing pkt action, " << action << " current state " << m_state); - ProcessPacketAction (action, packet, tcpHeader, address); + ProcessPacketAction (action, packet, tcpHeader, fromAddress, toAddress); } Actions_t TcpSocketImpl::ProcessEvent (Events_t e) @@ -708,7 +702,6 @@ { Simulator::ScheduleNow(&TcpSocketImpl::ConnectionSucceeded, this); m_connected = true; - m_endPoint->SetPeer (m_remoteAddress, m_remotePort); NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!"); } if (saveState < CLOSING && (m_state == CLOSING || m_state == TIMED_WAIT) ) @@ -768,10 +761,10 @@ header.SetSequenceNumber (m_nextTxSequence); header.SetAckNumber (m_nextRxSequence); header.SetSourcePort (m_endPoint->GetLocalPort ()); - header.SetDestinationPort (m_remotePort); + header.SetDestinationPort (m_endPoint->GetPeerPort()); header.SetWindowSize (AdvertisedWindowSize()); m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), - m_remoteAddress); + m_endPoint->GetPeerAddress()); Time rto = m_rtt->RetransmitTimeout (); bool hasSyn = flags & TcpHeader::SYN; bool hasFin = flags & TcpHeader::FIN; @@ -882,7 +875,8 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, const TcpHeader& tcpHeader, - const Address& fromAddress) + const Address& fromAddress, + const Address& toAddress) { NS_LOG_FUNCTION (this << a << p << fromAddress); Ptr ipv4 = m_node->GetObject (); @@ -916,40 +910,16 @@ NS_LOG_LOGIC ("Cloned a TcpSocketImpl " << newSock); //this listening socket should do nothing more Simulator::ScheduleNow (&TcpSocketImpl::CompleteFork, newSock, - p, tcpHeader,fromAddress); + p, tcpHeader,fromAddress, toAddress); return true; } - // This is the cloned endpoint - m_endPoint->SetPeer (m_remoteAddress, m_remotePort); + else + {// This is the cloned endpoint + // TCP SYN consumes one byte + m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1); + SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); + } - // Look up the source address - if (ipv4->GetRoutingProtocol () != 0) - { - Ipv4Header header; - Socket::SocketErrno errno_; - Ptr route; - uint32_t oif = 0; //specify non-zero if bound to a source address - header.SetDestination (m_remoteAddress); - route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr (), header, oif, errno_); - if (route != 0) - { - NS_LOG_LOGIC ("Route exists"); - m_endPoint->SetLocalAddress (route->GetSource ()); - } - else - { - NS_LOG_ERROR (errno_); - m_errno = errno_; - return -1; - } - } - else - { - NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node"); - } - // TCP SYN consumes one byte - m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1); - SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); break; case ACK_TX_1: NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action ACK_TX_1"); @@ -982,7 +952,8 @@ NEW_SEQ_RX, p, tcpHeader, - fromAddress); + fromAddress, + toAddress); } if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing { @@ -1006,7 +977,7 @@ break; case NEW_SEQ_RX: NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action NEW_SEQ_RX"); - NewRx (p, tcpHeader, fromAddress); // Process new data received + NewRx (p, tcpHeader, fromAddress, toAddress); // Process new data received break; case PEER_CLOSE: { @@ -1020,14 +991,14 @@ NS_LOG_LOGIC ("TcpSocketImpl " << this << " setting pendingClose" << " rxseq " << tcpHeader.GetSequenceNumber () << " nextRxSeq " << m_nextRxSequence); - NewRx (p, tcpHeader, fromAddress); + NewRx (p, tcpHeader, fromAddress, toAddress); return true; } // Now we need to see if any data came with the FIN // if so, call NewRx if (p->GetSize () != 0) { - NewRx (p, tcpHeader, fromAddress); + NewRx (p, tcpHeader, fromAddress, toAddress); } ++m_nextRxSequence; //bump this to account for the FIN States_t saveState = m_state; // Used to see if app responds @@ -1059,7 +1030,7 @@ NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SERV_NOTIFY"); NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!"); m_connected = true; // ! This is bogus; fix when we clone the tcp - m_endPoint->SetPeer (m_remoteAddress, m_remotePort); + m_endPoint->SetPeer (m_endPoint->GetPeerAddress(), m_endPoint->GetPeerPort()); //treat the connection orientation final ack as a newack CommonNewAck (tcpHeader.GetAckNumber (), true); NotifyNewConnectionCreated (this, fromAddress); @@ -1070,21 +1041,19 @@ return true; } -void TcpSocketImpl::CompleteFork(Ptr p, const TcpHeader& h, const Address& fromAddress) +void TcpSocketImpl::CompleteFork(Ptr p, const TcpHeader& h, const Address& fromAddress, const Address& toAddress) { // Get port and address from peer (connecting host) - m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort (); - m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (); - m_endPoint = m_tcp->Allocate (m_localAddress, - m_localPort, - m_remoteAddress, - m_remotePort); + m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom(toAddress).GetIpv4 (), + InetSocketAddress::ConvertFrom(toAddress).GetPort (), + InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (), + InetSocketAddress::ConvertFrom (fromAddress).GetPort ()); //the cloned socket with be in listen state, so manually change state m_state = SYN_RCVD; //equivalent to FinishBind m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr(this))); m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr(this))); - ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress); + ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress, toAddress); } void TcpSocketImpl::ConnectionSucceeded() @@ -1146,7 +1115,7 @@ header.SetSequenceNumber (m_nextTxSequence); header.SetAckNumber (m_nextRxSequence); header.SetSourcePort (m_endPoint->GetLocalPort()); - header.SetDestinationPort (m_remotePort); + header.SetDestinationPort (m_endPoint->GetPeerPort()); header.SetWindowSize (AdvertisedWindowSize()); if (m_shutdownSend) { @@ -1166,7 +1135,7 @@ NS_LOG_LOGIC ("About to send a packet with flags: " << flags); m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), - m_remoteAddress); + m_endPoint->GetPeerAddress()); m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT // Notify the application of the data being sent Simulator::ScheduleNow(&TcpSocketImpl::NotifyDataSent, this, sz); @@ -1224,7 +1193,8 @@ void TcpSocketImpl::NewRx (Ptr p, const TcpHeader& tcpHeader, - const Address& fromAddress) + const Address& fromAddress, + const Address& toAddress) { NS_LOG_FUNCTION (this << p << "tcpHeader " << fromAddress); NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewRx," @@ -1291,7 +1261,7 @@ { // See if we can close now if (m_bufferedData.empty()) { - ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress); + ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress, toAddress); } } } @@ -1608,11 +1578,11 @@ tcpHeader.SetSequenceNumber (m_nextTxSequence); tcpHeader.SetAckNumber (m_nextRxSequence); tcpHeader.SetSourcePort (m_endPoint->GetLocalPort()); - tcpHeader.SetDestinationPort (m_remotePort); + tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort()); tcpHeader.SetWindowSize (AdvertisedWindowSize()); m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (), - m_remoteAddress); + m_endPoint->GetPeerAddress()); NS_LOG_LOGIC ("Schedule persist timeout at time " <GetLocalPort()); - tcpHeader.SetDestinationPort (m_remotePort); + tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort()); tcpHeader.SetFlags (flags); tcpHeader.SetWindowSize (AdvertisedWindowSize()); m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (), - m_remoteAddress); + m_endPoint->GetPeerAddress()); } void diff -r 547ae5e7d3d0 -r 28d8e04ab790 src/internet-stack/tcp-socket-impl.h --- a/src/internet-stack/tcp-socket-impl.h Thu Nov 19 14:57:17 2009 +0100 +++ b/src/internet-stack/tcp-socket-impl.h Mon Nov 23 11:16:45 2009 +0100 @@ -100,7 +100,7 @@ friend class Tcp; // invoked by Tcp class int FinishBind (void); - void ForwardUp (Ptr p, Ipv4Address ipv4, uint16_t port); + void ForwardUp (Ptr p, Ipv4Address saddr, Ipv4Address daddr, uint16_t port); void Destroy (void); int DoSendTo (Ptr p, const Address &daddr); int DoSendTo (Ptr p, Ipv4Address daddr, uint16_t dport); @@ -113,10 +113,11 @@ Ipv4Address saddr, Ipv4Address daddr); bool ProcessPacketAction (Actions_t a, Ptr p, const TcpHeader& tcpHeader, - const Address& fromAddress); + const Address& fromAddress, + const Address& toAddress); Actions_t ProcessEvent (Events_t e); bool SendPendingData(bool withAck = false); - void CompleteFork(Ptr, const TcpHeader&, const Address& fromAddress); + void CompleteFork(Ptr, const TcpHeader&, const Address& fromAddress, const Address& toAddress); void ConnectionSucceeded(); //methods for window management @@ -130,7 +131,7 @@ uint16_t AdvertisedWindowSize(); // Manage data tx/rx - void NewRx (Ptr, const TcpHeader&, const Address&); + void NewRx (Ptr, const TcpHeader&, const Address& fromAddress, const Address& toAddress); void RxBufFinishInsert (SequenceNumber); Ptr Copy (); virtual void NewAck (SequenceNumber seq); @@ -177,11 +178,7 @@ Ipv4EndPoint *m_endPoint; Ptr m_node; Ptr m_tcp; - Ipv4Address m_remoteAddress; - uint16_t m_remotePort; - //these two are so that the socket/endpoint cloning works - Ipv4Address m_localAddress; - uint16_t m_localPort; + enum SocketErrno m_errno; bool m_shutdownSend; bool m_shutdownRecv; diff -r 547ae5e7d3d0 -r 28d8e04ab790 src/internet-stack/udp-l4-protocol.cc --- a/src/internet-stack/udp-l4-protocol.cc Thu Nov 19 14:57:17 2009 +0100 +++ b/src/internet-stack/udp-l4-protocol.cc Mon Nov 23 11:16:45 2009 +0100 @@ -230,7 +230,7 @@ for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin (); endPoint != endPoints.end (); endPoint++) { - (*endPoint)->ForwardUp (packet->Copy (), source, udpHeader.GetSourcePort ()); + (*endPoint)->ForwardUp (packet->Copy (), source, destination, udpHeader.GetSourcePort ()); } return Ipv4L4Protocol::RX_OK; } diff -r 547ae5e7d3d0 -r 28d8e04ab790 src/internet-stack/udp-socket-impl.cc --- a/src/internet-stack/udp-socket-impl.cc Thu Nov 19 14:57:17 2009 +0100 +++ b/src/internet-stack/udp-socket-impl.cc Mon Nov 23 11:16:45 2009 +0100 @@ -556,9 +556,9 @@ } void -UdpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) +UdpSocketImpl::ForwardUp (Ptr packet, Ipv4Address saddr, Ipv4Address daddr, uint16_t port) { - NS_LOG_FUNCTION (this << packet << ipv4 << port); + NS_LOG_FUNCTION (this << packet << saddr << daddr << port); if (m_shutdownRecv) { @@ -566,7 +566,7 @@ } if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize) { - Address address = InetSocketAddress (ipv4, port); + Address address = InetSocketAddress (saddr, port); SocketAddressTag tag; tag.SetAddress (address); packet->AddPacketTag (tag); diff -r 547ae5e7d3d0 -r 28d8e04ab790 src/internet-stack/udp-socket-impl.h --- a/src/internet-stack/udp-socket-impl.h Thu Nov 19 14:57:17 2009 +0100 +++ b/src/internet-stack/udp-socket-impl.h Mon Nov 23 11:16:45 2009 +0100 @@ -97,7 +97,7 @@ friend class UdpSocketFactory; // invoked by Udp class int FinishBind (void); - void ForwardUp (Ptr p, Ipv4Address ipv4, uint16_t port); + void ForwardUp (Ptr p, Ipv4Address saddr, Ipv4Address daddr, uint16_t port); void Destroy (void); int DoSend (Ptr p); int DoSendTo (Ptr p, const Address &daddr);