|
|
| 1 |
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
| 2 |
/* |
| 3 |
* Copyright (c) 2018 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 |
using namespace ns3; |
| 37 |
|
| 38 |
/** |
| 39 |
* This test suite verifies following two things: |
| 40 |
* |
| 41 |
* 1. When CA is enabled and UE carriers configuration is different than the default one, |
| 42 |
* we check that the UE is configured properly once it receives |
| 43 |
* RRC Connection Reconfiguration message from eNB. |
| 44 |
* |
| 45 |
* 2. A user can configure 2 or more eNBs and UEs with different configuration parameters, |
| 46 |
* i.e, each eNB and UE can have different EARFCN and Bandwidths and a UE connects to |
| 47 |
* an eNB with similar DL EARFCN. |
| 48 |
* Here we check it with CA enabled but the end results will be the same if CA is not |
| 49 |
* enabled and we have more than one eNBs and UEs with different configurations. |
| 50 |
* |
| 51 |
* Since we do not need EPC to test the configuration, this test only simulates |
| 52 |
* the LTE radio access with RLC SM. |
| 53 |
* |
| 54 |
* Test 1 tests that the UE is configured properly after receiving RRC Connection |
| 55 |
* Reconfiguration message from the eNB, which will overwrite UE default configuration |
| 56 |
* done in LteHelper for the sake of creating PHY and MAC instances equal to the number |
| 57 |
* of component carriers. |
| 58 |
* |
| 59 |
* Test 2 tests that in a simulation scenario every eNB or UE can be configured with |
| 60 |
* different EARFCNs and Bandwidths. This will check that the eNBs and UEs configuration |
| 61 |
* is not static, as reported in BUG 2840. |
| 62 |
*/ |
| 63 |
|
| 64 |
struct ConfigToCheck |
| 65 |
{ |
| 66 |
uint16_t m_dlBandwidth; |
| 67 |
uint16_t m_ulBandwidth; |
| 68 |
uint32_t m_dlEarfcn; |
| 69 |
uint32_t m_ulEarfcn; |
| 70 |
}; |
| 71 |
|
| 72 |
NS_LOG_COMPONENT_DEFINE ("TestCarrierAggregationConfig"); |
| 73 |
|
| 74 |
class CarrierAggregationConfigTestCase : public TestCase |
| 75 |
{ |
| 76 |
public: |
| 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 |
virtual void DoRun (void); |
| 96 |
|
| 97 |
std::string BuildNameString (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector<ConfigToCheck> configToCheck, Time simulationDuration); |
| 98 |
void Evaluate (std::string context, Ptr<LteUeRrc> ueRrc, std::list<LteRrcSap::SCellToAddMod> sCellToAddModList); |
| 99 |
std::vector<std::map<uint16_t, ConfigToCheck> > EquallySpacedCcs (); |
| 100 |
|
| 101 |
uint32_t m_numberOfNodes; |
| 102 |
uint16_t m_numberOfComponentCarriers; |
| 103 |
std::vector<ConfigToCheck> m_configToCheck; |
| 104 |
uint32_t m_connectionCounter; |
| 105 |
Time m_simulationDuration; |
| 106 |
std::vector<std::map<uint16_t, ConfigToCheck> > m_configToCheckContainer; |
| 107 |
}; |
| 108 |
|
| 109 |
std::string |
| 110 |
CarrierAggregationConfigTestCase::BuildNameString (uint32_t numberOfNodes, uint16_t numberOfComponentCarriers, std::vector<ConfigToCheck> configToCheck, Time simulationDuration) |
| 111 |
{ |
| 112 |
std::ostringstream oss; |
| 113 |
oss << " nodes " << numberOfNodes << " carriers " << numberOfComponentCarriers |
| 114 |
<< " configurations " << configToCheck.size () |
| 115 |
<< " duration " << simulationDuration; |
| 116 |
return oss.str (); |
| 117 |
} |
| 118 |
|
| 119 |
std::vector<std::map<uint16_t, ConfigToCheck> > |
| 120 |
CarrierAggregationConfigTestCase::EquallySpacedCcs () |
| 121 |
{ |
| 122 |
std::vector<std::map<uint16_t, ConfigToCheck> > configToCheckContainer; |
| 123 |
|
| 124 |
for (auto &it: m_configToCheck) |
| 125 |
{ |
| 126 |
std::map<uint16_t, ConfigToCheck> ccmap; |
| 127 |
uint32_t ulEarfcn = it.m_ulEarfcn; |
| 128 |
uint32_t dlEarfcn = it.m_dlEarfcn; |
| 129 |
uint32_t maxBandwidthRb = std::max<uint32_t> (it.m_ulBandwidth, it.m_dlBandwidth); |
| 130 |
|
| 131 |
// Convert bandwidth from RBs to kHz |
| 132 |
uint32_t maxBandwidthKhz = LteSpectrumValueHelper::GetChannelBandwidth (maxBandwidthRb) / 1e3; |
| 133 |
|
| 134 |
for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++) |
| 135 |
{ |
| 136 |
// Make sure we stay within the same band. |
| 137 |
if (LteSpectrumValueHelper::GetUplinkCarrierBand (ulEarfcn) != |
| 138 |
LteSpectrumValueHelper::GetUplinkCarrierBand (it.m_ulEarfcn) |
| 139 |
|| LteSpectrumValueHelper::GetDownlinkCarrierBand (dlEarfcn) != |
| 140 |
LteSpectrumValueHelper::GetDownlinkCarrierBand (it.m_dlEarfcn)) |
| 141 |
{ |
| 142 |
NS_FATAL_ERROR ("Band is not wide enough to allocate " << m_numberOfComponentCarriers << " CCs"); |
| 143 |
} |
| 144 |
|
| 145 |
ConfigToCheck cc; |
| 146 |
cc.m_dlBandwidth = it.m_dlBandwidth; |
| 147 |
cc.m_dlEarfcn = dlEarfcn; |
| 148 |
cc.m_ulBandwidth = it.m_ulBandwidth; |
| 149 |
cc.m_ulEarfcn = ulEarfcn; |
| 150 |
|
| 151 |
ccmap.insert (std::pair<uint16_t, ConfigToCheck> (i, cc)); |
| 152 |
|
| 153 |
NS_LOG_INFO ("UL BW: " << it.m_ulBandwidth << |
| 154 |
", DL BW: " << it.m_dlBandwidth << |
| 155 |
", UL Earfcn: " << ulEarfcn << |
| 156 |
", DL Earfcn: " << dlEarfcn); |
| 157 |
|
| 158 |
// The spacing between the center frequencies of two contiguous CCs should be multiple of 300 kHz. |
| 159 |
// Round spacing up to 300 kHz. |
| 160 |
uint32_t frequencyShift = 300 * (1 + (maxBandwidthKhz - 1) / 300); |
| 161 |
|
| 162 |
// Unit of EARFCN corresponds to 100kHz. |
| 163 |
uint32_t earfcnShift = frequencyShift / 100; |
| 164 |
ulEarfcn += earfcnShift; |
| 165 |
dlEarfcn += earfcnShift; |
| 166 |
} |
| 167 |
|
| 168 |
configToCheckContainer.push_back (ccmap); |
| 169 |
} |
| 170 |
|
| 171 |
return configToCheckContainer; |
| 172 |
} |
| 173 |
|
| 174 |
void |
| 175 |
CarrierAggregationConfigTestCase::Evaluate (std::string context, Ptr<LteUeRrc> ueRrc, std::list<LteRrcSap::SCellToAddMod> sCellToAddModList) |
| 176 |
{ |
| 177 |
NS_LOG_INFO ("Secondary carriers configured"); |
| 178 |
|
| 179 |
uint16_t cellId = ueRrc->GetCellId (); |
| 180 |
NS_LOG_INFO ("cellId " << cellId); |
| 181 |
NS_LOG_INFO ("m_configToCheckContainer size " << m_configToCheckContainer.size ()); |
| 182 |
|
| 183 |
++m_connectionCounter; |
| 184 |
|
| 185 |
std::map<uint16_t, ConfigToCheck> configToCheckMap; |
| 186 |
|
| 187 |
if (cellId == 1) |
| 188 |
{ |
| 189 |
configToCheckMap = m_configToCheckContainer[cellId-1]; |
| 190 |
} |
| 191 |
else |
| 192 |
{ |
| 193 |
uint16_t n1 = std::max(cellId, m_numberOfComponentCarriers); |
| 194 |
uint16_t n2 = std::min(cellId, m_numberOfComponentCarriers); |
| 195 |
configToCheckMap = m_configToCheckContainer[n1-n2]; |
| 196 |
} |
| 197 |
|
| 198 |
NS_LOG_INFO ("PCarrier - UL BW: " << static_cast<uint16_t> (ueRrc->GetUlBandwidth ()) << |
| 199 |
", DL BW: " << static_cast<uint16_t> (ueRrc->GetDlBandwidth ()) << |
| 200 |
", UL Earfcn: " << ueRrc->GetUlEarfcn () << |
| 201 |
", DL Earfcn: " << ueRrc->GetDlEarfcn ()); |
| 202 |
|
| 203 |
for (auto scell: sCellToAddModList) |
| 204 |
{ |
| 205 |
NS_LOG_INFO ("SCarrier - UL BW: " << static_cast<uint16_t> (scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth)<< |
| 206 |
", DL BW: " << static_cast<uint16_t> (scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth) << |
| 207 |
", UL Earfcn: " << scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq << |
| 208 |
", DL Earfcn: " << scell.cellIdentification.dlCarrierFreq); |
| 209 |
} |
| 210 |
|
| 211 |
ConfigToCheck pCConfig = configToCheckMap[0]; // Primary Carrier |
| 212 |
ConfigToCheck sCConfig; // Secondary Carriers |
| 213 |
|
| 214 |
NS_TEST_ASSERT_MSG_EQ (pCConfig.m_dlBandwidth, static_cast<uint16_t> (ueRrc->GetDlBandwidth ()), |
| 215 |
"Primary Carrier DL bandwidth configuration failed"); |
| 216 |
NS_TEST_ASSERT_MSG_EQ (pCConfig.m_ulBandwidth, static_cast<uint16_t> (ueRrc->GetUlBandwidth ()), |
| 217 |
"Primary Carrier UL bandwidth configuration failed"); |
| 218 |
NS_TEST_ASSERT_MSG_EQ (pCConfig.m_dlEarfcn, ueRrc->GetDlEarfcn (), |
| 219 |
"Primary Carrier DL EARFCN configuration failed"); |
| 220 |
NS_TEST_ASSERT_MSG_EQ (pCConfig.m_ulEarfcn, ueRrc->GetUlEarfcn (), |
| 221 |
"Primary Carrier UL EARFCN configuration failed"); |
| 222 |
|
| 223 |
uint32_t ConfigToCheckMapIndex = 1; |
| 224 |
|
| 225 |
for (auto scell: sCellToAddModList) |
| 226 |
{ |
| 227 |
sCConfig = configToCheckMap[ConfigToCheckMapIndex]; |
| 228 |
|
| 229 |
NS_TEST_ASSERT_MSG_EQ (sCConfig.m_dlBandwidth, static_cast<uint16_t> (scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth), |
| 230 |
"Secondary Carrier DL bandwidth configuration failed"); |
| 231 |
NS_TEST_ASSERT_MSG_EQ (sCConfig.m_ulBandwidth, static_cast<uint16_t> (scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth), |
| 232 |
"Secondary Carrier UL bandwidth configuration failed"); |
| 233 |
NS_TEST_ASSERT_MSG_EQ (sCConfig.m_dlEarfcn, scell.cellIdentification.dlCarrierFreq, |
| 234 |
"Secondary Carrier DL EARFCN configuration failed"); |
| 235 |
NS_TEST_ASSERT_MSG_EQ (sCConfig.m_ulEarfcn, scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq, |
| 236 |
"Secondary Carrier UL EARFCN configuration failed"); |
| 237 |
ConfigToCheckMapIndex++; |
| 238 |
} |
| 239 |
} |
| 240 |
|
| 241 |
void |
| 242 |
CarrierAggregationConfigTestCase::DoRun () |
| 243 |
{ |
| 244 |
Config::SetDefault ("ns3::LteHelper::UseCa", BooleanValue (true)); |
| 245 |
Config::SetDefault ("ns3::LteHelper::NumberOfComponentCarriers", UintegerValue (m_numberOfComponentCarriers)); |
| 246 |
Config::SetDefault ("ns3::LteHelper::EnbComponentCarrierManager", StringValue ("ns3::RrComponentCarrierManager")); |
| 247 |
|
| 248 |
int64_t stream = 1; |
| 249 |
|
| 250 |
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> (); |
| 251 |
|
| 252 |
// Create Nodes: eNodeB and UE |
| 253 |
NodeContainer enbNodes; |
| 254 |
NodeContainer ueNodes; |
| 255 |
enbNodes.Create (m_numberOfNodes); |
| 256 |
ueNodes.Create (m_numberOfNodes); |
| 257 |
|
| 258 |
uint32_t totalNumberOfNodes = enbNodes.GetN () + ueNodes.GetN (); |
| 259 |
|
| 260 |
// Install Mobility Model |
| 261 |
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> (); |
| 262 |
for (uint16_t i = 0; i < totalNumberOfNodes; i++) |
| 263 |
{ |
| 264 |
positionAlloc->Add (Vector (2 * i, 0, 0)); |
| 265 |
} |
| 266 |
|
| 267 |
MobilityHelper mobility; |
| 268 |
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); |
| 269 |
mobility.SetPositionAllocator (positionAlloc); |
| 270 |
|
| 271 |
for (uint32_t n = 0; n < m_numberOfNodes; ++n) |
| 272 |
{ |
| 273 |
mobility.Install (enbNodes.Get (n)); |
| 274 |
mobility.Install (ueNodes.Get (n)); |
| 275 |
} |
| 276 |
|
| 277 |
ConfigToCheck configuration; |
| 278 |
NetDeviceContainer enbDevs; |
| 279 |
NetDeviceContainer ueDevs; |
| 280 |
|
| 281 |
// Set bandwidth, EARFCN and install nodes (eNB and UE) |
| 282 |
for (uint32_t i = 0; i < m_configToCheck.size (); ++i) |
| 283 |
{ |
| 284 |
configuration = m_configToCheck[i]; |
| 285 |
|
| 286 |
lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (configuration.m_dlBandwidth)); |
| 287 |
lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (configuration.m_ulBandwidth)); |
| 288 |
lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (configuration.m_dlEarfcn)); |
| 289 |
lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (configuration.m_ulEarfcn)); |
| 290 |
lteHelper->SetUeDeviceAttribute ("DlEarfcn", UintegerValue (configuration.m_dlEarfcn)); |
| 291 |
enbDevs.Add (lteHelper->InstallEnbDevice (enbNodes.Get (i))); |
| 292 |
lteHelper->AssignStreams (enbDevs, stream); |
| 293 |
ueDevs.Add (lteHelper->InstallUeDevice (ueNodes.Get (i))); |
| 294 |
lteHelper->AssignStreams (ueDevs, stream); |
| 295 |
} |
| 296 |
|
| 297 |
// Calculate the DlBandwidth, UlBandwidth, DlEarfcn and UlEarfcn to which the values from UE RRC would be compared |
| 298 |
m_configToCheckContainer = EquallySpacedCcs (); |
| 299 |
|
| 300 |
// Attach a UE to an eNB |
| 301 |
for(uint32_t k = 0; k < m_numberOfNodes; ++k) |
| 302 |
{ |
| 303 |
lteHelper->Attach (ueDevs.Get (k), enbDevs.Get (k)); |
| 304 |
} |
| 305 |
|
| 306 |
// Activate a data radio bearer |
| 307 |
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; |
| 308 |
EpsBearer bearer (q); |
| 309 |
lteHelper->ActivateDataRadioBearer (ueDevs, bearer); |
| 310 |
|
| 311 |
Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/SCarrierConfigured", |
| 312 |
MakeCallback (&CarrierAggregationConfigTestCase::Evaluate, this)); |
| 313 |
|
| 314 |
Simulator::Stop (m_simulationDuration); |
| 315 |
Simulator::Run (); |
| 316 |
|
| 317 |
NS_TEST_ASSERT_MSG_EQ (m_connectionCounter, ueNodes.GetN (), "Not all the UEs were connected"); |
| 318 |
|
| 319 |
Simulator::Destroy (); |
| 320 |
} |
| 321 |
|
| 322 |
|
| 323 |
class CarrierAggregationConfigTestSuite : public TestSuite |
| 324 |
{ |
| 325 |
public: |
| 326 |
CarrierAggregationConfigTestSuite (); |
| 327 |
}; |
| 328 |
|
| 329 |
CarrierAggregationConfigTestSuite::CarrierAggregationConfigTestSuite () |
| 330 |
: TestSuite ("lte-carrier-aggregation-configuration", SYSTEM) |
| 331 |
{ |
| 332 |
std::vector<ConfigToCheck> configToCheck; |
| 333 |
|
| 334 |
// Test1 with 1 eNB and 1 UE. |
| 335 |
// 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_dlBandwidth = 50; |
| 340 |
configToCheckTest1.m_ulBandwidth = 50; |
| 341 |
configToCheckTest1.m_dlEarfcn = 300; |
| 342 |
configToCheckTest1.m_ulEarfcn = 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 |
configToCheck.clear (); |
| 352 |
|
| 353 |
// Test2 with 2 eNBs and 2 UEs. |
| 354 |
// We decrease the bandwidth so not to exceed maximum band bandwidth of 20 MHz |
| 355 |
|
| 356 |
configToCheckTest1.m_dlBandwidth = 25; |
| 357 |
configToCheckTest1.m_ulBandwidth = 25; |
| 358 |
configToCheckTest1.m_dlEarfcn = 300; |
| 359 |
configToCheckTest1.m_ulEarfcn = 300+18000; |
| 360 |
configToCheck.push_back (configToCheckTest1); |
| 361 |
|
| 362 |
ConfigToCheck configToCheckTest2; |
| 363 |
configToCheckTest2.m_dlBandwidth = 25; |
| 364 |
configToCheckTest2.m_ulBandwidth = 25; |
| 365 |
configToCheckTest2.m_dlEarfcn = 502; |
| 366 |
configToCheckTest2.m_ulEarfcn = 502+18000; |
| 367 |
configToCheck.push_back (configToCheckTest2); |
| 368 |
numberOfNodes = 2; |
| 369 |
simulationDuration = Seconds (2); |
| 370 |
|
| 371 |
AddTestCase (new CarrierAggregationConfigTestCase (numberOfNodes, numberOfComponentCarriers, configToCheck, simulationDuration), TestCase::QUICK); |
| 372 |
} |
| 373 |
|
| 374 |
static CarrierAggregationConfigTestSuite g_carrierAggregationConfigTestSuite; |