@@ -, +, @@ --- src/internet/test/tcp-general-test.cc | 33 ++-- src/internet/test/tcp-general-test.h | 10 + src/lte/test/tcp-buffer-size.cc | 335 ++++++++++++++++++++++++++++++++++ src/lte/wscript | 1 + 4 files changed, 368 insertions(+), 11 deletions(-) create mode 100644 src/lte/test/tcp-buffer-size.cc --- a/src/internet/test/tcp-general-test.cc +++ a/src/internet/test/tcp-general-test.cc @@ -101,6 +101,7 @@ TcpGeneralTest::ConfigureEnvironment () SetAppPktCount (10); SetAppPktInterval (MilliSeconds (1)); SetMTU (1500); + SetConnectTime (Seconds (0.0)); } void @@ -113,20 +114,15 @@ TcpGeneralTest::ConfigureProperties () SetSegmentSize (RECEIVER, 500); } -void -TcpGeneralTest::DoRun (void) +Ipv4Address +TcpGeneralTest::MakeEnvironment (Ptr sender, Ptr receiver) { - ConfigureEnvironment (); - - NS_LOG_INFO ("Create nodes."); NodeContainer nodes; - nodes.Create (2); - + nodes.Add (sender); + nodes.Add (receiver); InternetStackHelper internet; internet.Install (nodes); - Packet::EnablePrinting (); - Ptr channel = CreateChannel (); SimpleNetDeviceHelper helperChannel; @@ -161,6 +157,22 @@ TcpGeneralTest::DoRun (void) Ipv4Address serverAddress = i.GetAddress (1); //Ipv4Address clientAddress = i.GetAddress (0); + return serverAddress; +} + +void +TcpGeneralTest::DoRun (void) +{ + ConfigureEnvironment (); + + NS_LOG_INFO ("Create nodes."); + NodeContainer nodes; + nodes.Create (2); + + Packet::EnablePrinting (); + + Ipv4Address serverAddress = MakeEnvironment (nodes.Get (0), nodes.Get (1)); + NS_LOG_INFO ("Create sockets."); //Receiver socket on n1 m_receiverSocket = CreateReceiverSocket (nodes.Get (1)); @@ -213,8 +225,7 @@ TcpGeneralTest::DoRun (void) m_receiverSocket->Listen (); m_receiverSocket->ShutdownSend (); - Simulator::Schedule (Seconds (0.0), - &TcpGeneralTest::DoConnect, this); + Simulator::Schedule (m_connectTime, &TcpGeneralTest::DoConnect, this); Simulator::ScheduleWithContext (nodes.Get (0)->GetId (), m_startTime, &TcpGeneralTest::SendPacket, this, m_senderSocket, m_pktSize, m_pktCount, m_interPacketInterval); --- a/src/internet/test/tcp-general-test.h +++ a/src/internet/test/tcp-general-test.h @@ -323,6 +323,8 @@ protected: */ virtual void ConfigureProperties (void); + virtual Ipv4Address MakeEnvironment (Ptr sender, Ptr receiver); + /** * \brief Teardown the TCP test */ @@ -539,6 +541,13 @@ protected: void SetAppPktInterval (Time pktInterval) { m_interPacketInterval = pktInterval; } /** + * \brief Set the connect time + * + * \param connectTime the time at which the application will connect + */ + void SetConnectTime (Time connectTime) { m_connectTime = connectTime; } + + /** * \brief Propagation delay of the bottleneck link * * \param propDelay propagation delay @@ -812,6 +821,7 @@ private: uint32_t m_pktCount; //!< Count of the application packet Time m_interPacketInterval; //!< Time between sending application packet // down to tcp socket + Time m_connectTime; //!< Time at which application will connect Ptr m_senderSocket; //!< Pointer to sender socket Ptr m_receiverSocket; //!< Pointer to receiver socket --- a/src/lte/test/tcp-buffer-size.cc +++ a/src/lte/test/tcp-buffer-size.cc @@ -0,0 +1,335 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2016 Natale Patriciello + * + * 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 "../internet/test/tcp-general-test.h" +#include "ns3/point-to-point-module.h" +#include "ns3/antenna-module.h" + +#include "ns3/propagation-module.h" +#include "ns3/mobility-module.h" +#include "ns3/test.h" +#include "ns3/internet-module.h" +#include "ns3/node-container.h" +#include "ns3/tcp-socket-base.h" +#include "ns3/simple-net-device-helper.h" +#include "ns3/ipv4-address-helper.h" +#include "ns3/internet-stack-helper.h" +#include "ns3/log.h" +#include "ns3/tcp-l4-protocol.h" +#include "../internet/model/ipv4-end-point.h" +#include "../internet/model/ipv6-end-point.h" +#include "ns3/lte-module.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("TcpBufferSizeTestSuite"); + +class TcpSocketHighBuf : public TcpSocketMsgBase +{ +public: + static TypeId GetTypeId (); + TcpSocketHighBuf () : TcpSocketMsgBase () { } + TcpSocketHighBuf (const TcpSocketHighBuf &other) : TcpSocketMsgBase (other) { } + +protected: + virtual void ReceivedData (Ptr p, const TcpHeader& tcpHeader); + virtual Ptr Fork (void) { return CopyObject (this); } +}; + +TypeId +TcpSocketHighBuf::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::TcpSocketHighBuf") + .SetParent () + .SetGroupName ("Internet") + .AddConstructor () + ; + return tid; +} + +void +TcpSocketHighBuf::ReceivedData (Ptr p, const TcpHeader& tcpHeader) +{ + NS_LOG_FUNCTION (this << tcpHeader); + NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () << + " pkt size=" << p->GetSize () ); + + // Put into Rx buffer + SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence (); + if (!m_rxBuffer->Add (p, tcpHeader)) + { // Insert failed: No data or RX buffer full + SendEmptyPacket (TcpHeader::ACK); + return; + } + // Now send a new ACK packet acknowledging all received and delivered data + if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ()) + { // A gap exists in the buffer, or we filled a gap: Always ACK + SendEmptyPacket (TcpHeader::ACK); + } + else + { // In-sequence packet: ACK if delayed ack count allows + if (++m_delAckCount >= m_delAckMaxCount) + { + m_delAckEvent.Cancel (); + m_delAckCount = 0; + SendEmptyPacket (TcpHeader::ACK); + } + else if (m_delAckEvent.IsExpired ()) + { + m_delAckEvent = Simulator::Schedule (m_delAckTimeout, + &TcpSocketHighBuf::DelAckTimeout, this); + NS_LOG_LOGIC (this << " scheduled delayed ACK at " << + (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ()); + } + } + // Notify app to receive if necessary + if (expectedSeq < m_rxBuffer->NextRxSequence ()) + { // NextRxSeq advanced, we have something to send to the app + if (!m_shutdownRecv && m_rxBuffer->Available () > 4000000) + { + NotifyDataRecv (); + } + else + { + NS_LOG_DEBUG ("Queueing " << m_rxBuffer->Available () << " bytes"); + } + // Handle exceptions + if (m_closeNotified) + { + NS_LOG_WARN ("Why TCP " << this << " got data after close notification?"); + } + // If we received FIN before and now completed all "holes" in rx buffer, + // invoke peer close procedure + if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0) + { + DoPeerClose (); + } + } +} + +class TcpBufferSizeTest : public TcpGeneralTest +{ +public: + TcpBufferSizeTest (const std::string &desc); + +protected: + virtual Ptr CreateReceiverSocket (Ptr node); + virtual Ptr CreateSenderSocket (Ptr node); + void ConfigureEnvironment (); + void ConfigureProperties (); + virtual Ipv4Address MakeEnvironment (Ptr sender, Ptr receiver); +}; + +TcpBufferSizeTest::TcpBufferSizeTest (const std::string &desc) + : TcpGeneralTest (desc) +{ +} + +void +TcpBufferSizeTest::ConfigureEnvironment () +{ + NS_LOG_FUNCTION (this); + TcpGeneralTest::ConfigureEnvironment (); + SetPropagationDelay (MilliSeconds (50)); + SetAppPktSize (1340); + SetAppPktCount (60000); + SetConnectTime (Seconds (4.0)); +} + +void +TcpBufferSizeTest::ConfigureProperties () +{ + TcpGeneralTest::ConfigureProperties (); + SetRcvBufSize (RECEIVER, 6000000); + SetSegmentSize (SENDER, 1340); + SetSegmentSize (RECEIVER, 1340); +} + +Ptr +TcpBufferSizeTest::CreateReceiverSocket (Ptr node) +{ + return CreateSocket (node, TcpSocketHighBuf::GetTypeId (), m_congControlTypeId); +} + +Ptr +TcpBufferSizeTest::CreateSenderSocket (Ptr node) +{ + return CreateSocket (node, TcpSocketHighBuf::GetTypeId (), m_congControlTypeId); +} + +static void +SetNodeProperties (Ptr node, double x, double y, double z, const std::string &name) +{ + Ptr loc = node->GetObject (); + if (loc == 0) + { + loc = CreateObject (); + node->AggregateObject (loc); + } + loc->SetPosition (Vector3D (x, y, z)); // 5, 2 + Names::Add (name, node); +} + +static Ipv4InterfaceContainer +BuildIpv4LAN (NetDeviceContainer &devs, const std::string &baseAddr = "10.0.0.0") +{ + static Ipv4AddressHelper address; + address.SetBase (baseAddr.c_str (), "255.255.0.0"); + address.NewNetwork (); + + return address.Assign (devs); +} + +Ipv4Address +TcpBufferSizeTest::MakeEnvironment (Ptr sender, Ptr receiver) +{ + static Ptr lteHelper = CreateObject (); + static Ptr epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + + lteHelper->SetEnbAntennaModelType ("ns3::IsotropicAntennaModel"); + lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (100)); + lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (100)); + lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (1575)); + lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (19575)); + lteHelper->SetUeAntennaModelType ("ns3::IsotropicAntennaModel"); + lteHelper->SetUeDeviceAttribute ("DlEarfcn", UintegerValue (1575)); + lteHelper->SetPathlossModelType ("ns3::OkumuraHataPropagationLossModel"); + lteHelper->SetPathlossModelAttribute ("Environment", EnumValue (UrbanEnvironment)); + lteHelper->SetPathlossModelAttribute ("CitySize", EnumValue (MediumCity)); + lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler"); + + Ptr pgw = epcHelper->GetPgwNode (); + + SetNodeProperties (pgw, 50, 20, 2, "pgw"); + + // Create a single RemoteHost + NodeContainer remoteHostContainer; + remoteHostContainer.Add (receiver); + Ptr remoteHost = remoteHostContainer.Get (0); + InternetStackHelper internet; + internet.Install (remoteHostContainer); + + //add a position to the Remote Host node + SetNodeProperties (remoteHost, 70, 20, 2, "remote"); + + // Create the Internet + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("500Mb/s"))); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); + p2ph.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (5))); + + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + Ipv4AddressHelper ipv4h; + ipv4h.SetBase ("1.0.0.0", "255.0.0.0"); + Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices); + + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ptr remoteHostStaticRouting; + + remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + + remoteHostStaticRouting->SetDefaultRoute (internetIpIfaces.GetAddress (0), 1); + + // Create the ENBs and set position + NodeContainer enbNodes; + enbNodes.Create (1); + for (uint32_t i = 0; i < 1; ++i) + { + std::stringstream n; + n << "ENB" << i+1; + SetNodeProperties (enbNodes.Get (i), 10, 10, 2, n.str ()); + } + + // Create the UEs and set position + NodeContainer ueNodes; + ueNodes.Add (sender); + for (uint32_t i = 0; i < 1; ++i) + { + std::stringstream n; + n << "UE" << i+1; + SetNodeProperties (ueNodes.Get (i), 9, 10, 2, n.str ()); + } + + NetDeviceContainer enbDevices = lteHelper->InstallEnbDevice (enbNodes); + NetDeviceContainer ueDevices = lteHelper->InstallUeDevice (ueNodes); + + NetDeviceContainer::Iterator it; + for (it = enbDevices.Begin (); it != enbDevices.End (); ++it) + { + Ptr dev = DynamicCast (*it); + NS_ASSERT (dev != 0); + + dev->GetPhy ()->SetTxPower (23.0); + dev->GetRrc ()->SetSrsPeriodicity (80); + } + + InternetStackHelper stack; + stack.Install (ueNodes); + + Ipv4InterfaceContainer ueIpIface; + ueIpIface = epcHelper->AssignUeIpv4Address (ueDevices); + + for (it = ueDevices.Begin (); it != ueDevices.End (); ++it) + { + Ptr dev = DynamicCast (*it); + + dev->GetPhy ()->SetTxPower (23.0); + } + + lteHelper->AttachToClosestEnb (ueDevices, enbDevices); + + + for (uint32_t i = 0; i < ueNodes.GetN (); ++i) + { + Ptr ue = ueNodes.Get (i); + Ptr ueStaticRouting; + ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject ()); + + // 0 is Loopback, 1 is LteUeNetDevice + ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1); + } + + BuildIpv4LAN (ueDevices, "192.168.0.0"); + + { + Ptr ueStaticRouting; + ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + + // 0 is Loopback, 1 is LteUeNetDevice + ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1); + } + + return internetIpIfaces.GetAddress (1); +} + + +//----------------------------------------------------------------------------- + +static class TcpBufferSizeTestSuite : public TestSuite +{ +public: + TcpBufferSizeTestSuite () : TestSuite ("tcp-buffer-size-test", UNIT) + { + AddTestCase (new TcpBufferSizeTest ("Some data exchanged"), + TestCase::QUICK); + } +} g_tcpBufferSizeTestSuite; + +} // namespace ns3 --- a/src/lte/wscript +++ a/src/lte/wscript @@ -126,6 +126,7 @@ def build(bld): module_test = bld.create_ns3_module_test_library('lte') module_test.source = [ + 'test/tcp-buffer-size.cc', 'test/lte-test-downlink-sinr.cc', 'test/lte-test-uplink-sinr.cc', 'test/lte-test-link-adaptation.cc', --