|
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; |