From a5ea699a83beca56daffcf41e310569fb778c680 Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Tue, 26 Mar 2013 10:42:22 +0100 Subject: [PATCH] Add testcase for the automatic HO triger --- src/lte/test/test-lte-x2-handover-measures.cc | 669 ++++++++++++++++++ src/lte/wscript | 5 +- 2 files changed, 672 insertions(+), 2 deletions(-) create mode 100644 src/lte/test/test-lte-x2-handover-measures.cc diff --git a/src/lte/test/test-lte-x2-handover-measures.cc b/src/lte/test/test-lte-x2-handover-measures.cc new file mode 100644 index 000000000..3acfac18d --- /dev/null +++ b/src/lte/test/test-lte-x2-handover-measures.cc @@ -0,0 +1,669 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2013 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Nicola Baldo + * Manuel Requena + */ + +#include +#include +#include +#include +#include +#include +#include + +NS_LOG_COMPONENT_DEFINE ("LteX2HandoverMeasuresTest"); + +namespace ns3 { + + +struct CheckPointEvent +{ + Time checkStartTime; + Time checkStopTime; + Time checkInterval; + uint32_t ueDeviceIndex; + uint32_t enbDeviceIndex; + + CheckPointEvent (Time start, Time stop, Time interval, uint32_t ueIndex, uint32_t enbIndex) + : checkStartTime (start), + checkStopTime (stop), + checkInterval (interval), + ueDeviceIndex (ueIndex), + enbDeviceIndex (enbIndex) + { + } +}; + + +class LteX2HandoverMeasuresTestCase : public TestCase +{ +public: + /** + * + * + * \param nEnbs number of eNBs in the test + * \param nUes number of UEs in the test + * \param nDedicatedBearers number of bearers to be activated per UE + * \param checkPointEventList + * \param checkPointEventListName + * \param useUdp true if UDP is to be used, false if TCP is to be used + * + * \return + */ + LteX2HandoverMeasuresTestCase (uint32_t nEnbs, uint32_t nUes, uint32_t nDedicatedBearers, + std::list checkPointEventList, std::string checkPointEventListName, + bool useUdp, std::string schedulerType, bool admitHo, bool useIdealRrc); + +private: + static std::string BuildNameString (uint32_t nEnbs, uint32_t nUes, uint32_t nDedicatedBearers, + std::string checkPointEventListName, + bool useUdp, std::string schedulerType, bool admitHo, bool useIdealRrc); + virtual void DoRun (void); + void CheckConnected (Ptr ueDevice, Ptr enbDevice); + + uint32_t m_nEnbs; // number of eNBs in the test + uint32_t m_nUes; // number of UEs in the test + uint32_t m_nDedicatedBearers; // number of UEs in the test + std::list m_checkPointEventList; + std::string m_checkPointEventListName; + bool m_epc; + bool m_useUdp; + std::string m_schedulerType; + bool m_admitHo; + bool m_useIdealRrc; + Ptr m_lteHelper; + Ptr m_epcHelper; + + struct BearerData + { + uint32_t bid; + Ptr dlSink; + Ptr ulSink; + uint32_t dlOldTotalRx; + uint32_t ulOldTotalRx; + }; + + struct UeData + { + uint32_t id; + std::list bearerDataList; + }; + + void SaveStats (uint32_t ueIndex); + void CheckStats (uint32_t ueIndex); + + std::vector m_ueDataVector; + + const Time m_maxHoDuration; + const Time m_statsDuration; + const Time m_udpClientInterval; + const uint32_t m_udpClientPktSize; +}; + + +std::string +LteX2HandoverMeasuresTestCase::BuildNameString (uint32_t nEnbs, uint32_t nUes, uint32_t nDedicatedBearers, + std::string checkPointEventListName, + bool useUdp, std::string schedulerType, bool admitHo, bool useIdealRrc) +{ + std::ostringstream oss; + oss << "nEnbs=" << nEnbs + << " nUes=" << nUes + << " nDedicatedBearers=" << nDedicatedBearers + << " udp=" << useUdp + << " " << schedulerType + << " admitHo=" << admitHo + << " hoList: " << checkPointEventListName; + if (useIdealRrc) + { + oss << ", ideal RRC"; + } + else + { + oss << ", real RRC"; + } + return oss.str (); +} + +LteX2HandoverMeasuresTestCase::LteX2HandoverMeasuresTestCase (uint32_t nEnbs, uint32_t nUes, uint32_t nDedicatedBearers, + std::list checkPointEventList, std::string checkPointEventListName, + bool useUdp, std::string schedulerType, bool admitHo, bool useIdealRrc) + : TestCase (BuildNameString (nEnbs, nUes, nDedicatedBearers, checkPointEventListName, useUdp, schedulerType, admitHo, useIdealRrc)), + m_nEnbs (nEnbs), + m_nUes (nUes), + m_nDedicatedBearers (nDedicatedBearers), + m_checkPointEventList (checkPointEventList), + m_checkPointEventListName (checkPointEventListName), + m_epc (true), + m_useUdp (useUdp), + m_schedulerType (schedulerType), + m_admitHo (admitHo), + m_useIdealRrc (useIdealRrc), + m_maxHoDuration (Seconds (0.1)), + m_statsDuration (Seconds (0.5)), + m_udpClientInterval (Seconds (0.01)), + m_udpClientPktSize (100) +{ +} + +void +LteX2HandoverMeasuresTestCase::DoRun () +{ + NS_LOG_FUNCTION (this << BuildNameString (m_nEnbs, m_nUes, m_nDedicatedBearers, + m_checkPointEventListName, + m_useUdp, m_schedulerType, m_admitHo, m_useIdealRrc)); + + Config::Reset (); + Config::SetDefault ("ns3::UdpClient::Interval", TimeValue (m_udpClientInterval)); + Config::SetDefault ("ns3::UdpClient::MaxPackets", UintegerValue (1000000)); + Config::SetDefault ("ns3::UdpClient::PacketSize", UintegerValue (m_udpClientPktSize)); + Config::SetDefault ("ns3::LteEnbRrc::ServingCellHandoverThreshold", UintegerValue (30)); + Config::SetDefault ("ns3::LteEnbRrc::NeighbourCellHandoverOffset", UintegerValue (1)); + Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (20)); + + + int64_t stream = 1; + + m_lteHelper = CreateObject (); + m_lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel")); + m_lteHelper->SetSchedulerType (m_schedulerType); + m_lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (m_useIdealRrc)); + + + double distance = 1000.0; // m + double speed = 100; // m/s + + NodeContainer enbNodes; + enbNodes.Create (m_nEnbs); + NodeContainer ueNodes; + ueNodes.Create (m_nUes); + + if (m_epc) + { + m_epcHelper = CreateObject (); + m_lteHelper->SetEpcHelper (m_epcHelper); + } + + // Install Mobility Model in eNBs + // eNBs are located along a line in the X axis + Ptr enbPositionAlloc = CreateObject (); + for (uint16_t i = 0; i < m_nEnbs; i++) + { + Vector enbPosition (distance * (i + 1), 0, 0); + enbPositionAlloc->Add (enbPosition); + } + MobilityHelper enbMobility; + enbMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); + enbMobility.SetPositionAllocator(enbPositionAlloc); + enbMobility.Install(enbNodes); + + // Install Mobility Model in UE + // UE moves with a constant speed along the X axis + MobilityHelper ueMobility; + ueMobility.SetMobilityModel ("ns3::ConstantVelocityMobilityModel"); + ueMobility.Install(ueNodes); + ueNodes.Get (0)->GetObject ()->SetPosition (Vector (0, 0, 0)); + ueNodes.Get (0)->GetObject ()->SetVelocity (Vector (speed, 0, 0)); + + + NetDeviceContainer enbDevices; + enbDevices = m_lteHelper->InstallEnbDevice (enbNodes); + stream += m_lteHelper->AssignStreams (enbDevices, stream); + for (NetDeviceContainer::Iterator it = enbDevices.Begin (); + it != enbDevices.End (); + ++it) + { + Ptr enbRrc = (*it)->GetObject ()->GetRrc (); + enbRrc->SetAttribute ("AdmitHandoverRequest", BooleanValue (m_admitHo)); + } + + NetDeviceContainer ueDevices; + ueDevices = m_lteHelper->InstallUeDevice (ueNodes); + stream += m_lteHelper->AssignStreams (ueDevices, stream); + + Ipv4Address remoteHostAddr; + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ipv4InterfaceContainer ueIpIfaces; + Ptr remoteHost; + if (m_epc) + { + // Create a single RemoteHost + NodeContainer remoteHostContainer; + remoteHostContainer.Create (1); + remoteHost = remoteHostContainer.Get (0); + InternetStackHelper internet; + internet.Install (remoteHostContainer); + + // Create the Internet + PointToPointHelper p2ph; + p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s"))); + p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); + p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010))); + Ptr pgw = m_epcHelper->GetPgwNode (); + NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); + Ipv4AddressHelper ipv4h; + ipv4h.SetBase ("1.0.0.0", "255.0.0.0"); + Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices); + // in this container, interface 0 is the pgw, 1 is the remoteHost + remoteHostAddr = internetIpIfaces.GetAddress (1); + + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ptr remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ()); + remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1); + + // Install the IP stack on the UEs + internet.Install (ueNodes); + ueIpIfaces = m_epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueDevices)); + } + + // attachment (needs to be done after IP stack configuration) + // all UEs attached to eNB 0 at the beginning + m_lteHelper->Attach (ueDevices, enbDevices.Get (0)); + + if (m_epc) + { + bool epcDl = true; + bool epcUl = false; + // the rest of this block is copied from lena-dual-stripe + + + // Install and start applications on UEs and remote host + uint16_t dlPort = 10000; + uint16_t ulPort = 20000; + + // randomize a bit start times to avoid simulation artifacts + // (e.g., buffer overflows due to packet transmissions happening + // exactly at the same time) + Ptr startTimeSeconds = CreateObject (); + startTimeSeconds->SetAttribute ("Min", DoubleValue (0)); + startTimeSeconds->SetAttribute ("Max", DoubleValue (0.010)); + startTimeSeconds->SetStream (stream++); + + for (uint32_t u = 0; u < ueNodes.GetN (); ++u) + { + Ptr ue = ueNodes.Get (u); + // Set the default gateway for the UE + Ptr ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject ()); + ueStaticRouting->SetDefaultRoute (m_epcHelper->GetUeDefaultGatewayAddress (), 1); + + UeData ueData; + + for (uint32_t b = 0; b < m_nDedicatedBearers; ++b) + { + ++dlPort; + ++ulPort; + + ApplicationContainer clientApps; + ApplicationContainer serverApps; + BearerData bearerData; + + if (m_useUdp) + { + if (epcDl) + { + UdpClientHelper dlClientHelper (ueIpIfaces.GetAddress (u), dlPort); + clientApps.Add (dlClientHelper.Install (remoteHost)); + PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory", + InetSocketAddress (Ipv4Address::GetAny (), dlPort)); + ApplicationContainer sinkContainer = dlPacketSinkHelper.Install (ue); + bearerData.dlSink = sinkContainer.Get (0)->GetObject (); + serverApps.Add (sinkContainer); + + } + if (epcUl) + { + UdpClientHelper ulClientHelper (remoteHostAddr, ulPort); + clientApps.Add (ulClientHelper.Install (ue)); + PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory", + InetSocketAddress (Ipv4Address::GetAny (), ulPort)); + ApplicationContainer sinkContainer = ulPacketSinkHelper.Install (remoteHost); + bearerData.ulSink = sinkContainer.Get (0)->GetObject (); + serverApps.Add (sinkContainer); + } + } + else // use TCP + { + if (epcDl) + { + BulkSendHelper dlClientHelper ("ns3::TcpSocketFactory", + InetSocketAddress (ueIpIfaces.GetAddress (u), dlPort)); + dlClientHelper.SetAttribute ("MaxBytes", UintegerValue (0)); + clientApps.Add (dlClientHelper.Install (remoteHost)); + PacketSinkHelper dlPacketSinkHelper ("ns3::TcpSocketFactory", + InetSocketAddress (Ipv4Address::GetAny (), dlPort)); + ApplicationContainer sinkContainer = dlPacketSinkHelper.Install (ue); + bearerData.dlSink = sinkContainer.Get (0)->GetObject (); + serverApps.Add (sinkContainer); + } + if (epcUl) + { + BulkSendHelper ulClientHelper ("ns3::TcpSocketFactory", + InetSocketAddress (remoteHostAddr, ulPort)); + ulClientHelper.SetAttribute ("MaxBytes", UintegerValue (0)); + clientApps.Add (ulClientHelper.Install (ue)); + PacketSinkHelper ulPacketSinkHelper ("ns3::TcpSocketFactory", + InetSocketAddress (Ipv4Address::GetAny (), ulPort)); + ApplicationContainer sinkContainer = ulPacketSinkHelper.Install (remoteHost); + bearerData.ulSink = sinkContainer.Get (0)->GetObject (); + serverApps.Add (sinkContainer); + } + } // end if (useUdp) + + Ptr tft = Create (); + if (epcDl) + { + EpcTft::PacketFilter dlpf; + dlpf.localPortStart = dlPort; + dlpf.localPortEnd = dlPort; + tft->Add (dlpf); + } + if (epcUl) + { + EpcTft::PacketFilter ulpf; + ulpf.remotePortStart = ulPort; + ulpf.remotePortEnd = ulPort; + tft->Add (ulpf); + } + + if (epcDl || epcUl) + { + EpsBearer bearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT); + m_lteHelper->ActivateDedicatedEpsBearer (ueDevices.Get (u), bearer, tft); + } + Time startTime = Seconds (startTimeSeconds->GetValue ()); + serverApps.Start (startTime); + clientApps.Start (startTime); + + ueData.bearerDataList.push_back (bearerData); + + } // end for b + + m_ueDataVector.push_back (ueData); + } + + } + else // (epc == false) + { + // for radio bearer activation purposes, consider together home UEs and macro UEs + for (uint32_t u = 0; u < ueDevices.GetN (); ++u) + { + Ptr ueDev = ueDevices.Get (u); + for (uint32_t b = 0; b < m_nDedicatedBearers; ++b) + { + enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT; + EpsBearer bearer (q); + m_lteHelper->ActivateDataRadioBearer (ueDev, bearer); + } + } + } + + + m_lteHelper->AddX2Interface (enbNodes); + + // check initial RRC connection + const Time maxRrcConnectionEstablishmentDuration = Seconds (0.080); + for (NetDeviceContainer::Iterator it = ueDevices.Begin (); it != ueDevices.End (); ++it) + { + NS_LOG_FUNCTION (maxRrcConnectionEstablishmentDuration); + Simulator::Schedule (maxRrcConnectionEstablishmentDuration, + &LteX2HandoverMeasuresTestCase::CheckConnected, + this, *it, enbDevices.Get (0)); + } + + // schedule the checkpoint events + + Time stopTime = Seconds (0); + for (std::list::iterator checkPointEventIt = m_checkPointEventList.begin (); + checkPointEventIt != m_checkPointEventList.end (); + ++checkPointEventIt) + { + for (Time checkPointTime = checkPointEventIt->checkStartTime; + checkPointTime < checkPointEventIt->checkStopTime; + checkPointTime += checkPointEventIt->checkInterval) + { + Simulator::Schedule (checkPointTime, &LteX2HandoverMeasuresTestCase::CheckConnected, + this, ueDevices.Get (checkPointEventIt->ueDeviceIndex), + enbDevices.Get (checkPointEventIt->enbDeviceIndex)); + + Time saveStatsTime = checkPointTime; + Simulator::Schedule (saveStatsTime, &LteX2HandoverMeasuresTestCase::SaveStats, + this, checkPointEventIt->ueDeviceIndex); + + Time checkStats = saveStatsTime + m_statsDuration; + Simulator::Schedule (checkStats, &LteX2HandoverMeasuresTestCase::CheckStats, + this, checkPointEventIt->ueDeviceIndex); + + if (stopTime <= checkStats) + { + stopTime = checkStats + Seconds (1); + } + } + } + + // TODO useful? to remove +// m_lteHelper->EnableRlcTraces (); +// Ptr rlcStats = m_lteHelper->GetRlcStats (); +// rlcStats->SetAttribute ("StartTime", TimeValue (Seconds (0.101))); +// rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (0.1))); +// m_lteHelper->EnablePdcpTraces (); + + Simulator::Stop (stopTime); + Simulator::Run (); + Simulator::Destroy (); +} + +void +LteX2HandoverMeasuresTestCase::CheckConnected (Ptr ueDevice, Ptr enbDevice) +{ + NS_LOG_FUNCTION (ueDevice << enbDevice); + + Ptr ueLteDevice = ueDevice->GetObject (); + Ptr ueRrc = ueLteDevice->GetRrc (); + NS_TEST_ASSERT_MSG_EQ (ueRrc->GetState (), LteUeRrc::CONNECTED_NORMALLY, "Wrong LteUeRrc state!"); + + + Ptr enbLteDevice = enbDevice->GetObject (); + Ptr enbRrc = enbLteDevice->GetRrc (); + uint16_t rnti = ueRrc->GetRnti (); + Ptr ueManager = enbRrc->GetUeManager (rnti); + NS_TEST_ASSERT_MSG_NE (ueManager, 0, "RNTI " << rnti << " not found in eNB"); + + UeManager::State ueManagerState = ueManager->GetState (); + NS_TEST_ASSERT_MSG_EQ (ueManagerState, UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!"); + NS_ASSERT_MSG (ueManagerState == UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!"); + + uint16_t ueCellId = ueRrc->GetCellId (); + uint16_t enbCellId = enbLteDevice->GetCellId (); + uint8_t ueDlBandwidth = ueRrc->GetDlBandwidth (); + uint8_t enbDlBandwidth = enbLteDevice->GetDlBandwidth (); + uint8_t ueUlBandwidth = ueRrc->GetUlBandwidth (); + uint8_t enbUlBandwidth = enbLteDevice->GetUlBandwidth (); + uint8_t ueDlEarfcn = ueRrc->GetDlEarfcn (); + uint8_t enbDlEarfcn = enbLteDevice->GetDlEarfcn (); + uint8_t ueUlEarfcn = ueRrc->GetUlEarfcn (); + uint8_t enbUlEarfcn = enbLteDevice->GetUlEarfcn (); + uint64_t ueImsi = ueLteDevice->GetImsi (); + uint64_t enbImsi = ueManager->GetImsi (); + + NS_TEST_ASSERT_MSG_EQ (ueImsi, enbImsi, "inconsistent IMSI"); + NS_TEST_ASSERT_MSG_EQ (ueCellId, enbCellId, "inconsistent CellId"); + NS_TEST_ASSERT_MSG_EQ (ueDlBandwidth, enbDlBandwidth, "inconsistent DlBandwidth"); + NS_TEST_ASSERT_MSG_EQ (ueUlBandwidth, enbUlBandwidth, "inconsistent UlBandwidth"); + NS_TEST_ASSERT_MSG_EQ (ueDlEarfcn, enbDlEarfcn, "inconsistent DlEarfcn"); + NS_TEST_ASSERT_MSG_EQ (ueUlEarfcn, enbUlEarfcn, "inconsistent UlEarfcn"); + + ObjectMapValue enbDataRadioBearerMapValue; + ueManager->GetAttribute ("DataRadioBearerMap", enbDataRadioBearerMapValue); + NS_TEST_ASSERT_MSG_EQ (enbDataRadioBearerMapValue.GetN (), m_nDedicatedBearers + 1, "wrong num bearers at eNB"); + + ObjectMapValue ueDataRadioBearerMapValue; + ueRrc->GetAttribute ("DataRadioBearerMap", ueDataRadioBearerMapValue); + NS_TEST_ASSERT_MSG_EQ (ueDataRadioBearerMapValue.GetN (), m_nDedicatedBearers + 1, "wrong num bearers at UE"); + + ObjectMapValue::Iterator enbBearerIt = enbDataRadioBearerMapValue.Begin (); + ObjectMapValue::Iterator ueBearerIt = ueDataRadioBearerMapValue.Begin (); + while (enbBearerIt != enbDataRadioBearerMapValue.End () + && ueBearerIt != ueDataRadioBearerMapValue.End ()) + { + Ptr enbDrbInfo = enbBearerIt->second->GetObject (); + Ptr ueDrbInfo = ueBearerIt->second->GetObject (); + //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_epsBearer, ueDrbInfo->m_epsBearer, "epsBearer differs"); + NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_epsBearerIdentity, (uint32_t) ueDrbInfo->m_epsBearerIdentity, "epsBearerIdentity differs"); + NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_drbIdentity, (uint32_t) ueDrbInfo->m_drbIdentity, "drbIdentity differs"); + //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_rlcConfig, ueDrbInfo->m_rlcConfig, "rlcConfig differs"); + NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_logicalChannelIdentity, (uint32_t) ueDrbInfo->m_logicalChannelIdentity, "logicalChannelIdentity differs"); + //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_logicalChannelConfig, ueDrbInfo->m_logicalChannelConfig, "logicalChannelConfig differs"); + + ++enbBearerIt; + ++ueBearerIt; + } + NS_ASSERT_MSG (enbBearerIt == enbDataRadioBearerMapValue.End (), "too many bearers at eNB"); + NS_ASSERT_MSG (ueBearerIt == ueDataRadioBearerMapValue.End (), "too many bearers at UE"); +} + +void +LteX2HandoverMeasuresTestCase::SaveStats (uint32_t ueIndex) +{ + NS_LOG_FUNCTION (ueIndex); + for (std::list::iterator it = m_ueDataVector.at (ueIndex).bearerDataList.begin (); + it != m_ueDataVector.at (ueIndex).bearerDataList.end (); + ++it) + { + if (it->dlSink) + { + it->dlOldTotalRx = it->dlSink->GetTotalRx (); + } + if (it->ulSink) + { + it->ulOldTotalRx = it->ulSink->GetTotalRx (); + } + } +} + +void +LteX2HandoverMeasuresTestCase::CheckStats (uint32_t ueIndex) +{ + NS_LOG_FUNCTION (ueIndex); + uint32_t b = 1; + for (std::list::iterator it = m_ueDataVector.at (ueIndex).bearerDataList.begin (); + it != m_ueDataVector.at (ueIndex).bearerDataList.end (); + ++it) + { + uint32_t dlRx = 0; + uint32_t ulRx = 0; + + if (it->dlSink) + { + dlRx = it->dlSink->GetTotalRx () - it->dlOldTotalRx; + } + + if (it->ulSink) + { + ulRx = it->ulSink->GetTotalRx () - it->ulOldTotalRx; + } + double expectedBytes = m_udpClientPktSize * (m_statsDuration.GetSeconds () / m_udpClientInterval.GetSeconds ()); + + NS_LOG_LOGIC ("expBytes = " << expectedBytes); + NS_LOG_LOGIC ("dlRx = " << dlRx); + NS_LOG_LOGIC ("ulRx = " << ulRx); + + // tolerance + if (it->dlSink) + { + NS_TEST_ASSERT_MSG_GT (dlRx, 0.500 * expectedBytes, "too few RX bytes in DL, ue=" << ueIndex << ", b=" << b); + } + if (it->ulSink) + { + NS_TEST_ASSERT_MSG_GT (ulRx, 0.500 * expectedBytes, "too few RX bytes in UL, ue=" << ueIndex << ", b=" << b); + } + ++b; + } +} + + +class LteX2HandoverMeasuresTestSuite : public TestSuite +{ +public: + LteX2HandoverMeasuresTestSuite (); +}; + + +LteX2HandoverMeasuresTestSuite::LteX2HandoverMeasuresTestSuite () + : TestSuite ("lte-x2-handover-measures", SYSTEM) +{ + std::string cel0name ("no ho"); + std::list cel0; + cel0.push_back (CheckPointEvent (Seconds (1), Seconds (50), Seconds (1), 0, 0)); + + std::string cel1name ("ho: 0 -> 1"); + std::list cel1; + cel1.push_back (CheckPointEvent (Seconds (1), Seconds (16.1), Seconds (1), 0, 0)); + // HO is performed between seconds 16 and 17 + cel1.push_back (CheckPointEvent (Seconds (17), Seconds (50), Seconds (1), 0, 1)); + + std::string cel2name ("ho: 0 -> 1 -> 2"); + std::list cel2; + cel2.push_back (CheckPointEvent (Seconds (1), Seconds (16.1), Seconds (1), 0, 0)); + // First HO is performed between seconds 16 and 17 + cel2.push_back (CheckPointEvent (Seconds (17), Seconds (26.1), Seconds (1), 0, 1)); + // Second HO is performed between seconds 26 and 27 + cel2.push_back (CheckPointEvent (Seconds (27), Seconds (50), Seconds (1), 0, 2)); + + std::string cel3name ("ho: 0 -> 1 -> 2 -> 3"); + std::list cel3; + cel3.push_back (CheckPointEvent (Seconds (1), Seconds (16.1), Seconds (1), 0, 0)); + // First HO is performed between seconds 16 and 17 + cel3.push_back (CheckPointEvent (Seconds (17), Seconds (26.1), Seconds (1), 0, 1)); + // Second HO is performed between seconds 26 and 27 + cel3.push_back (CheckPointEvent (Seconds (27), Seconds (36.1), Seconds (1), 0, 2)); + // Third HO is performed between seconds 36 and 37 + cel3.push_back (CheckPointEvent (Seconds (37), Seconds (50), Seconds (1), 0, 3)); + + std::vector schedulers; + schedulers.push_back ("ns3::RrFfMacScheduler"); +// schedulers.push_back ("ns3::PfFfMacScheduler"); + for (std::vector::iterator schedIt = schedulers.begin (); schedIt != schedulers.end (); ++schedIt) + { + int32_t useIdealRrc = 0; +// for (int32_t useIdealRrc = 1; useIdealRrc >= 0; --useIdealRrc) + { + // nEnbs, nUes, nDBearers, celist, name, useUdp, sched, admitHo, idealRrc +// AddTestCase (new LteX2HandoverMeasuresTestCase ( 2, 1, 0, cel1, cel1name, true, *schedIt, true, useIdealRrc)); +// AddTestCase (new LteX2HandoverMeasuresTestCase ( 2, 1, 1, cel1, cel1name, true, *schedIt, true, useIdealRrc)); +// AddTestCase (new LteX2HandoverMeasuresTestCase ( 2, 1, 2, cel1, cel1name, true, *schedIt, true, useIdealRrc)); // CRASH in lte-enb-rrc.cc, line=1916 + // AddTestCase (new LteX2HandoverMeasuresTestCase ( 2, 1, 0, cel0, cel0name, true, *schedIt, false, useIdealRrc)); + // AddTestCase (new LteX2HandoverMeasuresTestCase ( 2, 1, 1, cel0, cel0name, true, *schedIt, false, useIdealRrc)); + // AddTestCase (new LteX2HandoverMeasuresTestCase ( 2, 1, 2, cel0, cel0name, true, *schedIt, false, useIdealRrc)); + AddTestCase (new LteX2HandoverMeasuresTestCase ( 3, 1, 0, cel2, cel2name, true, *schedIt, true, useIdealRrc)); // CRASH in rr-ff-mac-scheduler.cc, line=1519 +// AddTestCase (new LteX2HandoverMeasuresTestCase ( 3, 1, 1, cel2, cel2name, true, *schedIt, true, useIdealRrc)); +// AddTestCase (new LteX2HandoverMeasuresTestCase ( 3, 1, 2, cel2, cel2name, true, *schedIt, true, useIdealRrc)); + // AddTestCase (new LteX2HandoverMeasuresTestCase ( 3, 1, 0, cel0, cel0name, true, *schedIt, false, useIdealRrc)); + // AddTestCase (new LteX2HandoverMeasuresTestCase ( 3, 1, 1, cel0, cel0name, true, *schedIt, false, useIdealRrc)); + // AddTestCase (new LteX2HandoverMeasuresTestCase ( 3, 1, 2, cel0, cel0name, true, *schedIt, false, useIdealRrc)); +// AddTestCase (new LteX2HandoverMeasuresTestCase ( 4, 1, 0, cel3, cel3name, true, *schedIt, true, useIdealRrc)); +// AddTestCase (new LteX2HandoverMeasuresTestCase ( 4, 1, 1, cel3, cel3name, true, *schedIt, true, useIdealRrc)); +// AddTestCase (new LteX2HandoverMeasuresTestCase ( 4, 1, 2, cel3, cel3name, true, *schedIt, true, useIdealRrc)); + } + } +} + +static LteX2HandoverMeasuresTestSuite g_lteX2HandoverMeasuresTestSuiteInstance; + + +} // namespace ns3 diff --git a/src/lte/wscript b/src/lte/wscript index bbf1fc393..111dab9b5 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -89,7 +89,7 @@ def build(bld): 'model/lte-harq-phy.cc', 'model/epc-mme.cc', 'model/lte-asn1-header.cc', - 'model/lte-rrc-header.cc', + 'model/lte-rrc-header.cc', ] module_test = bld.create_ns3_module_test_library('lte') @@ -123,6 +123,7 @@ def build(bld): 'test/lte-test-harq.cc', 'test/test-lte-rrc.cc', 'test/test-lte-x2-handover.cc', + 'test/test-lte-x2-handover-measures.cc', 'test/test-asn1-encoding.cc', 'test/lte-test-ue-measurements.cc', ] @@ -217,7 +218,7 @@ def build(bld): 'model/lte-harq-phy.h', 'model/epc-mme.h', 'model/lte-asn1-header.h', - 'model/lte-rrc-header.h', + 'model/lte-rrc-header.h', ] if (bld.env['ENABLE_EXAMPLES']):