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