|
|
| 1 |
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
| 2 |
/* |
| 3 |
* Copyright (c) 2016 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) |
| 4 |
* |
| 5 |
* This program is free software; you can redistribute it and/or modify |
| 6 |
* it under the terms of the GNU General Public License version 2 as |
| 7 |
* published by the Free Software Foundation; |
| 8 |
* |
| 9 |
* This program is distributed in the hope that it will be useful, |
| 10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 |
* GNU General Public License for more details. |
| 13 |
* |
| 14 |
* You should have received a copy of the GNU General Public License |
| 15 |
* along with this program; if not, write to the Free Software |
| 16 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 |
* |
| 18 |
* Author: Zoraze Ali <zoraze.ali@cttc.es> |
| 19 |
* |
| 20 |
*/ |
| 21 |
|
| 22 |
#include <ns3/object.h> |
| 23 |
#include <ns3/log.h> |
| 24 |
#include <ns3/test.h> |
| 25 |
#include <ns3/simulator.h> |
| 26 |
#include <ns3/ptr.h> |
| 27 |
#include <ns3/constant-position-mobility-model.h> |
| 28 |
#include <ns3/node-container.h> |
| 29 |
#include <ns3/mobility-helper.h> |
| 30 |
#include <ns3/net-device-container.h> |
| 31 |
#include <ns3/lte-ue-rrc.h> |
| 32 |
#include <ns3/lte-helper.h> |
| 33 |
#include <ns3/lte-spectrum-value-helper.h> |
| 34 |
#include <ns3/callback.h> |
| 35 |
|
| 36 |
|
| 37 |
using namespace ns3; |
| 38 |
|
| 39 |
/** |
| 40 |
* This test is to verify following two things, |
| 41 |
* |
| 42 |
* 1. When CA is enabled and UE carriers configuration is different than the default one, we check that |
| 43 |
* the UE is configured properly once it receives RRC Connection Reconfiguration message from eNB. |
| 44 |
* |
| 45 |
* 2. A user can configure 2 or more eNBs and UEs with different configuration parameters, i.e, |
| 46 |
* each eNB and UE can have different EARFCN and Bandwidths and a UE connects to an eNB with similar DL EARFCN. |
| 47 |
* Here we check it with CA enabled but the end results will be the same if CA is not enabled and we |
| 48 |
* have more than one eNBs and UEs with different configurations. |
| 49 |
* |
| 50 |
* Since we do not need EPC to test the configuration, this test only simulates the LTE radio access with |
| 51 |
* RLC SM. |
| 52 |
* |
| 53 |
* Test 1 tests that the UE is configured properly after receiving RRC Connection Reconfiguration message |
| 54 |
* from the eNB, which will overrides UE default configuration done in LteHelper for the sake of |
| 55 |
* creating PHY and MAC instances equal to the number of component carriers. |
| 56 |
* |
| 57 |
* Test 2 tests that in a simulation scenario every eNB or UE can be configured with different EARFCNs and |
| 58 |
* Bandwidths. This will check that the eNBs and UEs configuration is not static, as reported in |
| 59 |
* BUG 2840. |
| 60 |
* |
| 61 |
*/ |
| 62 |
struct ConfigToCheck |
| 63 |
{ |
| 64 |
uint16_t m_dlBandwidthToCheck; |
| 65 |
uint16_t m_ulBandwidthToCheck; |
| 66 |
uint32_t m_dlEarfcnToCheck; |
| 67 |
uint32_t m_ulEarfcnToCheck; |
| 68 |
}; |
| 69 |
|
| 70 |
NS_LOG_COMPONENT_DEFINE ("TestCarrierAggregationConfig"); |
| 71 |
|
| 72 |
class CarrierAggregationConfigTestCase : public TestCase |
| 73 |
{ |
| 74 |
public: |
| 75 |
|
| 76 |
|
| 77 |
/** |
| 78 |
* Constructor |
| 79 |
* |
| 80 |
* \param numberOfNodes, Total Number of eNBs and UEs |
| 81 |
* \param configToCheck, Vector containing all the configurations to check |
| 82 |
* \param simulationDuration, Duration of the simulation |
| 83 |
*/ |
| 84 |
CarrierAggregationConfigTestCase (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector<ConfigToCheck> configToCheck, Time simulationDuration) |
| 85 |
: TestCase (BuildNameString (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration)), |
| 86 |
m_numberOfNodes(numberOfNodes), |
| 87 |
m_numberOfComponentCarriers(numberOfComponentCarriers), |
| 88 |
m_configToCheck(configToCheck), |
| 89 |
m_simulationDuration (simulationDuration) |
| 90 |
{ |
| 91 |
m_connectionCounter = 0.0; |
| 92 |
} |
| 93 |
|
| 94 |
private: |
| 95 |
|
| 96 |
virtual void DoRun (void); |
| 97 |
|
| 98 |
std::string BuildNameString (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector<ConfigToCheck> configToCheck, Time simulationDuration); |
| 99 |
void Evaluate (std::string context, Ptr<LteUeRrc> ueRrc, std::list<LteRrcSap::SCellToAddMod> sCellToAddModList); |
| 100 |
std::vector<std::map< uint16_t, ConfigToCheck >> EquallySpacedCcs (); |
| 101 |
|
| 102 |
uint32_t m_numberOfNodes; |
| 103 |
uint16_t m_numberOfComponentCarriers; |
| 104 |
std::vector<ConfigToCheck> m_configToCheck; |
| 105 |
uint32_t m_connectionCounter; |
| 106 |
Time m_simulationDuration; |
| 107 |
std::vector<std::map< uint16_t, ConfigToCheck >> m_configToCheckContainer; |
| 108 |
}; |
| 109 |
|
| 110 |
std::string |
| 111 |
CarrierAggregationConfigTestCase::BuildNameString (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector<ConfigToCheck> configToCheck, Time simulationDuration) |
| 112 |
{ |
| 113 |
std::ostringstream oss; |
| 114 |
oss <<" number of nodes "<<numberOfNodes<< " number of component carriers "<<numberOfComponentCarriers<<" number of configurations to check "<<configToCheck.size()<<" simulation duration "<<simulationDuration; |
| 115 |
return oss.str (); |
| 116 |
} |
| 117 |
|
| 118 |
std::vector<std::map< uint16_t, ConfigToCheck >> |
| 119 |
CarrierAggregationConfigTestCase::EquallySpacedCcs () |
| 120 |
{ |
| 121 |
std::vector<std::map< uint16_t, ConfigToCheck >> configToCheckContainer; |
| 122 |
|
| 123 |
for(auto &it:m_configToCheck) |
| 124 |
{ |
| 125 |
std::map< uint16_t, ConfigToCheck > ccmap; |
| 126 |
uint32_t ulEarfcn = it.m_ulEarfcnToCheck; |
| 127 |
uint32_t dlEarfcn = it.m_dlEarfcnToCheck; |
| 128 |
uint32_t maxBandwidthRb = std::max<uint32_t> (it.m_ulBandwidthToCheck, it.m_dlBandwidthToCheck); |
| 129 |
|
| 130 |
// Convert bandwidth from RBs to kHz |
| 131 |
uint32_t maxBandwidthKhz = LteSpectrumValueHelper::GetChannelBandwidth(maxBandwidthRb) / 1e3; |
| 132 |
|
| 133 |
for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++) |
| 134 |
{ |
| 135 |
// Make sure we stay within the same band. |
| 136 |
if (LteSpectrumValueHelper::GetUplinkCarrierBand (ulEarfcn) != |
| 137 |
LteSpectrumValueHelper::GetUplinkCarrierBand (it.m_ulEarfcnToCheck) |
| 138 |
|| LteSpectrumValueHelper::GetDownlinkCarrierBand (dlEarfcn) != |
| 139 |
LteSpectrumValueHelper::GetDownlinkCarrierBand (it.m_dlEarfcnToCheck)) |
| 140 |
{ |
| 141 |
NS_FATAL_ERROR ("Band is not wide enough to allocate " << +m_numberOfComponentCarriers << " CCs"); |
| 142 |
} |
| 143 |
|
| 144 |
ConfigToCheck cc; |
| 145 |
cc.m_dlBandwidthToCheck = it.m_dlBandwidthToCheck; |
| 146 |
cc.m_dlEarfcnToCheck = dlEarfcn; |
| 147 |
cc.m_ulBandwidthToCheck = it.m_ulBandwidthToCheck; |
| 148 |
cc.m_ulEarfcnToCheck = ulEarfcn; |
| 149 |
|
| 150 |
ccmap.insert (std::pair<uint16_t, ConfigToCheck >(i, cc)); |
| 151 |
|
| 152 |
NS_LOG_INFO("Uplink Bandwidth: " << it.m_ulBandwidthToCheck << |
| 153 |
", Downlink Bandwidth: " << it.m_dlBandwidthToCheck << |
| 154 |
", Uplink Earfcn: " << ulEarfcn << |
| 155 |
", Downlink Earfcn: " << dlEarfcn); |
| 156 |
|
| 157 |
// The spacing between the center frequencies of two contiguous CCs should be multiple of 300 kHz. |
| 158 |
// Round spacing up to 300 kHz. |
| 159 |
uint32_t frequencyShift = 300 * (1 + (maxBandwidthKhz - 1) / 300); |
| 160 |
|
| 161 |
// Unit of EARFCN corresponds to 100kHz. |
| 162 |
uint32_t earfcnShift = frequencyShift / 100; |
| 163 |
ulEarfcn += earfcnShift; |
| 164 |
dlEarfcn += earfcnShift; |
| 165 |
} |
| 166 |
|
| 167 |
configToCheckContainer.push_back(ccmap); |
| 168 |
} |
| 169 |
|
| 170 |
return configToCheckContainer; |
| 171 |
} |
| 172 |
|
| 173 |
void |
| 174 |
CarrierAggregationConfigTestCase::Evaluate (std::string context, Ptr<LteUeRrc> ueRrc, std::list<LteRrcSap::SCellToAddMod> sCellToAddModList) |
| 175 |
{ |
| 176 |
NS_LOG_INFO(Simulator::Now ().GetSeconds () <<" "<< "Secondary carriers configured"); |
| 177 |
|
| 178 |
uint16_t cellId = ueRrc->GetCellId(); |
| 179 |
NS_LOG_INFO("cellId : "<<cellId); |
| 180 |
NS_LOG_INFO("m_configToCheckContainer size = "<<m_configToCheckContainer.size()); |
| 181 |
|
| 182 |
++m_connectionCounter; |
| 183 |
|
| 184 |
std::map< uint16_t, ConfigToCheck > configToCheckMap; |
| 185 |
|
| 186 |
if(cellId==1) |
| 187 |
{ |
| 188 |
configToCheckMap = m_configToCheckContainer[cellId-1]; |
| 189 |
} |
| 190 |
else |
| 191 |
{ |
| 192 |
uint16_t n1 = std::max(cellId, m_numberOfComponentCarriers); |
| 193 |
uint16_t n2 = std::min(cellId, m_numberOfComponentCarriers); |
| 194 |
configToCheckMap = m_configToCheckContainer[n1-n2]; |
| 195 |
} |
| 196 |
|
| 197 |
|
| 198 |
NS_LOG_INFO("Primary Carrier Uplink Bandwidth: " << static_cast<uint16_t>(ueRrc->GetUlBandwidth()) << |
| 199 |
", Primary Carrier Downlink Bandwidth: " << static_cast<uint16_t>(ueRrc->GetUlBandwidth()) << |
| 200 |
", Primary Carrier Uplink Earfcn: " << ueRrc->GetUlEarfcn() << |
| 201 |
", Primary Carrier Downlink Earfcn: " << ueRrc->GetUlEarfcn()); |
| 202 |
|
| 203 |
for(auto &list:sCellToAddModList) |
| 204 |
{ |
| 205 |
LteRrcSap::SCellToAddMod scell = list; |
| 206 |
|
| 207 |
NS_LOG_INFO("Secondary Carrier Uplink Bandwidth: " << static_cast<uint16_t>(scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth)<< |
| 208 |
", Secondary Carrier Downlink Bandwidth: " << static_cast<uint16_t>(scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth) << |
| 209 |
", Secondary Carrier Uplink Earfcn: " << scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq << |
| 210 |
", Secondary Carrier Downlink Earfcn: " << scell.cellIdentification.dlCarrierFreq); |
| 211 |
} |
| 212 |
|
| 213 |
ConfigToCheck pCConfig = configToCheckMap[0]; //Primary Carrier |
| 214 |
ConfigToCheck sCConfig; //Secondary Carriers |
| 215 |
|
| 216 |
NS_TEST_ASSERT_MSG_EQ(pCConfig.m_dlBandwidthToCheck,static_cast<uint16_t>(ueRrc->GetDlBandwidth()),"Primary Carrier DL bandwidth configuration failed"); |
| 217 |
NS_TEST_ASSERT_MSG_EQ(pCConfig.m_ulBandwidthToCheck,static_cast<uint16_t>(ueRrc->GetUlBandwidth()),"Primary Carrier UL bandwidth configuration failed"); |
| 218 |
NS_TEST_ASSERT_MSG_EQ(pCConfig.m_dlEarfcnToCheck, ueRrc->GetDlEarfcn(),"Primary Carrier DL EARFCN configuration failed"); |
| 219 |
NS_TEST_ASSERT_MSG_EQ(pCConfig.m_ulEarfcnToCheck, ueRrc->GetUlEarfcn(),"Primary Carrier UL EARFCN configuration failed"); |
| 220 |
|
| 221 |
uint32_t ConfigToCheckMapIndex = 1; |
| 222 |
|
| 223 |
for(auto &list:sCellToAddModList) |
| 224 |
{ |
| 225 |
LteRrcSap::SCellToAddMod scell = list; |
| 226 |
sCConfig = configToCheckMap[ConfigToCheckMapIndex]; |
| 227 |
|
| 228 |
NS_TEST_ASSERT_MSG_EQ(sCConfig.m_dlBandwidthToCheck, static_cast<uint16_t>(scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth),"Secondary Carrier DL bandwidth configuration failed"); |
| 229 |
NS_TEST_ASSERT_MSG_EQ(sCConfig.m_ulBandwidthToCheck,static_cast<uint16_t>(scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth),"Secondary Carrier UL bandwidth configuration failed"); |
| 230 |
NS_TEST_ASSERT_MSG_EQ(sCConfig.m_dlEarfcnToCheck, scell.cellIdentification.dlCarrierFreq,"Secondary Carrier DL EARFCN configuration failed"); |
| 231 |
NS_TEST_ASSERT_MSG_EQ(sCConfig.m_ulEarfcnToCheck, scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq,"Secondary Carrier UL EARFCN configuration failed"); |
| 232 |
ConfigToCheckMapIndex++; |
| 233 |
} |
| 234 |
|
| 235 |
} |
| 236 |
|
| 237 |
void |
| 238 |
CarrierAggregationConfigTestCase::DoRun () |
| 239 |
{ |
| 240 |
Config::SetDefault ("ns3::LteHelper::UseCa", BooleanValue (true)); |
| 241 |
Config::SetDefault ("ns3::LteHelper::NumberOfComponentCarriers", UintegerValue (m_numberOfComponentCarriers)); |
| 242 |
Config::SetDefault ("ns3::LteHelper::EnbComponentCarrierManager", StringValue ("ns3::RrComponentCarrierManager")); |
| 243 |
|
| 244 |
int64_t stream = 1; |
| 245 |
|
| 246 |
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> (); |
| 247 |
// Create Nodes: eNodeB and UE |
| 248 |
NodeContainer enbNodes; |
| 249 |
NodeContainer ueNodes; |
| 250 |
enbNodes.Create (m_numberOfNodes); |
| 251 |
ueNodes.Create (m_numberOfNodes); |
| 252 |
|
| 253 |
uint32_t totalNumberOfNodes = enbNodes.GetN() + ueNodes.GetN(); |
| 254 |
|
| 255 |
// Install Mobility Model |
| 256 |
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> (); |
| 257 |
for (uint16_t i = 0; i < totalNumberOfNodes; i++) |
| 258 |
{ |
| 259 |
positionAlloc->Add (Vector(2 * i, 0, 0)); |
| 260 |
} |
| 261 |
|
| 262 |
NS_LOG_INFO(" Position vector size "<<positionAlloc->GetSize()); |
| 263 |
|
| 264 |
MobilityHelper mobility; |
| 265 |
mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); |
| 266 |
mobility.SetPositionAllocator(positionAlloc); |
| 267 |
|
| 268 |
for(uint32_t n = 0; n < m_numberOfNodes; ++n) |
| 269 |
{ |
| 270 |
mobility.Install(enbNodes.Get(n)); |
| 271 |
mobility.Install(ueNodes.Get(n)); |
| 272 |
} |
| 273 |
|
| 274 |
ConfigToCheck Configurations; |
| 275 |
NetDeviceContainer enbDevs; |
| 276 |
NetDeviceContainer ueDevs; |
| 277 |
|
| 278 |
// Set bandwidth, EARFCN and install nodes (eNB and UE) |
| 279 |
for(uint32_t i = 0; i < m_configToCheck.size(); ++i) |
| 280 |
{ |
| 281 |
Configurations = m_configToCheck[i]; |
| 282 |
|
| 283 |
lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (Configurations.m_dlBandwidthToCheck)); |
| 284 |
lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (Configurations.m_ulBandwidthToCheck)); |
| 285 |
lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (Configurations.m_dlEarfcnToCheck)); |
| 286 |
lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (Configurations.m_ulEarfcnToCheck)); |
| 287 |
lteHelper->SetUeDeviceAttribute ("DlEarfcn", UintegerValue (Configurations.m_dlEarfcnToCheck)); |
| 288 |
enbDevs.Add(lteHelper->InstallEnbDevice (enbNodes.Get(i))); |
| 289 |
lteHelper->AssignStreams (enbDevs, stream); |
| 290 |
ueDevs.Add(lteHelper->InstallUeDevice (ueNodes.Get(i))); |
| 291 |
lteHelper->AssignStreams (ueDevs, stream); |
| 292 |
} |
| 293 |
|
| 294 |
|
| 295 |
//Calculate the DlBandwidth, UlBandwidth, DlEarfcn and UlEarfcn to which the values from UE RRC would be compared |
| 296 |
|
| 297 |
m_configToCheckContainer = EquallySpacedCcs (); |
| 298 |
|
| 299 |
// Attach a UE to a eNB |
| 300 |
for(uint32_t k = 0; k < m_numberOfNodes; ++k) |
| 301 |
{ |
| 302 |
lteHelper->Attach (ueDevs.Get(k), enbDevs.Get (k)); |
| 303 |
} |
| 304 |
|
| 305 |
// Activate a data radio bearer |
| 306 |
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; |
| 307 |
EpsBearer bearer (q); |
| 308 |
lteHelper->ActivateDataRadioBearer (ueDevs, bearer); |
| 309 |
|
| 310 |
Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/SCarrierConfigured", MakeCallback (&CarrierAggregationConfigTestCase::Evaluate, this)); |
| 311 |
|
| 312 |
Simulator::Stop (m_simulationDuration); |
| 313 |
|
| 314 |
Simulator::Run (); |
| 315 |
|
| 316 |
NS_TEST_ASSERT_MSG_EQ(m_connectionCounter, ueNodes.GetN(),"Not all the UEs were connected"); |
| 317 |
|
| 318 |
Simulator::Destroy (); |
| 319 |
} |
| 320 |
|
| 321 |
|
| 322 |
class CarrierAggregationConfigTestSuite : public TestSuite |
| 323 |
{ |
| 324 |
public: |
| 325 |
CarrierAggregationConfigTestSuite (); |
| 326 |
}; |
| 327 |
|
| 328 |
CarrierAggregationConfigTestSuite::CarrierAggregationConfigTestSuite () |
| 329 |
: TestSuite ("carrier-aggregation-config-test", SYSTEM) |
| 330 |
{ |
| 331 |
//LogComponentEnable("TestCarrierAggregationConfig", LOG_LEVEL_ALL); |
| 332 |
|
| 333 |
std::vector<ConfigToCheck> configToCheck; |
| 334 |
|
| 335 |
//Test1 with 1 eNB and 1 UE. We put a configuration different than the default configuration done in LteHelper for the sake of |
| 336 |
//creating PHY and MAC instances equal to the number of component carriers. |
| 337 |
|
| 338 |
ConfigToCheck configToCheckTest1; |
| 339 |
configToCheckTest1.m_dlBandwidthToCheck = 50; |
| 340 |
configToCheckTest1.m_ulBandwidthToCheck = 50; |
| 341 |
configToCheckTest1.m_dlEarfcnToCheck = 300; |
| 342 |
configToCheckTest1.m_ulEarfcnToCheck = 300+18000; |
| 343 |
configToCheck.push_back(configToCheckTest1); |
| 344 |
uint32_t numberOfNodes = 1; |
| 345 |
uint16_t numberOfComponentCarriers = 2; |
| 346 |
Time simulationDuration = Seconds(1); |
| 347 |
|
| 348 |
AddTestCase (new CarrierAggregationConfigTestCase (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration), TestCase::QUICK); |
| 349 |
|
| 350 |
configToCheck.erase(configToCheck.begin(), configToCheck.end()); |
| 351 |
|
| 352 |
//Test2 with 2 eNBs and 2 UEs. We decrease the bandwidth so not to exceed maximum band bandwidth of 20 MHz |
| 353 |
configToCheckTest1.m_dlBandwidthToCheck = 25; |
| 354 |
configToCheckTest1.m_ulBandwidthToCheck = 25; |
| 355 |
configToCheckTest1.m_dlEarfcnToCheck = 300; |
| 356 |
configToCheckTest1.m_ulEarfcnToCheck = 300+18000; |
| 357 |
configToCheck.push_back(configToCheckTest1); |
| 358 |
|
| 359 |
ConfigToCheck configToCheckTest2; |
| 360 |
configToCheckTest2.m_dlBandwidthToCheck = 25; |
| 361 |
configToCheckTest2.m_ulBandwidthToCheck = 25; |
| 362 |
configToCheckTest2.m_dlEarfcnToCheck = 502; |
| 363 |
configToCheckTest2.m_ulEarfcnToCheck = 502+18000; |
| 364 |
configToCheck.push_back(configToCheckTest2); |
| 365 |
numberOfNodes = 2; |
| 366 |
simulationDuration = Seconds(2); |
| 367 |
|
| 368 |
AddTestCase (new CarrierAggregationConfigTestCase (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration), TestCase::QUICK); |
| 369 |
} |
| 370 |
|
| 371 |
static CarrierAggregationConfigTestSuite g_carrierAggregationConfigTestSuite; |