diff -r 23aa339aecd6 src/lte/helper/lte-helper.cc --- a/src/lte/helper/lte-helper.cc Tue Feb 20 12:52:37 2018 +0100 +++ b/src/lte/helper/lte-helper.cc Thu Feb 22 12:07:27 2018 +0100 @@ -518,12 +518,17 @@ Ptr dev = m_enbNetDeviceFactory.Create (); Ptr handoverAlgorithm = m_handoverAlgorithmFactory.Create (); - if (m_componentCarrierPhyParams.size() == 0) + //Cc map size should be less than or equal to m_noOfCcs. We need <= since for the first eNB its size would be zero. + + if (m_componentCarrierPhyParams.size() <= m_noOfCcs) { DoComponentCarrierConfigure (dev->GetUlEarfcn (), dev->GetDlEarfcn (), dev->GetUlBandwidth (), dev->GetDlBandwidth ()); } - NS_ASSERT_MSG(m_componentCarrierPhyParams.size()!=0, "Cannot create enb ccm map."); + //After DoComponentCarrierConfigure call, size of m_componentCarrierPhyParams should be equal to m_noOfCcs. + //This is to check that we overwrite m_componentCarrierPhyParams for every eNB and catch any undesirable insert operation on this map. + NS_ABORT_MSG_IF (m_componentCarrierPhyParams.size() != m_noOfCcs,"Cc map size should be == m_noOfCcs. Map Size = "< InstallEnbDevice()"); Ptr dev = m_ueNetDeviceFactory.Create (); + + if (m_componentCarrierPhyParams.size() <= m_noOfCcs) + { + // We initialize the component carriers with following default values for the sake of initializing/configuring + // MACs and PHYs of each component carrier. These values should be updated once the UE is attached to the + // eNB and receives RRC Connection Reconfiguration message. In case of primary carrier or a single carrier, these + // values will be updated once the UE will receive SIB2 and MIB. + + DoComponentCarrierConfigure (dev->GetDlEarfcn () + 18000, dev->GetDlEarfcn (), 25, 25); + } + + //After DoComponentCarrierConfigure call, size of m_componentCarrierPhyParams should be equal to m_noOfCcs. + //This is to check that we overwrite m_componentCarrierPhyParams for every UE and catch any undesirable insert operation on this map. + NS_ABORT_MSG_IF (m_componentCarrierPhyParams.size() != m_noOfCcs,"Cc map size should be == m_noOfCcs. Map Size = "< m_noOfCcs, "Cc map size should be <= m_noOfCcs. We should keep over wrting it for every configuration. Size of the map = "<::iterator it = nonCec.sCellsToAddModList.begin(); it!=nonCec.sCellsToAddModList.end(); it++) { LteRrcSap::SCellToAddMod scell = *it; @@ -1258,6 +1264,8 @@ m_cphySapProvider.at (ccId)->SetPa (paDouble); m_cphySapProvider.at (ccId)->SetSrsConfigurationIndex (srsIndex); } + + m_sCarrierConfiguredTrace(this,m_sCellToAddModList); //Fire the trace } void diff -r 23aa339aecd6 src/lte/model/lte-ue-rrc.h --- a/src/lte/model/lte-ue-rrc.h Tue Feb 20 12:52:37 2018 +0100 +++ b/src/lte/model/lte-ue-rrc.h Thu Feb 22 12:07:27 2018 +0100 @@ -352,6 +352,15 @@ (uint64_t imsi, uint16_t cellId, uint16_t rnti, State oldState, State newState); + /** + * TracedCallback signature for secondary carrier configuration events. + * + * \param [in] Pointer to UE RRC + * \param [in] List of LteRrcSap::SCellToAddMod + */ + typedef void (* SCarrierConfiguredCallback) + (Ptr, std::list); + private: @@ -768,7 +777,7 @@ uint32_t m_dlEarfcn; /**< Downlink carrier frequency. */ uint32_t m_ulEarfcn; /**< Uplink carrier frequency. */ - + std::list m_sCellToAddModList; /**< List of LteRrcSap::SCellToAddMod structures. */ /** * The `MibReceived` trace source. Fired upon reception of Master Information * Block. Exporting IMSI, the serving cell ID, RNTI, and the source cell ID. @@ -842,6 +851,12 @@ * procedure. Exporting IMSI, cell ID, and RNTI. */ TracedCallback m_handoverEndErrorTrace; + /** + * The `SCarrierConfigured` trace source. Fired after the configuration + * of secondary carriers received through RRC Connection Reconfiguration + * message. + */ + TracedCallback, std::list> m_sCarrierConfiguredTrace; /// True if a connection request by upper layers is pending. bool m_connectionPending; diff -r 23aa339aecd6 src/lte/test/lte-test-carrier-aggregation-configuration.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lte/test/lte-test-carrier-aggregation-configuration.cc Thu Feb 22 12:07:27 2018 +0100 @@ -0,0 +1,371 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2016 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 + * + * Author: Zoraze Ali + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace ns3; + +/** + * This test is to verify following two things, + * + * 1. When CA is enabled and UE carriers configuration is different than the default one, we check that + * the UE is configured properly once it receives RRC Connection Reconfiguration message from eNB. + * + * 2. A user can configure 2 or more eNBs and UEs with different configuration parameters, i.e, + * each eNB and UE can have different EARFCN and Bandwidths and a UE connects to an eNB with similar DL EARFCN. + * Here we check it with CA enabled but the end results will be the same if CA is not enabled and we + * have more than one eNBs and UEs with different configurations. + * + * Since we do not need EPC to test the configuration, this test only simulates the LTE radio access with + * RLC SM. + * + * Test 1 tests that the UE is configured properly after receiving RRC Connection Reconfiguration message + * from the eNB, which will overwrite UE default configuration done in LteHelper for the sake of + * creating PHY and MAC instances equal to the number of component carriers. + * + * Test 2 tests that in a simulation scenario every eNB or UE can be configured with different EARFCNs and + * Bandwidths. This will check that the eNBs and UEs configuration is not static, as reported in + * BUG 2840. + * + */ +struct ConfigToCheck +{ + uint16_t m_dlBandwidthToCheck; + uint16_t m_ulBandwidthToCheck; + uint32_t m_dlEarfcnToCheck; + uint32_t m_ulEarfcnToCheck; +}; + +NS_LOG_COMPONENT_DEFINE ("TestCarrierAggregationConfig"); + +class CarrierAggregationConfigTestCase : public TestCase +{ +public: + + + /** + * Constructor + * + * \param numberOfNodes, Total Number of eNBs and UEs + * \param configToCheck, Vector containing all the configurations to check + * \param simulationDuration, Duration of the simulation + */ + CarrierAggregationConfigTestCase (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector configToCheck, Time simulationDuration) + : TestCase (BuildNameString (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration)), + m_numberOfNodes(numberOfNodes), + m_numberOfComponentCarriers(numberOfComponentCarriers), + m_configToCheck(configToCheck), + m_simulationDuration (simulationDuration) + { + m_connectionCounter = 0.0; + } + +private: + + virtual void DoRun (void); + + std::string BuildNameString (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector configToCheck, Time simulationDuration); + void Evaluate (std::string context, Ptr ueRrc, std::list sCellToAddModList); + std::vector> EquallySpacedCcs (); + + uint32_t m_numberOfNodes; + uint16_t m_numberOfComponentCarriers; + std::vector m_configToCheck; + uint32_t m_connectionCounter; + Time m_simulationDuration; + std::vector> m_configToCheckContainer; +}; + +std::string +CarrierAggregationConfigTestCase::BuildNameString (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector configToCheck, Time simulationDuration) +{ + std::ostringstream oss; + oss <<" number of nodes "<> +CarrierAggregationConfigTestCase::EquallySpacedCcs () +{ + std::vector> configToCheckContainer; + + for(auto &it:m_configToCheck) + { + std::map< uint16_t, ConfigToCheck > ccmap; + uint32_t ulEarfcn = it.m_ulEarfcnToCheck; + uint32_t dlEarfcn = it.m_dlEarfcnToCheck; + uint32_t maxBandwidthRb = std::max (it.m_ulBandwidthToCheck, it.m_dlBandwidthToCheck); + + // Convert bandwidth from RBs to kHz + uint32_t maxBandwidthKhz = LteSpectrumValueHelper::GetChannelBandwidth(maxBandwidthRb) / 1e3; + + for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++) + { + // Make sure we stay within the same band. + if (LteSpectrumValueHelper::GetUplinkCarrierBand (ulEarfcn) != + LteSpectrumValueHelper::GetUplinkCarrierBand (it.m_ulEarfcnToCheck) + || LteSpectrumValueHelper::GetDownlinkCarrierBand (dlEarfcn) != + LteSpectrumValueHelper::GetDownlinkCarrierBand (it.m_dlEarfcnToCheck)) + { + NS_FATAL_ERROR ("Band is not wide enough to allocate " << +m_numberOfComponentCarriers << " CCs"); + } + + ConfigToCheck cc; + cc.m_dlBandwidthToCheck = it.m_dlBandwidthToCheck; + cc.m_dlEarfcnToCheck = dlEarfcn; + cc.m_ulBandwidthToCheck = it.m_ulBandwidthToCheck; + cc.m_ulEarfcnToCheck = ulEarfcn; + + ccmap.insert (std::pair(i, cc)); + + NS_LOG_INFO("Uplink Bandwidth: " << it.m_ulBandwidthToCheck << + ", Downlink Bandwidth: " << it.m_dlBandwidthToCheck << + ", Uplink Earfcn: " << ulEarfcn << + ", Downlink Earfcn: " << dlEarfcn); + + // The spacing between the center frequencies of two contiguous CCs should be multiple of 300 kHz. + // Round spacing up to 300 kHz. + uint32_t frequencyShift = 300 * (1 + (maxBandwidthKhz - 1) / 300); + + // Unit of EARFCN corresponds to 100kHz. + uint32_t earfcnShift = frequencyShift / 100; + ulEarfcn += earfcnShift; + dlEarfcn += earfcnShift; + } + + configToCheckContainer.push_back(ccmap); + } + + return configToCheckContainer; +} + +void +CarrierAggregationConfigTestCase::Evaluate (std::string context, Ptr ueRrc, std::list sCellToAddModList) +{ + NS_LOG_INFO(Simulator::Now ().GetSeconds () <<" "<< "Secondary carriers configured"); + + uint16_t cellId = ueRrc->GetCellId(); + NS_LOG_INFO("cellId : "<(ueRrc->GetUlBandwidth()) << + ", Primary Carrier Downlink Bandwidth: " << static_cast(ueRrc->GetUlBandwidth()) << + ", Primary Carrier Uplink Earfcn: " << ueRrc->GetUlEarfcn() << + ", Primary Carrier Downlink Earfcn: " << ueRrc->GetUlEarfcn()); + + for(auto &list:sCellToAddModList) + { + LteRrcSap::SCellToAddMod scell = list; + + NS_LOG_INFO("Secondary Carrier Uplink Bandwidth: " << static_cast(scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth)<< + ", Secondary Carrier Downlink Bandwidth: " << static_cast(scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth) << + ", Secondary Carrier Uplink Earfcn: " << scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq << + ", Secondary Carrier Downlink Earfcn: " << scell.cellIdentification.dlCarrierFreq); + } + + ConfigToCheck pCConfig = configToCheckMap[0]; //Primary Carrier + ConfigToCheck sCConfig; //Secondary Carriers + + NS_TEST_ASSERT_MSG_EQ(pCConfig.m_dlBandwidthToCheck,static_cast(ueRrc->GetDlBandwidth()),"Primary Carrier DL bandwidth configuration failed"); + NS_TEST_ASSERT_MSG_EQ(pCConfig.m_ulBandwidthToCheck,static_cast(ueRrc->GetUlBandwidth()),"Primary Carrier UL bandwidth configuration failed"); + NS_TEST_ASSERT_MSG_EQ(pCConfig.m_dlEarfcnToCheck, ueRrc->GetDlEarfcn(),"Primary Carrier DL EARFCN configuration failed"); + NS_TEST_ASSERT_MSG_EQ(pCConfig.m_ulEarfcnToCheck, ueRrc->GetUlEarfcn(),"Primary Carrier UL EARFCN configuration failed"); + + uint32_t ConfigToCheckMapIndex = 1; + + for(auto &list:sCellToAddModList) + { + LteRrcSap::SCellToAddMod scell = list; + sCConfig = configToCheckMap[ConfigToCheckMapIndex]; + + NS_TEST_ASSERT_MSG_EQ(sCConfig.m_dlBandwidthToCheck, static_cast(scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth),"Secondary Carrier DL bandwidth configuration failed"); + NS_TEST_ASSERT_MSG_EQ(sCConfig.m_ulBandwidthToCheck,static_cast(scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth),"Secondary Carrier UL bandwidth configuration failed"); + NS_TEST_ASSERT_MSG_EQ(sCConfig.m_dlEarfcnToCheck, scell.cellIdentification.dlCarrierFreq,"Secondary Carrier DL EARFCN configuration failed"); + NS_TEST_ASSERT_MSG_EQ(sCConfig.m_ulEarfcnToCheck, scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq,"Secondary Carrier UL EARFCN configuration failed"); + ConfigToCheckMapIndex++; + } + +} + +void +CarrierAggregationConfigTestCase::DoRun () +{ + Config::SetDefault ("ns3::LteHelper::UseCa", BooleanValue (true)); + Config::SetDefault ("ns3::LteHelper::NumberOfComponentCarriers", UintegerValue (m_numberOfComponentCarriers)); + Config::SetDefault ("ns3::LteHelper::EnbComponentCarrierManager", StringValue ("ns3::RrComponentCarrierManager")); + + int64_t stream = 1; + + Ptr lteHelper = CreateObject (); + // Create Nodes: eNodeB and UE + NodeContainer enbNodes; + NodeContainer ueNodes; + enbNodes.Create (m_numberOfNodes); + ueNodes.Create (m_numberOfNodes); + + uint32_t totalNumberOfNodes = enbNodes.GetN() + ueNodes.GetN(); + + // Install Mobility Model + Ptr positionAlloc = CreateObject (); + for (uint16_t i = 0; i < totalNumberOfNodes; i++) + { + positionAlloc->Add (Vector(2 * i, 0, 0)); + } + + NS_LOG_INFO(" Position vector size "<GetSize()); + + MobilityHelper mobility; + mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); + mobility.SetPositionAllocator(positionAlloc); + + for(uint32_t n = 0; n < m_numberOfNodes; ++n) + { + mobility.Install(enbNodes.Get(n)); + mobility.Install(ueNodes.Get(n)); + } + + ConfigToCheck Configurations; + NetDeviceContainer enbDevs; + NetDeviceContainer ueDevs; + + // Set bandwidth, EARFCN and install nodes (eNB and UE) + for(uint32_t i = 0; i < m_configToCheck.size(); ++i) + { + Configurations = m_configToCheck[i]; + + lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (Configurations.m_dlBandwidthToCheck)); + lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (Configurations.m_ulBandwidthToCheck)); + lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (Configurations.m_dlEarfcnToCheck)); + lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (Configurations.m_ulEarfcnToCheck)); + lteHelper->SetUeDeviceAttribute ("DlEarfcn", UintegerValue (Configurations.m_dlEarfcnToCheck)); + enbDevs.Add(lteHelper->InstallEnbDevice (enbNodes.Get(i))); + lteHelper->AssignStreams (enbDevs, stream); + ueDevs.Add(lteHelper->InstallUeDevice (ueNodes.Get(i))); + lteHelper->AssignStreams (ueDevs, stream); + } + + + //Calculate the DlBandwidth, UlBandwidth, DlEarfcn and UlEarfcn to which the values from UE RRC would be compared + + m_configToCheckContainer = EquallySpacedCcs (); + + // Attach a UE to a eNB + for(uint32_t k = 0; k < m_numberOfNodes; ++k) + { + lteHelper->Attach (ueDevs.Get(k), enbDevs.Get (k)); + } + + // Activate a data radio bearer + enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; + EpsBearer bearer (q); + lteHelper->ActivateDataRadioBearer (ueDevs, bearer); + + Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/SCarrierConfigured", MakeCallback (&CarrierAggregationConfigTestCase::Evaluate, this)); + + Simulator::Stop (m_simulationDuration); + + Simulator::Run (); + + NS_TEST_ASSERT_MSG_EQ(m_connectionCounter, ueNodes.GetN(),"Not all the UEs were connected"); + + Simulator::Destroy (); +} + + +class CarrierAggregationConfigTestSuite : public TestSuite +{ +public: + CarrierAggregationConfigTestSuite (); +}; + +CarrierAggregationConfigTestSuite::CarrierAggregationConfigTestSuite () + : TestSuite ("carrier-aggregation-config-test", SYSTEM) +{ + //LogComponentEnable("TestCarrierAggregationConfig", LOG_LEVEL_ALL); + + std::vector configToCheck; + + //Test1 with 1 eNB and 1 UE. We put a configuration different than the default configuration done in LteHelper for the sake of + //creating PHY and MAC instances equal to the number of component carriers. + + ConfigToCheck configToCheckTest1; + configToCheckTest1.m_dlBandwidthToCheck = 50; + configToCheckTest1.m_ulBandwidthToCheck = 50; + configToCheckTest1.m_dlEarfcnToCheck = 300; + configToCheckTest1.m_ulEarfcnToCheck = 300+18000; + configToCheck.push_back(configToCheckTest1); + uint32_t numberOfNodes = 1; + uint16_t numberOfComponentCarriers = 2; + Time simulationDuration = Seconds(1); + + AddTestCase (new CarrierAggregationConfigTestCase (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration), TestCase::QUICK); + + configToCheck.erase(configToCheck.begin(), configToCheck.end()); + + //Test2 with 2 eNBs and 2 UEs. We decrease the bandwidth so not to exceed maximum band bandwidth of 20 MHz + configToCheckTest1.m_dlBandwidthToCheck = 25; + configToCheckTest1.m_ulBandwidthToCheck = 25; + configToCheckTest1.m_dlEarfcnToCheck = 300; + configToCheckTest1.m_ulEarfcnToCheck = 300+18000; + configToCheck.push_back(configToCheckTest1); + + ConfigToCheck configToCheckTest2; + configToCheckTest2.m_dlBandwidthToCheck = 25; + configToCheckTest2.m_ulBandwidthToCheck = 25; + configToCheckTest2.m_dlEarfcnToCheck = 502; + configToCheckTest2.m_ulEarfcnToCheck = 502+18000; + configToCheck.push_back(configToCheckTest2); + numberOfNodes = 2; + simulationDuration = Seconds(2); + + AddTestCase (new CarrierAggregationConfigTestCase (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration), TestCase::QUICK); +} + +static CarrierAggregationConfigTestSuite g_carrierAggregationConfigTestSuite; diff -r 23aa339aecd6 src/lte/wscript --- a/src/lte/wscript Tue Feb 20 12:52:37 2018 +0100 +++ b/src/lte/wscript Thu Feb 22 12:07:27 2018 +0100 @@ -191,7 +191,8 @@ 'test/lte-simple-spectrum-phy.cc', 'test/lte-test-carrier-aggregation.cc', 'test/lte-test-aggregation-throughput-scale.cc', - 'test/lte-test-ipv6-routing.cc' + 'test/lte-test-ipv6-routing.cc', + 'test/lte-test-carrier-aggregation-configuration.cc' ] headers = bld(features='ns3header')