From 0b49c1266071d35f4350bf00fcc7a8d22594dfaf Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Thu, 4 Feb 2010 14:10:13 -0500 Subject: [PATCH 1/8] Bug 748 - Cloned TCP socket uses wrong source address --- src/internet-stack/ipv4-end-point.cc | 10 +- src/internet-stack/ipv4-end-point.h | 8 +- src/internet-stack/nsc-tcp-l4-protocol.cc | 2 +- src/internet-stack/nsc-tcp-socket-impl.cc | 2 +- src/internet-stack/nsc-tcp-socket-impl.h | 2 +- src/internet-stack/tcp-l4-protocol.cc | 2 +- src/internet-stack/tcp-socket-impl.cc | 122 +++++++++------------- src/internet-stack/tcp-socket-impl.h | 15 ++- src/internet-stack/udp-l4-protocol.cc | 2 +- src/internet-stack/udp-socket-impl.cc | 6 +- src/internet-stack/udp-socket-impl.h | 2 +- 11 files changed, 72 insertions(+), 101 deletions(-) diff --git a/src/internet-stack/ipv4-end-point.cc b/src/internet-stack/ipv4-end-point.cc index 86b78fe42..3b3db1221 100644 --- a/src/internet-stack/ipv4-end-point.cc +++ b/src/internet-stack/ipv4-end-point.cc @@ -89,7 +89,7 @@ Ipv4EndPoint::GetBoundNetDevice (void) } void -Ipv4EndPoint::SetRxCallback (Callback, Ipv4Address, uint16_t> callback) +Ipv4EndPoint::SetRxCallback (Callback, Ipv4Address, Ipv4Address, uint16_t> callback) { m_rxCallback = callback; } @@ -106,17 +106,17 @@ Ipv4EndPoint::SetDestroyCallback (Callback callback) } 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 --git a/src/internet-stack/ipv4-end-point.h b/src/internet-stack/ipv4-end-point.h index ccdc1d573..8754de203 100644 --- a/src/internet-stack/ipv4-end-point.h +++ b/src/internet-stack/ipv4-end-point.h @@ -59,13 +59,13 @@ public: Ptr GetBoundNetDevice (void); // 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, @@ -73,7 +73,7 @@ public: 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); @@ -82,7 +82,7 @@ private: Ipv4Address m_peerAddr; uint16_t m_peerPort; Ptr m_boundnetdevice; - Callback, Ipv4Address, uint16_t> m_rxCallback; + Callback, Ipv4Address, Ipv4Address, uint16_t> m_rxCallback; Callback m_icmpCallback; Callback m_destroyCallback; }; diff --git a/src/internet-stack/nsc-tcp-l4-protocol.cc b/src/internet-stack/nsc-tcp-l4-protocol.cc index 83172e61c..621262286 100644 --- a/src/internet-stack/nsc-tcp-l4-protocol.cc +++ b/src/internet-stack/nsc-tcp-l4-protocol.cc @@ -382,7 +382,7 @@ void NscTcpL4Protocol::wakeup() for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin (); endPoint != endPoints.end (); endPoint++) { // NSC HACK: (ab)use TcpSocket::ForwardUp for signalling - (*endPoint)->ForwardUp (NULL, Ipv4Address(), 0); + (*endPoint)->ForwardUp (NULL, Ipv4Address(), Ipv4Address(), 0); } } diff --git a/src/internet-stack/nsc-tcp-socket-impl.cc b/src/internet-stack/nsc-tcp-socket-impl.cc index ec66493ab..b947c870b 100644 --- a/src/internet-stack/nsc-tcp-socket-impl.cc +++ b/src/internet-stack/nsc-tcp-socket-impl.cc @@ -465,7 +465,7 @@ NscTcpSocketImpl::GetRxAvailable (void) const } void -NscTcpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) +NscTcpSocketImpl::ForwardUp (Ptr packet, Ipv4Address saddr, Ipv4Address daddr, uint16_t port) { NSCWakeup(); } diff --git a/src/internet-stack/nsc-tcp-socket-impl.h b/src/internet-stack/nsc-tcp-socket-impl.h index 8269dc35f..9295084ad 100644 --- a/src/internet-stack/nsc-tcp-socket-impl.h +++ b/src/internet-stack/nsc-tcp-socket-impl.h @@ -88,7 +88,7 @@ private: 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); //methods for state bool SendPendingData(void); diff --git a/src/internet-stack/tcp-l4-protocol.cc b/src/internet-stack/tcp-l4-protocol.cc index a28eca482..d361a8604 100644 --- a/src/internet-stack/tcp-l4-protocol.cc +++ b/src/internet-stack/tcp-l4-protocol.cc @@ -546,7 +546,7 @@ TcpL4Protocol::Receive (Ptr packet, } 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 --git a/src/internet-stack/tcp-socket-impl.cc b/src/internet-stack/tcp-socket-impl.cc index 28ae5958c..cc0e9065e 100644 --- a/src/internet-stack/tcp-socket-impl.cc +++ b/src/internet-stack/tcp-socket-impl.cc @@ -70,8 +70,6 @@ TcpSocketImpl::GetTypeId () 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), @@ -109,10 +107,6 @@ TcpSocketImpl::TcpSocketImpl(const TcpSocketImpl& sock) 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), @@ -266,8 +260,6 @@ TcpSocketImpl::FinishBind (void) } 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; } @@ -377,13 +369,12 @@ TcpSocketImpl::Connect (const Address & address) 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; Ptr oif = m_boundnetdevice; //specify non-zero if bound to a source address @@ -396,7 +387,7 @@ TcpSocketImpl::Connect (const Address & address) } 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; @@ -602,7 +593,7 @@ TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) } } SocketAddressTag tag; - tag.SetAddress (InetSocketAddress (m_remoteAddress, m_remotePort)); + tag.SetAddress (InetSocketAddress (m_endPoint->GetPeerAddress(), m_endPoint->GetPeerPort())); outPacket->AddPacketTag (tag); return outPacket; } @@ -638,7 +629,8 @@ int 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; } @@ -661,7 +653,7 @@ TcpSocketImpl::BindToNetDevice (Ptr netdevice) } 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() << @@ -669,7 +661,11 @@ TcpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) " 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; @@ -695,11 +691,10 @@ TcpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) 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) @@ -727,7 +722,6 @@ Actions_t TcpSocketImpl::ProcessEvent (Events_t e) { 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) ) @@ -787,10 +781,10 @@ void TcpSocketImpl::SendEmptyPacket (uint8_t flags) 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_boundnetdevice); + m_endPoint->GetPeerAddress (), m_boundnetdevice); Time rto = m_rtt->RetransmitTimeout (); bool hasSyn = flags & TcpHeader::SYN; bool hasFin = flags & TcpHeader::FIN; @@ -901,7 +895,8 @@ bool TcpSocketImpl::ProcessAction (Actions_t a) 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 (); @@ -935,40 +930,18 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, 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; - Ptr oif = m_boundnetdevice; //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"); @@ -1001,7 +974,8 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, NEW_SEQ_RX, p, tcpHeader, - fromAddress); + fromAddress, + toAddress); } if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing { @@ -1025,7 +999,7 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, 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: { @@ -1039,14 +1013,14 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, 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 @@ -1078,7 +1052,7 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, 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); @@ -1089,21 +1063,19 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, 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() @@ -1165,7 +1137,7 @@ bool TcpSocketImpl::SendPendingData (bool withAck) 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) { @@ -1185,7 +1157,8 @@ bool TcpSocketImpl::SendPendingData (bool withAck) NS_LOG_LOGIC ("About to send a packet with flags: " << flags); m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), - m_remoteAddress, m_boundnetdevice); + m_endPoint->GetPeerAddress (), + m_boundnetdevice); m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT // Notify the application of the data being sent Simulator::ScheduleNow(&TcpSocketImpl::NotifyDataSent, this, sz); @@ -1243,7 +1216,8 @@ uint16_t TcpSocketImpl::AdvertisedWindowSize() 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," @@ -1310,7 +1284,7 @@ void TcpSocketImpl::NewRx (Ptr p, { // See if we can close now if (m_bufferedData.empty()) { - ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress); + ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress, toAddress); } } } @@ -1627,11 +1601,11 @@ void TcpSocketImpl::PersistTimeout () 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_boundnetdevice); + m_endPoint->GetPeerAddress (), m_boundnetdevice); 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_boundnetdevice); + m_endPoint->GetPeerAddress (), m_boundnetdevice); } void diff --git a/src/internet-stack/tcp-socket-impl.h b/src/internet-stack/tcp-socket-impl.h index 3acb0c8f0..a778ce3e7 100644 --- a/src/internet-stack/tcp-socket-impl.h +++ b/src/internet-stack/tcp-socket-impl.h @@ -101,7 +101,7 @@ private: 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); @@ -114,10 +114,11 @@ private: 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 @@ -131,7 +132,7 @@ private: 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); @@ -178,11 +179,7 @@ private: 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 --git a/src/internet-stack/udp-l4-protocol.cc b/src/internet-stack/udp-l4-protocol.cc index 972e3c9bf..f9185cf1c 100644 --- a/src/internet-stack/udp-l4-protocol.cc +++ b/src/internet-stack/udp-l4-protocol.cc @@ -230,7 +230,7 @@ UdpL4Protocol::Receive(Ptr packet, 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 --git a/src/internet-stack/udp-socket-impl.cc b/src/internet-stack/udp-socket-impl.cc index 216b014ed..f2c015957 100644 --- a/src/internet-stack/udp-socket-impl.cc +++ b/src/internet-stack/udp-socket-impl.cc @@ -583,9 +583,9 @@ UdpSocketImpl::BindToNetDevice (Ptr netdevice) } 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) { @@ -593,7 +593,7 @@ UdpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) } 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 --git a/src/internet-stack/udp-socket-impl.h b/src/internet-stack/udp-socket-impl.h index 174f19a33..0b03b24a1 100644 --- a/src/internet-stack/udp-socket-impl.h +++ b/src/internet-stack/udp-socket-impl.h @@ -98,7 +98,7 @@ private: 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); From f98c26ce467a56794e7434a6044141f657ec195d Mon Sep 17 00:00:00 2001 From: "tomhewer@blackbook.local" Date: Fri, 5 Feb 2010 11:39:16 +0000 Subject: [PATCH 2/8] addition of two ray ground model and tests --- .../propagation-loss-model-test-suite.cc | 133 ++++++++++++++ src/common/propagation-loss-model.cc | 171 ++++++++++++++++++ src/common/propagation-loss-model.h | 90 +++++++++ 3 files changed, 394 insertions(+) diff --git a/src/common/propagation-loss-model-test-suite.cc b/src/common/propagation-loss-model-test-suite.cc index 2e3a40a0b..f40840451 100644 --- a/src/common/propagation-loss-model-test-suite.cc +++ b/src/common/propagation-loss-model-test-suite.cc @@ -145,6 +145,138 @@ FriisPropagationLossModelTestCase::DoRun (void) return GetErrorStatus (); } +// Added for Two-Ray Ground Model - tomhewer@mac.com + +class TwoRayGroundPropagationLossModelTestCase : public TestCase +{ +public: + TwoRayGroundPropagationLossModelTestCase (); + virtual ~TwoRayGroundPropagationLossModelTestCase (); + +private: + virtual bool DoRun (void); + + typedef struct + { + Vector m_position; + double m_pt; // dBm + double m_pr; // W + double m_tolerance; + } TestVector; + + TestVectors m_testVectors; +}; + +TwoRayGroundPropagationLossModelTestCase::TwoRayGroundPropagationLossModelTestCase () +: TestCase ("Check to see that the ns-3 TwoRayGround propagation loss model provides correct received power"), +m_testVectors () +{ +} + +TwoRayGroundPropagationLossModelTestCase::~TwoRayGroundPropagationLossModelTestCase () +{ +} + +bool +TwoRayGroundPropagationLossModelTestCase::DoRun (void) +{ + // wavelength at 2.4 GHz is 0.125m + Config::SetDefault ("ns3::TwoRayGroundPropagationLossModel::Lambda", DoubleValue (0.125)); + Config::SetDefault ("ns3::TwoRayGroundPropagationLossModel::SystemLoss", DoubleValue (1.0)); + + // set antenna height to 1.5m above z coordinate + Config::SetDefault ("ns3::TwoRayGroundPropagationLossModel::HeightAboveZ", DoubleValue (1.5)); + + // Select a reference transmit power of 17.0206 dBm + // Pt = 10^(17.0206/10)/10^3 = .05035702 W + double txPowerW = 0.05035702; + double txPowerdBm = 10 * log10 (txPowerW) + 30; + + // + // As with the Friis tests above, we want to test the propagation loss + // model calculations at a few chosen distances and compare the results + // to those we can manually calculate. Let us test the ns-3 calculated + // value for agreement to be within 5e-16, as above. + // + TestVector testVector; + + // Below the Crossover distance use Friis so this test should be the same as that above + // Crossover = (4 * PI * TxAntennaHeight * RxAntennaHeight) / Lamdba + // Crossover = (4 * PI * 1.5 * 1.5) / 0.125 = 226.1946m + + testVector.m_position = Vector (100, 0, 0); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 4.98265e-10; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + // These values are above the crossover distance and therefore use the Two Ray calculation + + testVector.m_position = Vector (500, 0, 0); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 4.07891862e-12; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + testVector.m_position = Vector (1000, 0, 0); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 2.5493241375e-13; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + testVector.m_position = Vector (2000, 0, 0); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 1.593327585938e-14; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + // Repeat the tests for non-zero z coordinates + + // Pr = (0.05035702 * (1.5*1.5) * (2.5*2.5)) / (500*500*500*500) = 1.13303295e-11 + // dCross = (4 * pi * 1.5 * 2.5) / 0.125 = 376.99m + testVector.m_position = Vector (500, 0, 1); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 1.13303295e-11; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + // Pr = (0.05035702 * (1.5*1.5) * (5.5*5.5)) / (1000*1000*1000*1000) = 3.42742467375e-12 + // dCross = (4 * pi * 1.5 * 5.5) / 0.125 = 829.38m + testVector.m_position = Vector (1000, 0, 4); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 3.42742467375e-12; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + // Pr = (0.05035702 * (1.5*1.5) * (11.5*11.5)) / (2000*2000*2000*2000) = 9.36522547734e-13 + // dCross = (4 * pi * 1.5 * 11.5) / 0.125 = 1734.15m + testVector.m_position = Vector (2000, 0, 10); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 9.36522547734e-13; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + + // Now, check that the received power values are expected + + Ptr a = CreateObject (); + a->SetPosition (Vector (0,0,0)); + Ptr b = CreateObject (); + + Ptr lossModel = CreateObject (); + for (uint32_t i = 0; i < m_testVectors.GetN (); ++i) + { + testVector = m_testVectors.Get (i); + b->SetPosition (testVector.m_position); + double resultdBm = lossModel->CalcRxPower (testVector.m_pt, a, b); + double resultW = pow (10.0, resultdBm / 10.0) / 1000; + NS_TEST_EXPECT_MSG_EQ_TOL (resultW, testVector.m_pr, testVector.m_tolerance, "Got unexpected rcv power"); + } + + return GetErrorStatus (); +} + + class LogDistancePropagationLossModelTestCase : public TestCase { public: @@ -244,6 +376,7 @@ PropagationLossModelsTestSuite::PropagationLossModelsTestSuite () : TestSuite ("propagation-loss-model", UNIT) { AddTestCase (new FriisPropagationLossModelTestCase); + AddTestCase (new TwoRayGroundPropagationLossModelTestCase); AddTestCase (new LogDistancePropagationLossModelTestCase); } diff --git a/src/common/propagation-loss-model.cc b/src/common/propagation-loss-model.cc index 0bf4d59b1..0b4f5ca3f 100644 --- a/src/common/propagation-loss-model.cc +++ b/src/common/propagation-loss-model.cc @@ -17,6 +17,7 @@ * * Author: Mathieu Lacage * Contributions: Timo Bingmann + * Contributions: Tom Hewer for Two Ray Ground Model */ #include "propagation-loss-model.h" @@ -232,6 +233,176 @@ FriisPropagationLossModel::DoCalcRxPower (double txPowerDbm, return txPowerDbm + pr; } +// ------------------------------------------------------------------------- // +// -- Two-Ray Ground Model ported from NS-2 -- tomhewer@mac.com -- Nov09 // + +NS_OBJECT_ENSURE_REGISTERED (TwoRayGroundPropagationLossModel); + +const double TwoRayGroundPropagationLossModel::PI = 3.14159265358979323846; + +TypeId +TwoRayGroundPropagationLossModel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::TwoRayGroundPropagationLossModel") + .SetParent () + .AddConstructor () + .AddAttribute ("Lambda", + "The wavelength (default is 5.15 GHz at 300 000 km/s).", + DoubleValue (300000000.0 / 5.150e9), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::m_lambda), + MakeDoubleChecker ()) + .AddAttribute ("SystemLoss", "The system loss", + DoubleValue (1.0), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::m_systemLoss), + MakeDoubleChecker ()) + .AddAttribute ("MinDistance", + "The distance under which the propagation model refuses to give results (m)", + DoubleValue (0.5), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::SetMinDistance, + &TwoRayGroundPropagationLossModel::GetMinDistance), + MakeDoubleChecker ()) + .AddAttribute ("HeightAboveZ", + "The height of the antenna (m) above the node's Z coordinate", + DoubleValue (0), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::m_heightAboveZ), + MakeDoubleChecker ()) + ; + return tid; +} + +TwoRayGroundPropagationLossModel::TwoRayGroundPropagationLossModel () +{ +} +void +TwoRayGroundPropagationLossModel::SetSystemLoss (double systemLoss) +{ + m_systemLoss = systemLoss; +} +double +TwoRayGroundPropagationLossModel::GetSystemLoss (void) const +{ + return m_systemLoss; +} +void +TwoRayGroundPropagationLossModel::SetMinDistance (double minDistance) +{ + m_minDistance = minDistance; +} +double +TwoRayGroundPropagationLossModel::GetMinDistance (void) const +{ + return m_minDistance; +} +void +TwoRayGroundPropagationLossModel::SetHeightAboveZ (double heightAboveZ) +{ + m_heightAboveZ = heightAboveZ; +} +void +TwoRayGroundPropagationLossModel::SetLambda (double frequency, double speed) +{ + m_lambda = speed / frequency; +} +void +TwoRayGroundPropagationLossModel::SetLambda (double lambda) +{ + m_lambda = lambda; +} +double +TwoRayGroundPropagationLossModel::GetLambda (void) const +{ + return m_lambda; +} + +double +TwoRayGroundPropagationLossModel::DbmToW (double dbm) const +{ + double mw = pow (10.0,dbm / 10.0); + return mw / 1000.0; +} + +double +TwoRayGroundPropagationLossModel::DbmFromW (double w) const +{ + double dbm = log10 (w * 1000.0) * 10.0; + return dbm; +} + +double +TwoRayGroundPropagationLossModel::DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const +{ + /* + * Two-Ray Ground equation: + * + * where Pt, Gt and Gr are in dBm units + * L, Ht and Hr are in meter units. + * + * Pr Gt * Gr * (Ht^2 * Hr^2) + * -- = (-------------------------) + * Pt d^4 * L + * + * Gt: tx gain (unit-less) + * Gr: rx gain (unit-less) + * Pt: tx power (dBm) + * d: distance (m) + * L: system loss + * Ht: Tx antenna height (m) + * Hr: Rx antenna height (m) + * lambda: wavelength (m) + * + * As with the Friis model we ignore tx and rx gain and output values + * are in dB or dBm + * + * (Ht * Ht) * (Hr * Hr) + * rx = tx + 10 log10 (-----------------------) + * (d * d * d * d) * L + */ + double distance = a->GetDistanceFrom (b); + if (distance <= m_minDistance) + { + return txPowerDbm; + } + + // Set the height of the Tx and Rx antennae + double txAntHeight = a->GetPosition ().z + m_heightAboveZ; + double rxAntHeight = b->GetPosition ().z + m_heightAboveZ; + + // Calculate a crossover distance, under which we use Friis + /* + * + * dCross = (4 * pi * Ht * Hr) / lambda + * + */ + + double dCross = (4 * PI * txAntHeight * rxAntHeight) / GetLambda (); + double tmp = 0; + if (distance <= dCross) + { + // We use Friis + double numerator = m_lambda * m_lambda; + tmp = PI * distance; + double denominator = 16 * tmp * tmp * m_systemLoss; + double pr = 10 * log10 (numerator / denominator); + NS_LOG_DEBUG ("Receiver within crossover (" << dCross << "m) for Two_ray path; using Friis"); + NS_LOG_DEBUG ("distance=" << distance << "m, attenuation coefficient=" << pr << "dB"); + return txPowerDbm + pr; + } + else // Use Two-Ray Pathloss + { + tmp = txAntHeight * rxAntHeight; + double rayNumerator = tmp * tmp; + tmp = distance * distance; + double rayDenominator = tmp * tmp * m_systemLoss; + double rayPr = 10 * log10 (rayNumerator / rayDenominator); + NS_LOG_DEBUG ("distance=" << distance << "m, attenuation coefficient=" << rayPr << "dB"); + return txPowerDbm + rayPr; + + } +} + + // ------------------------------------------------------------------------- // NS_OBJECT_ENSURE_REGISTERED (LogDistancePropagationLossModel); diff --git a/src/common/propagation-loss-model.h b/src/common/propagation-loss-model.h index 365bbd702..0814c009f 100644 --- a/src/common/propagation-loss-model.h +++ b/src/common/propagation-loss-model.h @@ -18,6 +18,7 @@ * Author: Mathieu Lacage * Contributions: Timo Bingmann * Contributions: Gary Pei for fixed RSS + * Contributions: Tom Hewer for two ray ground model */ #ifndef PROPAGATION_LOSS_MODEL_H @@ -182,6 +183,95 @@ private: double m_minDistance; }; +/* + * + * \brief a Two-Ray Ground propagation loss model ported from NS2 + * + * Two-ray ground reflection model. + * + * \f$ Pr = \frac{Pt * Gt * Gr * (ht^2 * hr^2)}{d^4 * L} \f$ + * + * The original equation in Rappaport's book assumes L = 1. + * To be consistent with the free space equation, L is added here. + * + * Ht and Hr are set at the respective nodes z coordinate plus a model parameter + * set via SetHeightAboveZ. + * + * The two-ray model does not give a good result for short distances, due to the + * oscillation caused by constructive and destructive combination of the two + * rays. Instead the Friis free-space model is used for small distances. + * + * The crossover distance, below which Friis is used, is calculated as follows: + * + * \f$ dCross = \frac{(4 * pi * Ht * Hr)}{lambda} \f$ + */ + +class TwoRayGroundPropagationLossModel : public PropagationLossModel +{ +public: + static TypeId GetTypeId (void); + TwoRayGroundPropagationLossModel (); + /** + * \param frequency (Hz) + * \param speed (m/s) + * + * Set the main wavelength used in the TwoRayGround model + * calculation. + */ + void SetLambda (double frequency, double speed); + /** + * \param lambda (m) the wavelength + * + * Set the main wavelength used in the TwoRayGround model + * calculation. + */ + void SetLambda (double lambda); + /** + * \param systemLoss (dimension-less) + * + * Set the system loss used by the TwoRayGround propagation model. + */ + void SetSystemLoss (double systemLoss); + /** + * \param minDistance the minimum distance + * + * Below this distance, the txpower is returned + * unmodified as the rxpower. + */ + void SetMinDistance (double minDistance); + /** + * \returns the minimum distance. + */ + double GetMinDistance (void) const; + /** + * \returns the current wavelength (m) + */ + double GetLambda (void) const; + /** + * \returns the current system loss (dimention-less) + */ + double GetSystemLoss (void) const; + /** + * \Set the model antenna height above the node's Z coordinate + */ + void SetHeightAboveZ (double heightAboveZ); + +private: + TwoRayGroundPropagationLossModel (const TwoRayGroundPropagationLossModel &o); + TwoRayGroundPropagationLossModel & operator = (const TwoRayGroundPropagationLossModel &o); + virtual double DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const; + double DbmToW (double dbm) const; + double DbmFromW (double w) const; + + static const double PI; + double m_lambda; + double m_systemLoss; + double m_minDistance; + double m_heightAboveZ; +}; + /** * \brief a log distance propagation model. * From e058907305309d65114027093775dfc0aef5e03a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20M=C3=A4kel=C3=A4?= Date: Thu, 21 Jan 2010 19:57:34 -0800 Subject: [PATCH 3/8] [bug 794] Ipv4Mask constructor for /yy-notation is wrong --- src/node/ipv4-address.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/node/ipv4-address.cc b/src/node/ipv4-address.cc index 02db1da3f..24735291d 100644 --- a/src/node/ipv4-address.cc +++ b/src/node/ipv4-address.cc @@ -72,8 +72,16 @@ Ipv4Mask::Ipv4Mask (char const *mask) { if (*mask == ASCII_SLASH) { - m_mask = static_cast (atoi (++mask)); - NS_ASSERT (m_mask <= 32); + uint32_t plen = static_cast (atoi (++mask)); + NS_ASSERT (plen <= 32); + if (plen > 0) + { + m_mask = 0xffffffff << (32 - plen); + } + else + { + m_mask = 0; + } } else { From df3f2292d25732ce9bd8913fab3549c4ab071cf6 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 8 Jan 2010 15:27:53 -0800 Subject: [PATCH 4/8] bug 731: Send function in point-to-point-net-device fails to check the return value of the Dequeue function --- .../point-to-point-net-device.cc | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/devices/point-to-point/point-to-point-net-device.cc b/src/devices/point-to-point/point-to-point-net-device.cc index 2271cdba1..ce8abbc77 100644 --- a/src/devices/point-to-point/point-to-point-net-device.cc +++ b/src/devices/point-to-point/point-to-point-net-device.cc @@ -511,11 +511,19 @@ PointToPointNetDevice::Send( // Even if the transmitter is immediately available, we still enqueue and // dequeue the packet to hit the tracing hooks. // - m_queue->Enqueue (packet); - packet = m_queue->Dequeue (); - m_snifferTrace (packet); - m_promiscSnifferTrace (packet); - return TransmitStart (packet); + if (m_queue->Enqueue (packet) == true) + { + packet = m_queue->Dequeue (); + m_snifferTrace (packet); + m_promiscSnifferTrace (packet); + return TransmitStart (packet); + } + else + { + // Enqueue may fail (overflow) + m_macTxDropTrace (packet); + return false; + } } else { From 9bdafa8c01a819b2a6d90a3ba41e1c449f438849 Mon Sep 17 00:00:00 2001 From: Craig Dowell Date: Fri, 5 Feb 2010 10:15:18 -0800 Subject: [PATCH 5/8] comparing with http://code.nsnam.org/ns-3-dev searching for changes changeset: 5930:0aaaaf92b988 user: Andrey Mazo date: Fri Jan 29 21:28:04 2010 +0300 files: wscript wutils.py description: Introduce NS3_EXECUTABLE_PATH variable similar to NS3_MODULE_PATH (e.g. may be used for various sock-creators). --- src/devices/emu/emu-net-device.cc | 52 ++-------------------------- src/devices/emu/emu-net-device.h | 5 --- src/devices/emu/wscript | 7 ++++ src/devices/tap-bridge/tap-bridge.cc | 46 +++--------------------- src/devices/tap-bridge/tap-bridge.h | 10 ------ src/devices/tap-bridge/wscript | 7 ++++ wscript | 9 +++-- wutils.py | 5 +++ 8 files changed, 32 insertions(+), 109 deletions(-) diff --git a/src/devices/emu/emu-net-device.cc b/src/devices/emu/emu-net-device.cc index 4764a5e41..d85f9b958 100644 --- a/src/devices/emu/emu-net-device.cc +++ b/src/devices/emu/emu-net-device.cc @@ -444,16 +444,16 @@ EmuNetDevice::CreateSocket (void) // // Execute the socket creation process image. // - status = ::execl (FindCreator ("emu-sock-creator").c_str (), + status = ::execlp ("emu-sock-creator", "emu-sock-creator", // argv[0] (filename) oss.str ().c_str (), // argv[1] (-p::const_iterator i = locations.begin (); i != locations.end (); ++i) - { - struct stat st; - - if (::stat ((*i + creatorName).c_str (), &st) == 0) - { - NS_LOG_INFO ("Found Creator " << *i + creatorName); - return *i + creatorName; - } - } - - NS_FATAL_ERROR ("EmuNetDevice::FindCreator(): Couldn't find creator"); - return ""; // quiet compiler -} - void EmuNetDevice::StopDevice (void) { diff --git a/src/devices/emu/emu-net-device.h b/src/devices/emu/emu-net-device.h index 7ec687e76..e351b86d8 100644 --- a/src/devices/emu/emu-net-device.h +++ b/src/devices/emu/emu-net-device.h @@ -213,11 +213,6 @@ private: */ void CreateSocket (void); - /** - * Figure out where the raw socket creation process lives on the system. - */ - std::string FindCreator (std::string creatorName); - /** * Get a copy of the attached Queue. * diff --git a/src/devices/emu/wscript b/src/devices/emu/wscript index 26089005b..e306b540c 100644 --- a/src/devices/emu/wscript +++ b/src/devices/emu/wscript @@ -1,5 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import os.path + def configure(conf): if conf.env['ENABLE_THREADING']: conf.env['ENABLE_EMU'] = conf.check(header_name='netpacket/packet.h', @@ -12,6 +14,11 @@ def configure(conf): False, "needs threading support which is not available") + if conf.env['ENABLE_EMU']: + blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant())) + emucreatordir = os.path.abspath(os.path.join(blddir, "src/devices/emu")) + conf.env.append_value('NS3_EXECUTABLE_PATH', emucreatordir) + def build(bld): module = bld.create_ns3_module('emu', ['node']) module.source = [ diff --git a/src/devices/tap-bridge/tap-bridge.cc b/src/devices/tap-bridge/tap-bridge.cc index 4d323afe0..5c78e320b 100644 --- a/src/devices/tap-bridge/tap-bridge.cc +++ b/src/devices/tap-bridge/tap-bridge.cc @@ -477,8 +477,8 @@ TapBridge::CreateTap (void) // // Execute the socket creation process image. // - status = ::execl (FindCreator ("tap-creator").c_str (), - FindCreator ("tap-creator").c_str (), // argv[0] (filename) + status = ::execlp ("tap-creator", + "tap-creator", // argv[0] (filename) ossDeviceName.str ().c_str (), // argv[1] (-d) ossGateway.str ().c_str (), // argv[2] (-g) ossIp.str ().c_str (), // argv[3] (-i) @@ -489,10 +489,10 @@ TapBridge::CreateTap (void) (char *)NULL); // - // If the execl successfully completes, it never returns. If it returns it failed or the OS is + // If the execlp successfully completes, it never returns. If it returns it failed or the OS is // broken. In either case, we bail. // - NS_FATAL_ERROR ("TapBridge::CreateTap(): Back from execl(), errno = " << ::strerror (errno)); + NS_FATAL_ERROR ("TapBridge::CreateTap(): Back from execlp(), errno = " << ::strerror (errno)); } else { @@ -614,44 +614,6 @@ TapBridge::CreateTap (void) } } -std::string -TapBridge::FindCreator (std::string creatorName) -{ - NS_LOG_FUNCTION (creatorName); - - std::list locations; - - // The path to the bits if we're sitting in the root of the repo - locations.push_back ("./build/optimized/src/devices/tap-bridge/"); - locations.push_back ("./build/debug/src/devices/tap-bridge/"); - - // if in src - locations.push_back ("../build/optimized/src/devices/tap-bridge/"); - locations.push_back ("../build/debug/src/devices/tap-bridge/"); - - // if in src/devices - locations.push_back ("../../build/optimized/src/devices/tap-bridge/"); - locations.push_back ("../../build/debug/src/devices/tap-bridge/"); - - // if in src/devices/tap-bridge - locations.push_back ("../../../build/optimized/src/devices/tap-bridge/"); - locations.push_back ("../../../build/debug/src/devices/tap-bridge/"); - - for (std::list::const_iterator i = locations.begin (); i != locations.end (); ++i) - { - struct stat st; - - if (::stat ((*i + creatorName).c_str (), &st) == 0) - { - NS_LOG_INFO ("Found Creator " << *i + creatorName); - return *i + creatorName; - } - } - - NS_FATAL_ERROR ("TapBridge::FindCreator(): Couldn't find creator"); - return ""; // quiet compiler -} - void TapBridge::ReadThread (void) { diff --git a/src/devices/tap-bridge/tap-bridge.h b/src/devices/tap-bridge/tap-bridge.h index 69d992db4..44bdf7445 100644 --- a/src/devices/tap-bridge/tap-bridge.h +++ b/src/devices/tap-bridge/tap-bridge.h @@ -231,16 +231,6 @@ private: */ void CreateTap (void); - /** - * \internal - * - * Figure out where the tap creation program lives on the system. - * - * \param creatorName The name of the program used to create the Tap. - * \returns A path name to use when you want to create a Tap. - */ - std::string FindCreator (std::string creatorName); - /** * \internal * diff --git a/src/devices/tap-bridge/wscript b/src/devices/tap-bridge/wscript index 0939c1a98..b7903ce3b 100644 --- a/src/devices/tap-bridge/wscript +++ b/src/devices/tap-bridge/wscript @@ -1,5 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import os.path + def configure(conf): if conf.env['ENABLE_THREADING']: conf.env['ENABLE_TAP'] = conf.check(header_name='linux/if_tun.h', @@ -12,6 +14,11 @@ def configure(conf): False, "needs threading support which is not available") + if conf.env['ENABLE_TAP']: + blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant())) + tapcreatordir = os.path.abspath(os.path.join(blddir, "src/devices/tap-bridge")) + conf.env.append_value('NS3_EXECUTABLE_PATH', tapcreatordir) + def build(bld): module = bld.create_ns3_module('tap-bridge', ['node']) module.source = [ diff --git a/wscript b/wscript index 4d0b5a8e7..6295c6299 100644 --- a/wscript +++ b/wscript @@ -697,12 +697,14 @@ class run_python_unit_tests_task(Task.TaskBase): self.bld.env, proc_env, force_no_valgrind=True) def check_shell(bld): - if 'NS3_MODULE_PATH' not in os.environ: + if ('NS3_MODULE_PATH' not in os.environ) or ('NS3_EXECUTABLE_PATH' not in os.environ): return env = bld.env correct_modpath = os.pathsep.join(env['NS3_MODULE_PATH']) found_modpath = os.environ['NS3_MODULE_PATH'] - if found_modpath != correct_modpath: + correct_execpath = os.pathsep.join(env['NS3_EXECUTABLE_PATH']) + found_execpath = os.environ['NS3_EXECUTABLE_PATH'] + if (found_modpath != correct_modpath) or (correct_execpath != found_execpath): msg = ("Detected shell (./waf shell) with incorrect configuration\n" "=========================================================\n" "Possible reasons for this problem:\n" @@ -728,7 +730,8 @@ def shell(ctx): shell = os.environ.get("SHELL", "/bin/sh") env = wutils.bld.env - wutils.run_argv([shell], env, {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH'])}) + os_env = {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH']), 'NS3_EXECUTABLE_PATH': os.pathsep.join(env['NS3_EXECUTABLE_PATH'])} + wutils.run_argv([shell], env, os_env) def _doxygen(bld): env = wutils.bld.env diff --git a/wutils.py b/wutils.py index 8df08b401..c426d57b8 100644 --- a/wutils.py +++ b/wutils.py @@ -112,6 +112,11 @@ def get_proc_env(os_env=None): else: proc_env['PYTHONPATH'] = pymoddir + if 'PATH' in proc_env: + proc_env['PATH'] = os.pathsep.join(list(env['NS3_EXECUTABLE_PATH']) + [proc_env['PATH']]) + else: + proc_env['PATH'] = os.pathsep.join(list(env['NS3_EXECUTABLE_PATH'])) + return proc_env def run_argv(argv, env, os_env=None, cwd=None, force_no_valgrind=False): From 10d4a5d913c3cdae95745f1925f8b51e6df6fc51 Mon Sep 17 00:00:00 2001 From: Mirko Banchi Date: Mon, 8 Feb 2010 22:35:08 +0100 Subject: [PATCH 6/8] use NS_LOG_APPEND_CONTEXT instead of MY_DEBUG macro --- src/devices/wifi/dca-txop.cc | 41 ++++++++++++----------- src/devices/wifi/edca-txop-n.cc | 58 ++++++++++++++++----------------- 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/devices/wifi/dca-txop.cc b/src/devices/wifi/dca-txop.cc index eba746669..5701e1bc3 100644 --- a/src/devices/wifi/dca-txop.cc +++ b/src/devices/wifi/dca-txop.cc @@ -36,9 +36,8 @@ NS_LOG_COMPONENT_DEFINE ("DcaTxop"); -#define MY_DEBUG(x) \ - NS_LOG_DEBUG (m_low->GetAddress () << " " << x) - +#undef NS_LOG_APPEND_CONTEXT +#define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_low->GetAddress () << "] "; namespace ns3 { @@ -361,7 +360,7 @@ DcaTxop::NotifyAccessGranted (void) { if (m_queue->IsEmpty ()) { - MY_DEBUG ("queue empty"); + NS_LOG_DEBUG ("queue empty"); return; } m_currentPacket = m_queue->Dequeue (&m_currentHdr); @@ -372,7 +371,7 @@ DcaTxop::NotifyAccessGranted (void) m_currentHdr.SetNoMoreFragments (); m_currentHdr.SetNoRetry (); m_fragmentNumber = 0; - MY_DEBUG ("dequeued size="<GetSize ()<< + NS_LOG_DEBUG ("dequeued size="<GetSize ()<< ", to="<StartTransmission (m_currentPacket, &m_currentHdr, @@ -451,7 +450,7 @@ void DcaTxop::NotifyCollision (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("collision"); + NS_LOG_DEBUG ("collision"); m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); RestartAccessIfNeeded (); } @@ -467,16 +466,16 @@ void DcaTxop::GotCts (double snr, WifiMode txMode) { NS_LOG_FUNCTION (this << snr << txMode); - MY_DEBUG ("got cts"); + NS_LOG_DEBUG ("got cts"); } void DcaTxop::MissedCts (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("missed cts"); + NS_LOG_DEBUG ("missed cts"); if (!NeedRtsRetransmission ()) { - MY_DEBUG ("Cts Fail"); + NS_LOG_DEBUG ("Cts Fail"); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); station->ReportFinalRtsFailed (); if (!m_txFailedCallback.IsNull ()) @@ -501,7 +500,7 @@ DcaTxop::GotAck (double snr, WifiMode txMode) if (!NeedFragmentation () || IsLastFragment ()) { - MY_DEBUG ("got ack. tx done."); + NS_LOG_DEBUG ("got ack. tx done."); if (!m_txOkCallback.IsNull ()) { m_txOkCallback (m_currentHdr); @@ -517,17 +516,17 @@ DcaTxop::GotAck (double snr, WifiMode txMode) } else { - MY_DEBUG ("got ack. tx not done, size="<GetSize ()); + NS_LOG_DEBUG ("got ack. tx not done, size="<GetSize ()); } } void DcaTxop::MissedAck (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("missed ack"); + NS_LOG_DEBUG ("missed ack"); if (!NeedDataRetransmission ()) { - MY_DEBUG ("Ack Fail"); + NS_LOG_DEBUG ("Ack Fail"); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); station->ReportFinalDataFailed (); if (!m_txFailedCallback.IsNull ()) @@ -540,7 +539,7 @@ DcaTxop::MissedAck (void) } else { - MY_DEBUG ("Retransmit"); + NS_LOG_DEBUG ("Retransmit"); m_currentHdr.SetRetry (); m_dcf->UpdateFailedCw (); } @@ -551,7 +550,7 @@ void DcaTxop::StartNext (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("start next packet fragment"); + NS_LOG_DEBUG ("start next packet fragment"); /* this callback is used only for fragments. */ NextFragment (); WifiMacHeader hdr; @@ -575,7 +574,7 @@ void DcaTxop::Cancel (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("transmission cancelled"); + NS_LOG_DEBUG ("transmission cancelled"); /** * This happens in only one case: in an AP, you have two DcaTxop: * - one is used exclusively for beacons and has a high priority. diff --git a/src/devices/wifi/edca-txop-n.cc b/src/devices/wifi/edca-txop-n.cc index 9473da398..f703bc79d 100644 --- a/src/devices/wifi/edca-txop-n.cc +++ b/src/devices/wifi/edca-txop-n.cc @@ -37,8 +37,8 @@ NS_LOG_COMPONENT_DEFINE ("EdcaTxopN"); -#define MY_DEBUG(x) \ - NS_LOG_DEBUG (m_low->GetAddress () << " " << x) +#undef NS_LOG_APPEND_CONTEXT +#define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_low->GetAddress () << "] "; namespace ns3 { @@ -317,7 +317,7 @@ EdcaTxopN::NotifyAccessGranted (void) { if (m_queue->IsEmpty () && !m_baManager->HasPackets ()) { - MY_DEBUG ("queue is empty"); + NS_LOG_DEBUG ("queue is empty"); return; } struct Bar bar; @@ -332,7 +332,7 @@ EdcaTxopN::NotifyAccessGranted (void) { if (m_queue->PeekFirstAvailable (&m_currentHdr, m_currentPacketTimestamp, m_qosBlockedDestinations) == 0) { - MY_DEBUG ("no available packets in the queue"); + NS_LOG_DEBUG ("no available packets in the queue"); return; } if (m_currentHdr.IsQosData () && !m_currentHdr.GetAddr1 ().IsBroadcast () && @@ -351,7 +351,7 @@ EdcaTxopN::NotifyAccessGranted (void) m_currentHdr.SetNoMoreFragments (); m_currentHdr.SetNoRetry (); m_fragmentNumber = 0; - MY_DEBUG ("dequeued size="<GetSize ()<< + NS_LOG_DEBUG ("dequeued size="<GetSize ()<< ", to="< fragment = GetFragmentPacket (&hdr); if (IsLastFragment ()) { - MY_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ()); + NS_LOG_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ()); params.DisableNextData (); } else { - MY_DEBUG ("fragmenting size=" << fragment->GetSize ()); + NS_LOG_DEBUG ("fragmenting size=" << fragment->GetSize ()); params.EnableNextData (GetNextFragmentSize ()); } m_low->StartTransmission (fragment, &hdr, params, @@ -453,18 +453,18 @@ EdcaTxopN::NotifyAccessGranted (void) m_currentHdr.SetAddr3 (m_low->GetBssid ()); m_currentPacket = currentAggregatedPacket; currentAggregatedPacket = 0; - MY_DEBUG ("tx unicast A-MSDU"); + NS_LOG_DEBUG ("tx unicast A-MSDU"); } } if (NeedRts ()) { params.EnableRts (); - MY_DEBUG ("tx unicast rts"); + NS_LOG_DEBUG ("tx unicast rts"); } else { params.DisableRts (); - MY_DEBUG ("tx unicast"); + NS_LOG_DEBUG ("tx unicast"); } params.DisableNextData (); m_low->StartTransmission (m_currentPacket, &m_currentHdr, @@ -492,17 +492,17 @@ void EdcaTxopN::GotCts (double snr, WifiMode txMode) { NS_LOG_FUNCTION (this << snr << txMode); - MY_DEBUG ("got cts"); + NS_LOG_DEBUG ("got cts"); } void EdcaTxopN::MissedCts (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("missed cts"); + NS_LOG_DEBUG ("missed cts"); if (!NeedRtsRetransmission ()) { - MY_DEBUG ("Cts Fail"); + NS_LOG_DEBUG ("Cts Fail"); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); station->ReportFinalRtsFailed (); if (!m_txFailedCallback.IsNull ()) @@ -548,7 +548,7 @@ EdcaTxopN::GotAck (double snr, WifiMode txMode) IsLastFragment () || m_currentHdr.IsQosAmsdu ()) { - MY_DEBUG ("got ack. tx done."); + NS_LOG_DEBUG ("got ack. tx done."); if (!m_txOkCallback.IsNull ()) { m_txOkCallback (m_currentHdr); @@ -582,7 +582,7 @@ EdcaTxopN::GotAck (double snr, WifiMode txMode) } else { - MY_DEBUG ("got ack. tx not done, size="<GetSize ()); + NS_LOG_DEBUG ("got ack. tx not done, size="<GetSize ()); } } @@ -590,10 +590,10 @@ void EdcaTxopN::MissedAck (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("missed ack"); + NS_LOG_DEBUG ("missed ack"); if (!NeedDataRetransmission ()) { - MY_DEBUG ("Ack Fail"); + NS_LOG_DEBUG ("Ack Fail"); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); station->ReportFinalDataFailed (); if (!m_txFailedCallback.IsNull ()) @@ -606,7 +606,7 @@ EdcaTxopN::MissedAck (void) } else { - MY_DEBUG ("Retransmit"); + NS_LOG_DEBUG ("Retransmit"); m_currentHdr.SetRetry (); m_dcf->UpdateFailedCw (); } @@ -618,9 +618,9 @@ void EdcaTxopN::MissedBlockAck (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("missed block ack"); + NS_LOG_DEBUG ("missed block ack"); //should i report this to station addressed by ADDR1? - MY_DEBUG ("Retransmit block ack request"); + NS_LOG_DEBUG ("Retransmit block ack request"); m_currentHdr.SetRetry (); m_dcf->UpdateFailedCw (); @@ -689,7 +689,7 @@ void EdcaTxopN::StartNext (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("start next packet fragment"); + NS_LOG_DEBUG ("start next packet fragment"); /* this callback is used only for fragments. */ NextFragment (); WifiMacHeader hdr; @@ -713,7 +713,7 @@ void EdcaTxopN::Cancel (void) { NS_LOG_FUNCTION (this); - MY_DEBUG ("transmission cancelled"); + NS_LOG_DEBUG ("transmission cancelled"); } bool @@ -835,18 +835,18 @@ void EdcaTxopN::GotAddBaResponse (const MgtAddBaResponseHeader *respHdr, Mac48Address recipient) { NS_LOG_FUNCTION (this); - MY_DEBUG ("received ADDBA response from "<GetTid (); if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING)) { if (respHdr->GetStatusCode ().IsSuccess ()) { - MY_DEBUG ("block ack agreement established with "<UpdateAgreement (respHdr, recipient); } else { - MY_DEBUG ("discard ADDBA response"<NotifyAgreementUnsuccessful (recipient, tid); } } @@ -857,14 +857,14 @@ void EdcaTxopN::GotDelBaFrame (const MgtDelBaHeader *delBaHdr, Mac48Address recipient) { NS_LOG_FUNCTION (this); - MY_DEBUG ("received DELBA frame from="< Date: Mon, 8 Feb 2010 22:44:12 -0800 Subject: [PATCH 7/8] [bug 806] Remove CSMA padding from IP datagrams --- src/internet-stack/ipv4-l3-protocol.cc | 6 ++++++ src/internet-stack/ipv6-l3-protocol.cc | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index d42484f51..0baae1e72 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -463,6 +463,12 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr } packet->RemoveHeader (ipHeader); + // Trim any residual frame padding from underlying devices + if (ipHeader.GetPayloadSize () < packet->GetSize ()) + { + packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ()); + } + if (!ipHeader.IsChecksumOk ()) { m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, interface); diff --git a/src/internet-stack/ipv6-l3-protocol.cc b/src/internet-stack/ipv6-l3-protocol.cc index d1487a5ac..e30eeea2f 100644 --- a/src/internet-stack/ipv6-l3-protocol.cc +++ b/src/internet-stack/ipv6-l3-protocol.cc @@ -695,6 +695,12 @@ void Ipv6L3Protocol::Receive (Ptr device, Ptr p, uint16 Ipv6Header hdr; packet->RemoveHeader (hdr); + // Trim any residual frame padding from underlying devices + if (hdr.GetPayloadLength () < packet->GetSize ()) + { + packet->RemoveAtEnd (packet->GetSize () - hdr.GetPayloadLength ()); + } + /* forward up to IPv6 raw sockets */ for (SocketList::iterator it = m_sockets.begin () ; it != m_sockets.end () ; ++it) { From acb120543a7f050e11a4d96a57c0fb2a305b53cc Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 8 Feb 2010 22:45:39 -0800 Subject: [PATCH 8/8] ns3-tcp-socket test suite for socket-related TCP tests --- src/test/ns3tcp/ns3tcp-socket-test-suite.cc | 360 ++++++++++++++++++++ src/test/ns3tcp/wscript | 3 +- 2 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 src/test/ns3tcp/ns3tcp-socket-test-suite.cc diff --git a/src/test/ns3tcp/ns3tcp-socket-test-suite.cc b/src/test/ns3tcp/ns3tcp-socket-test-suite.cc new file mode 100644 index 000000000..3a364c8d9 --- /dev/null +++ b/src/test/ns3tcp/ns3tcp-socket-test-suite.cc @@ -0,0 +1,360 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 University of Washington + * + * 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 + */ + +#include "ns3/log.h" +#include "ns3/abort.h" +#include "ns3/test.h" +#include "ns3/pcap-file.h" +#include "ns3/config.h" +#include "ns3/string.h" +#include "ns3/uinteger.h" +#include "ns3/data-rate.h" +#include "ns3/inet-socket-address.h" +#include "ns3/point-to-point-helper.h" +#include "ns3/csma-helper.h" +#include "ns3/internet-stack-helper.h" +#include "ns3/ipv4-global-routing-helper.h" +#include "ns3/ipv4-address-helper.h" +#include "ns3/packet-sink-helper.h" +#include "ns3/tcp-socket-factory.h" +#include "ns3/node-container.h" +#include "ns3/simulator.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("Ns3SocketTest"); + +// =========================================================================== +// Tests of TCP implementations from the application/socket perspective +// =========================================================================== +// +// +// Simple class to write data to sockets +class SocketWriter : public Application +{ +public: + SocketWriter (); + virtual ~SocketWriter (); + void Setup (Ptr node, Address peer); + void Connect (); + void Write (uint32_t numBytes); + void Close (); + +private: + virtual void StartApplication (void); + virtual void StopApplication (void); + Address m_peer; + Ptr m_node; + Ptr m_socket; + bool m_isSetup; + bool m_isConnected; +}; + +SocketWriter::SocketWriter () : m_node (0), m_socket (0), m_isSetup (false), m_isConnected (false) +{ +} + +SocketWriter::~SocketWriter () +{ + m_socket = 0; + m_node = 0; +} + +void +SocketWriter::StartApplication () +{ + m_socket = Socket::CreateSocket (m_node, TcpSocketFactory::GetTypeId ()); + m_socket->Bind (); +} + +void +SocketWriter::StopApplication () +{ +} + +void +SocketWriter::Setup (Ptr node, Address peer) +{ + m_peer = peer; + m_node = node; + m_isSetup = true; +} + +void +SocketWriter::Connect () +{ + if (!m_isSetup) + { + NS_FATAL_ERROR ("Forgot to call Setup() first"); + } + m_socket->Connect (m_peer); + m_isConnected = true; +} + +void +SocketWriter::Write (uint32_t numBytes) +{ + if (!m_isConnected) + { + Connect (); + } + Ptr packet = Create (numBytes); + m_socket->Send (packet); +} + +void +SocketWriter::Close () +{ + m_socket->Close (); +} + +class Ns3TcpSocketTestCase1 : public TestCase +{ +public: + Ns3TcpSocketTestCase1 (); + virtual ~Ns3TcpSocketTestCase1 () {} + +private: + virtual bool DoRun (void); + bool m_writeResults; + + void SinkRx (std::string path, Ptr p, const Address &address); + + TestVectors m_inputs; + TestVectors m_responses; +}; + +Ns3TcpSocketTestCase1::Ns3TcpSocketTestCase1 () + : TestCase ("Check that ns-3 TCP successfully transfers an application data write of various sizes (point-to-point)"), + m_writeResults (false) +{ +} + +void +Ns3TcpSocketTestCase1::SinkRx (std::string path, Ptr p, const Address &address) +{ + m_responses.Add (p->GetSize ()); +} + +bool +Ns3TcpSocketTestCase1::DoRun (void) +{ + uint16_t sinkPort = 50000; + double sinkStopTime = 40; // sec; will trigger Socket::Close + double writerStopTime = 30; // sec; will trigger Socket::Close + double simStopTime = 60; // sec + Time sinkStopTimeObj = Seconds (sinkStopTime); + Time writerStopTimeObj = Seconds (writerStopTime); + Time simStopTimeObj= Seconds (simStopTime); + + Ptr n0 = CreateObject (); + Ptr n1 = CreateObject (); + + PointToPointHelper pointToPoint; + pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); + pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); + + NetDeviceContainer devices; + devices = pointToPoint.Install (n0, n1); + + InternetStackHelper internet; + internet.InstallAll (); + + Ipv4AddressHelper address; + address.SetBase ("10.1.1.0", "255.255.255.252"); + Ipv4InterfaceContainer ifContainer = address.Assign (devices); + + Ptr socketWriter = CreateObject (); + Address sinkAddress (InetSocketAddress (ifContainer.GetAddress (1), sinkPort)); + socketWriter->Setup (n0, sinkAddress); + n0->AddApplication (socketWriter); + socketWriter->SetStartTime (Seconds (0.)); + socketWriter->SetStopTime (writerStopTimeObj); + + PacketSinkHelper sink ("ns3::TcpSocketFactory", + InetSocketAddress (Ipv4Address::GetAny (), sinkPort)); + ApplicationContainer apps = sink.Install (n1); + // Start the sink application at time zero, and stop it at sinkStopTime + apps.Start (Seconds (0.0)); + apps.Stop (sinkStopTimeObj); + + Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", + MakeCallback (&Ns3TcpSocketTestCase1::SinkRx, this)); + + Simulator::Schedule(Seconds (2), &SocketWriter::Connect, socketWriter); + // Send 1, 10, 100, 1000 bytes + Simulator::Schedule(Seconds (10), &SocketWriter::Write, socketWriter, 1); + m_inputs.Add (1); + Simulator::Schedule(Seconds (12), &SocketWriter::Write, socketWriter, 10); + m_inputs.Add (10); + Simulator::Schedule(Seconds (14), &SocketWriter::Write, socketWriter, 100); + m_inputs.Add (100); + Simulator::Schedule(Seconds (16), &SocketWriter::Write, socketWriter, 1000); + m_inputs.Add (536); + m_inputs.Add (464); // ns-3 TCP default segment size of 536 + Simulator::Schedule(writerStopTimeObj, &SocketWriter::Close, socketWriter); + + if (m_writeResults) + { + PointToPointHelper::EnablePcapAll ("tcp-socket-test-case-1"); + } + + Simulator::Stop (simStopTimeObj); + Simulator::Run (); + Simulator::Destroy (); + + // Compare inputs and outputs + NS_TEST_ASSERT_MSG_EQ (m_inputs.GetN (), m_responses.GetN (), "Incorrect number of expected receive events"); + for (uint32_t i = 0; i < m_responses.GetN (); i++) + { + uint32_t in = m_inputs.Get (i); + uint32_t out = m_responses.Get (i); + NS_TEST_ASSERT_MSG_EQ (in, out, "Mismatch: expected " << in << " bytes, got " << out << " bytes"); + } + + return GetErrorStatus (); +} + +class Ns3TcpSocketTestCase2 : public TestCase +{ +public: + Ns3TcpSocketTestCase2 (); + virtual ~Ns3TcpSocketTestCase2 () {} + +private: + virtual bool DoRun (void); + bool m_writeResults; + + void SinkRx (std::string path, Ptr p, const Address &address); + + TestVectors m_inputs; + TestVectors m_responses; +}; + +Ns3TcpSocketTestCase2::Ns3TcpSocketTestCase2 () + : TestCase ("Check to see that ns-3 TCP successfully transfers an application data write of various sizes (CSMA)"), + m_writeResults (false) +{ +} + +void +Ns3TcpSocketTestCase2::SinkRx (std::string path, Ptr p, const Address &address) +{ + m_responses.Add (p->GetSize ()); +} + +bool +Ns3TcpSocketTestCase2::DoRun (void) +{ + uint16_t sinkPort = 50000; + double sinkStopTime = 40; // sec; will trigger Socket::Close + double writerStopTime = 30; // sec; will trigger Socket::Close + double simStopTime = 60; // sec + Time sinkStopTimeObj = Seconds (sinkStopTime); + Time writerStopTimeObj = Seconds (writerStopTime); + Time simStopTimeObj= Seconds (simStopTime); + + Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1000)); + + NodeContainer nodes; + nodes.Create (2); + Ptr n0 = nodes.Get (0); + Ptr n1 = nodes.Get (1); + + CsmaHelper csma; + csma.SetChannelAttribute ("DataRate", StringValue ("5Mbps")); + csma.SetChannelAttribute ("Delay", StringValue ("2ms")); + + NetDeviceContainer devices; + devices = csma.Install (nodes); + + InternetStackHelper internet; + internet.InstallAll (); + + Ipv4AddressHelper address; + address.SetBase ("10.1.1.0", "255.255.255.252"); + Ipv4InterfaceContainer ifContainer = address.Assign (devices); + + Ptr socketWriter = CreateObject (); + Address sinkAddress (InetSocketAddress (ifContainer.GetAddress (1), sinkPort)); + socketWriter->Setup (n0, sinkAddress); + n0->AddApplication (socketWriter); + socketWriter->SetStartTime (Seconds (0.)); + socketWriter->SetStopTime (writerStopTimeObj); + + PacketSinkHelper sink ("ns3::TcpSocketFactory", + InetSocketAddress (Ipv4Address::GetAny (), sinkPort)); + ApplicationContainer apps = sink.Install (n1); + // Start the sink application at time zero, and stop it at sinkStopTime + apps.Start (Seconds (0.0)); + apps.Stop (sinkStopTimeObj); + + Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", + MakeCallback (&Ns3TcpSocketTestCase2::SinkRx, this)); + + Simulator::Schedule(Seconds (2), &SocketWriter::Connect, socketWriter); + // Send 1, 10, 100, 1000 bytes + // PointToPoint default MTU is 576 bytes, which leaves 536 bytes for TCP + Simulator::Schedule(Seconds (10), &SocketWriter::Write, socketWriter, 1); + m_inputs.Add (1); + Simulator::Schedule(Seconds (12), &SocketWriter::Write, socketWriter, 10); + m_inputs.Add (10); + Simulator::Schedule(Seconds (14), &SocketWriter::Write, socketWriter, 100); + m_inputs.Add (100); + Simulator::Schedule(Seconds (16), &SocketWriter::Write, socketWriter, 1000); + m_inputs.Add (1000); + // Next packet will fragment + Simulator::Schedule(Seconds (16), &SocketWriter::Write, socketWriter, 1001); + m_inputs.Add (1000); + m_inputs.Add (1); + Simulator::Schedule(writerStopTimeObj, &SocketWriter::Close, socketWriter); + + if (m_writeResults) + { + CsmaHelper::EnablePcapAll ("tcp-socket-test-case-2", false); + } + Simulator::Stop (simStopTimeObj); + Simulator::Run (); + Simulator::Destroy (); + + // Compare inputs and outputs + NS_TEST_ASSERT_MSG_EQ (m_inputs.GetN (), m_responses.GetN (), "Incorrect number of expected receive events"); + for (uint32_t i = 0; i < m_responses.GetN (); i++) + { + uint32_t in = m_inputs.Get (i); + uint32_t out = m_responses.Get (i); + NS_TEST_ASSERT_MSG_EQ (in, out, "Mismatch: expected " << in << " bytes, got " << out << " bytes"); + } + + return GetErrorStatus (); +} + +class Ns3TcpSocketTestSuite : public TestSuite +{ +public: + Ns3TcpSocketTestSuite (); +}; + +Ns3TcpSocketTestSuite::Ns3TcpSocketTestSuite () + : TestSuite ("ns3-tcp-socket", SYSTEM) +{ + AddTestCase (new Ns3TcpSocketTestCase1); + AddTestCase (new Ns3TcpSocketTestCase2); +} + +Ns3TcpSocketTestSuite ns3TcpSocketTestSuite; diff --git a/src/test/ns3tcp/wscript b/src/test/ns3tcp/wscript index 467957c6c..661cb3233 100644 --- a/src/test/ns3tcp/wscript +++ b/src/test/ns3tcp/wscript @@ -13,5 +13,6 @@ def build(bld): if bld.env['NSC_ENABLED']: ns3tcp.source = [ 'ns3tcp-interop-test-suite.cc', - 'ns3tcp-cwnd-test-suite.cc' + 'ns3tcp-cwnd-test-suite.cc', + 'ns3tcp-socket-test-suite.cc' ]