diff --git a/src/lte/test/lte-test-secondary-cell-selection.cc b/src/lte/test/lte-test-secondary-cell-selection.cc new file mode 100644 index 000000000..7ab334356 --- /dev/null +++ b/src/lte/test/lte-test-secondary-cell-selection.cc @@ -0,0 +1,196 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 Alexander Krotov + * + * 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 + * + * Author: Alexander Krotov + * + */ + +#include "lte-test-secondary-cell-selection.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("LteSecondaryCellSelectionTest"); + +/* + * Test Suite + */ + +LteSecondaryCellSelectionTestSuite::LteSecondaryCellSelectionTestSuite () + : TestSuite ("lte-secondary-cell-selection", SYSTEM) +{ + // REAL RRC PROTOCOL + + AddTestCase (new LteSecondaryCellSelectionTestCase ("EPC, real RRC, RngRun=1", false, 1), TestCase::QUICK); + + // IDEAL RRC PROTOCOL + + AddTestCase (new LteSecondaryCellSelectionTestCase ("EPC, ideal RRC, RngRun=1", true, 1), TestCase::QUICK); + +} // end of LteSecondaryCellSelectionTestSuite::LteSecondaryCellSelectionTestSuite () + +static LteSecondaryCellSelectionTestSuite g_lteSecondaryCellSelectionTestSuite; + +/* + * Test Case + */ + +LteSecondaryCellSelectionTestCase::LteSecondaryCellSelectionTestCase ( + std::string name, bool isIdealRrc, int64_t rngRun) + : TestCase (name), + m_isIdealRrc (isIdealRrc), + m_rngRun (rngRun) +{ + NS_LOG_FUNCTION (this << GetName ()); +} + + +LteSecondaryCellSelectionTestCase::~LteSecondaryCellSelectionTestCase () +{ + NS_LOG_FUNCTION (this << GetName ()); +} + +void +LteSecondaryCellSelectionTestCase::DoRun () +{ + NS_LOG_FUNCTION (this << GetName ()); + + Config::SetGlobal ("RngRun", IntegerValue (m_rngRun)); + + // Create helpers. + auto lteHelper = CreateObject (); + lteHelper->SetAttribute ("PathlossModel", TypeIdValue (ns3::FriisSpectrumPropagationLossModel::GetTypeId ())); + lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (m_isIdealRrc)); + lteHelper->SetAttribute ("NumberOfComponentCarriers", UintegerValue (2)); + + auto epcHelper = CreateObject (); + lteHelper->SetEpcHelper (epcHelper); + + auto cch = CreateObject (); + cch->SetUlEarfcn (100 + 18000); + cch->SetDlEarfcn (100); + cch->SetUlBandwidth (25); + cch->SetDlBandwidth (25); + cch->SetNumberOfComponentCarriers (2); + + const auto ccm = cch->EquallySpacedCcs (); + lteHelper->SetCcPhyParams (ccm); + + // Create nodes. + auto enbNode = CreateObject (); + NodeContainer ueNodes; + ueNodes.Create (2); + + MobilityHelper mobility; + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (enbNode); + mobility.Install (ueNodes); + + // Physical layer. + auto enbDev = DynamicCast (lteHelper->InstallEnbDevice (enbNode).Get (0)); + auto ueDevs = lteHelper->InstallUeDevice (ueNodes); + + // Network layer. + InternetStackHelper internet; + internet.Install (ueNodes); + epcHelper->AssignUeIpv4Address (ueDevs); + + for (auto &it: ccm) + { + std::cerr << "Assign " << it.second.GetDlEarfcn () << std::endl; + DynamicCast (ueDevs.Get (it.first))->SetDlEarfcn (it.second.GetDlEarfcn ()); + } + + // Enable Idle mode cell selection. + lteHelper->Attach (ueDevs); + + // Connect to trace sources in UEs + Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/StateTransition", + MakeCallback (&LteSecondaryCellSelectionTestCase::StateTransitionCallback, + this)); + Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/InitialSecondaryCellSelectionEndOk", + MakeCallback (&LteSecondaryCellSelectionTestCase::InitialSecondaryCellSelectionEndOkCallback, + this)); + Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionEstablished", + MakeCallback (&LteSecondaryCellSelectionTestCase::ConnectionEstablishedCallback, + this)); + + // Run simulation. + Simulator::Stop (Seconds (2.0)); + Simulator::Run (); + + for (auto &it: enbDev->GetCcMap ()) + { + auto ueDev = DynamicCast (ueDevs.Get (it.first)); + uint16_t expectedCellId = it.second->GetCellId (); + uint16_t actualCellId = ueDev->GetRrc ()->GetCellId (); + NS_TEST_ASSERT_MSG_EQ (expectedCellId, actualCellId, "IMSI " << ueDev->GetImsi () << " has attached to an unexpected cell"); + + NS_TEST_ASSERT_MSG_EQ (m_lastState.at (ueDev->GetImsi ()), + LteUeRrc::CONNECTED_NORMALLY, + "UE " << ueDev->GetImsi () + << " is not at CONNECTED_NORMALLY state"); + } + + // Destroy simulator. + Simulator::Destroy (); +} // end of void LteSecondaryCellSelectionTestCase::DoRun () + + +void +LteSecondaryCellSelectionTestCase::StateTransitionCallback ( + std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti, + LteUeRrc::State oldState, LteUeRrc::State newState) +{ + NS_LOG_FUNCTION (this << imsi << cellId << rnti << oldState << newState); + m_lastState[imsi] = newState; +} + + +void +LteSecondaryCellSelectionTestCase::InitialSecondaryCellSelectionEndOkCallback ( + std::string context, uint64_t imsi, uint16_t cellId) +{ + NS_LOG_FUNCTION (this << imsi << cellId); +} + +void +LteSecondaryCellSelectionTestCase::ConnectionEstablishedCallback ( + std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti) +{ + NS_LOG_FUNCTION (this << imsi << cellId << rnti); +} diff --git a/src/lte/test/lte-test-secondary-cell-selection.h b/src/lte/test/lte-test-secondary-cell-selection.h new file mode 100644 index 000000000..014c65b86 --- /dev/null +++ b/src/lte/test/lte-test-secondary-cell-selection.h @@ -0,0 +1,113 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 Alexander Krotov + * + * 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 + * + * Author: Alexander Krotov + * + */ + +#ifndef LTE_TEST_SECONDARY_CELL_SELECTION_H +#define LTE_TEST_SECONDARY_CELL_SELECTION_H + +#include +#include +#include +#include +#include +#include + +using namespace ns3; + +/** + * \brief Test suite for executing the secondary cell selection test cases. + * + * \sa ns3::LteSecondaryCellSelectionTestCase + */ +class LteSecondaryCellSelectionTestSuite : public TestSuite +{ +public: + LteSecondaryCellSelectionTestSuite (); +}; + + + + +/** + * \ingroup lte + * + * \brief Testing the initial cell selection procedure by UE at IDLE state in + * the beginning of simulation with multiple component carriers. + */ +class LteSecondaryCellSelectionTestCase : public TestCase +{ +public: + /** + * \brief Creates an instance of the initial cell selection test case. + * \param name name of this test + * \param isIdealRrc if true, simulation uses Ideal RRC protocol, otherwise + * simulation uses Real RRC protocol + * \param rngRun the number of run to be used by the random number generator + */ + LteSecondaryCellSelectionTestCase (std::string name, bool isIdealRrc, int64_t rngRun); + + virtual ~LteSecondaryCellSelectionTestCase (); + +private: + /** + * \brief Setup the simulation according to the configuration set by the + * class constructor, run it, and verify the result. + */ + virtual void DoRun (); + + /** + * \brief State transition callback function + * \param context the context string + * \param imsi the IMSI + * \param cellId the cell ID + * \param rnti the RNTI + * \param oldState the old state + * \param newState the new state + */ + void StateTransitionCallback (std::string context, uint64_t imsi, + uint16_t cellId, uint16_t rnti, + LteUeRrc::State oldState, LteUeRrc::State newState); + /** + * \brief Initial cell selection end ok callback function + * \param context the context string + * \param imsi the IMSI + * \param cellId the cell ID + */ + void InitialSecondaryCellSelectionEndOkCallback (std::string context, uint64_t imsi, + uint16_t cellId); + /** + * \brief Connection established callback function + * \param context the context string + * \param imsi the IMSI + * \param cellId the cell ID + * \param rnti the RNTI + */ + void ConnectionEstablishedCallback (std::string context, uint64_t imsi, + uint16_t cellId, uint16_t rnti); + + bool m_isIdealRrc; ///< whether the LTE is configured to use ideal RRC + int64_t m_rngRun; ///< rng run + + /// The current UE RRC state. + std::map m_lastState; + +}; // end of class LteSecondaryCellSelectionTestCase + +#endif /* LTE_TEST_SECONDARY_CELL_SELECTION_H */ diff --git a/src/lte/wscript b/src/lte/wscript index e5e14836d..9db4eddc7 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -178,6 +178,7 @@ def build(bld): 'test/test-asn1-encoding.cc', 'test/lte-test-ue-measurements.cc', 'test/lte-test-cell-selection.cc', + 'test/lte-test-secondary-cell-selection.cc', 'test/test-lte-handover-delay.cc', 'test/test-lte-handover-target.cc', 'test/lte-test-deactivate-bearer.cc',