5G-LENA nr-v3.3-120-gdac69c56
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-test-timings.cc
1// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include "ns3/antenna-module.h"
6#include "ns3/applications-module.h"
7#include "ns3/core-module.h"
8#include "ns3/internet-module.h"
9#include "ns3/mobility-module.h"
10#include "ns3/network-module.h"
11#include "ns3/nr-eps-bearer-tag.h"
12#include "ns3/nr-module.h"
13#include "ns3/point-to-point-helper.h"
14
15#include <unordered_map>
16
17// Do not put your test classes in namespace ns3. You may find it useful
18// to use the using directive to access the ns3 namespace directly
19using namespace ns3;
20
32static uint32_t packetSize = 21;
33
34static const std::unordered_map<NrControlMessage::messageType, bool, std::hash<int>> messageLog = {
35 {NrControlMessage::messageType::UL_DCI, false},
36 {NrControlMessage::messageType::DL_DCI, false},
37 {NrControlMessage::messageType::DL_CQI, false},
38 {NrControlMessage::messageType::MIB, false},
39 {NrControlMessage::messageType::SIB1, false},
40 {NrControlMessage::messageType::RACH_PREAMBLE, false},
41 {NrControlMessage::messageType::RAR, false},
42 {NrControlMessage::messageType::BSR, false},
43 {NrControlMessage::messageType::DL_HARQ, false},
44 {NrControlMessage::messageType::SR, false},
45};
46
47typedef std::unordered_map<NrControlMessage::messageType, uint64_t, std::hash<int>> TypeToResult;
48typedef std::unordered_map<uint32_t, TypeToResult> NumerologyToType;
49
50class NrTimingsTest : public TestCase
51{
52 public:
53 NrTimingsTest(const std::string& name, uint32_t numerology, bool verbose);
54 ~NrTimingsTest() override;
55
56 private:
57 void DoRun() override;
58 void GnbPhyTx(SfnSf sfn,
59 uint16_t nodeId,
60 uint16_t rnti,
61 uint8_t ccId,
62 Ptr<const NrControlMessage> msg);
63 void GnbPhyRx(SfnSf sfn,
64 uint16_t nodeId,
65 uint16_t rnti,
66 uint8_t ccId,
67 Ptr<const NrControlMessage> msg);
68
69 void GnbMacTx(SfnSf sfn,
70 uint16_t nodeId,
71 uint16_t rnti,
72 uint8_t ccId,
73 Ptr<const NrControlMessage> msg);
74 void GnbMacRx(SfnSf sfn,
75 uint16_t nodeId,
76 uint16_t rnti,
77 uint8_t ccId,
78 Ptr<const NrControlMessage> msg);
79
80 void UePhyTx(SfnSf sfn,
81 uint16_t nodeId,
82 uint16_t rnti,
83 uint8_t ccId,
84 Ptr<const NrControlMessage> msg);
85 void UePhyRx(SfnSf sfn,
86 uint16_t nodeId,
87 uint16_t rnti,
88 uint8_t ccId,
89 Ptr<const NrControlMessage> msg);
90
91 void UeMacTx(SfnSf sfn,
92 uint16_t nodeId,
93 uint16_t rnti,
94 uint8_t ccId,
95 Ptr<const NrControlMessage> msg);
96 void UeMacRx(SfnSf sfn,
97 uint16_t nodeId,
98 uint16_t rnti,
99 uint8_t ccId,
100 Ptr<const NrControlMessage> msg);
101
102 uint32_t m_numerology;
103 bool verbose{false};
104};
105
106NrTimingsTest::NrTimingsTest(const std::string& name, uint32_t numerology, bool verbose)
107 : TestCase(name),
108 m_numerology(numerology),
109 verbose(verbose)
110{
111}
112
113NrTimingsTest::~NrTimingsTest()
114{
115}
116
117static void
118SendPacket(const Ptr<NetDevice>& device, const Address& addr)
119{
120 Ipv4Header header;
121 NS_ASSERT(packetSize > header.GetSerializedSize());
122 Ptr<Packet> pkt = Create<Packet>(packetSize - header.GetSerializedSize());
123 header.SetProtocol(0x06);
124 NrEpsBearerTag tag(1, 1);
125 pkt->AddPacketTag(tag);
126 pkt->AddHeader(header);
127 device->Send(pkt, addr, Ipv4L3Protocol::PROT_NUMBER);
128}
129
130static const std::unordered_map<NrControlMessage::messageType, std::string, std::hash<int>>
131 TYPE_TO_STRING = {
132 {NrControlMessage::messageType::UL_DCI, "UL_DCI"},
133 {NrControlMessage::messageType::DL_DCI, "DL_DCI"},
134 {NrControlMessage::messageType::DL_CQI, "DL_CQI"},
135 {NrControlMessage::messageType::MIB, "MIB"},
136 {NrControlMessage::messageType::SIB1, "SIB1"},
137 {NrControlMessage::messageType::RACH_PREAMBLE, "RACH_PREAMBLE"},
138 {NrControlMessage::messageType::RAR, "RAR"},
139 {NrControlMessage::messageType::BSR, "BSR"},
140 {NrControlMessage::messageType::DL_HARQ, "DL_HARQ"},
141 {NrControlMessage::messageType::SR, "SR"},
142};
143
144void
145NrTimingsTest::GnbPhyTx(SfnSf sfn,
146 [[maybe_unused]] uint16_t nodeId,
147 [[maybe_unused]] uint16_t rnti,
148 [[maybe_unused]] uint8_t ccId,
149 Ptr<const NrControlMessage> msg)
150{
151 static NumerologyToType res = {
152 {
153 4,
154 {
155 {NrControlMessage::RAR, SfnSf(1, 6, 4, 4).Normalize()},
156 {NrControlMessage::DL_DCI, SfnSf(40, 0, 2, 4).Normalize()},
157 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 4).Normalize () },
158 },
159 },
160 {
161 3,
162 {
163 {NrControlMessage::RAR, SfnSf(1, 6, 4, 3).Normalize()},
164 {NrControlMessage::DL_DCI, SfnSf(40, 0, 2, 3).Normalize()},
165 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 3).Normalize () },
166 },
167
168 },
169 {
170 2,
171 {
172 {NrControlMessage::RAR, SfnSf(1, 7, 0, 2).Normalize()},
173 {NrControlMessage::DL_DCI, SfnSf(40, 0, 2, 2).Normalize()},
174 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 2).Normalize () },
175 },
176 },
177 {
178 1,
179 {
180 {NrControlMessage::RAR, SfnSf(1, 8, 0, 1).Normalize()},
181 {NrControlMessage::DL_DCI, SfnSf(40, 1, 0, 1).Normalize()},
182 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 1).Normalize () },
183 },
184 },
185 {
186 0,
187 {
188 {NrControlMessage::RAR, SfnSf(2, 0, 0, 0).Normalize()},
189 {NrControlMessage::DL_DCI, SfnSf(40, 2, 0, 0).Normalize()},
190 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 0).Normalize () },
191 },
192 },
193 };
194
195 if (verbose && messageLog.at(msg->GetMessageType()))
196 {
197 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType()) << " at " << sfn
198 << " numerology " << m_numerology << " slot count " << sfn.Normalize() << " "
199 << Simulator::Now() << std::endl;
200 }
201
202 auto numMap = res.find(m_numerology);
203 if (numMap != res.end())
204 {
205 auto resMap = numMap->second.find(msg->GetMessageType());
206 if (resMap != numMap->second.end())
207 {
208 uint64_t slotN = resMap->second;
209 NS_TEST_ASSERT_MSG_EQ(slotN,
210 sfn.Normalize(),
211 "The message type " << TYPE_TO_STRING.at(msg->GetMessageType())
212 << " was supposed to be sent at slot "
213 << slotN << " but instead we sent it at "
214 << sfn.Normalize() << " in numerology "
215 << m_numerology);
216 return;
217 }
218 }
219
220 if (verbose && messageLog.at(msg->GetMessageType()))
221 {
222 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType())
223 << " not found in the result map;" << std::endl;
224 }
225}
226
227void
228NrTimingsTest::GnbPhyRx(SfnSf sfn,
229 [[maybe_unused]] uint16_t nodeId,
230 [[maybe_unused]] uint16_t rnti,
231 [[maybe_unused]] uint8_t ccId,
232 Ptr<const NrControlMessage> msg)
233{
234 static NumerologyToType res = {
235 {
236 4,
237 {
239 {NrControlMessage::DL_HARQ, SfnSf(40, 0, 4, 4).Normalize()},
240 {NrControlMessage::DL_CQI, SfnSf(40, 0, 5, 4).Normalize()},
241 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 4).Normalize () },
242 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 4).Normalize () },
243 },
244 },
245 {
246 3,
247 {
249 {NrControlMessage::DL_HARQ, SfnSf(40, 0, 4, 3).Normalize()},
250 {NrControlMessage::DL_CQI, SfnSf(40, 0, 5, 3).Normalize()},
251 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 3).Normalize () },
252 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 3).Normalize () },
253 },
254 },
255 {
256 2,
257 {
259 {NrControlMessage::DL_HARQ, SfnSf(40, 1, 0, 2).Normalize()},
260 {NrControlMessage::DL_CQI, SfnSf(40, 1, 1, 2).Normalize()},
261 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 2).Normalize () },
262 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 2).Normalize () },
263 },
264 },
265 {
266 1,
267 {
269 {NrControlMessage::DL_HARQ, SfnSf(40, 2, 0, 1).Normalize()},
270 {NrControlMessage::DL_CQI, SfnSf(40, 2, 1, 1).Normalize()},
271 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 1).Normalize () },
272 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 1).Normalize () },
273 },
274 },
275 {
276 0,
277 {
279 {NrControlMessage::DL_HARQ, SfnSf(40, 4, 0, 0).Normalize()},
280 {NrControlMessage::DL_CQI, SfnSf(40, 5, 0, 0).Normalize()},
281 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 0).Normalize () },
282 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 0).Normalize () },
283 },
284 },
285 };
286
287 if (verbose && messageLog.at(msg->GetMessageType()))
288 {
289 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType()) << " at " << sfn
290 << " numerology " << m_numerology << " slot count " << sfn.Normalize() << " "
291 << Simulator::Now() << std::endl;
292 }
293
294 auto numMap = res.find(m_numerology);
295 if (numMap != res.end())
296 {
297 auto resMap = numMap->second.find(msg->GetMessageType());
298 if (resMap != numMap->second.end())
299 {
300 uint64_t slotN = resMap->second;
301 NS_TEST_ASSERT_MSG_EQ(slotN,
302 sfn.Normalize(),
303 "The message type " << TYPE_TO_STRING.at(msg->GetMessageType())
304 << " was supposed to be sent at slot "
305 << slotN << " but instead we sent it at "
306 << sfn.Normalize() << " in numerology "
307 << m_numerology);
308 return;
309 }
310 }
311
312 if (verbose && messageLog.at(msg->GetMessageType()))
313 {
314 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType())
315 << " not found in the result map;" << std::endl;
316 }
317}
318
319void
320NrTimingsTest::GnbMacTx(SfnSf sfn,
321 [[maybe_unused]] uint16_t nodeId,
322 [[maybe_unused]] uint16_t rnti,
323 [[maybe_unused]] uint8_t ccId,
324 Ptr<const NrControlMessage> msg)
325{
326 static NumerologyToType res = {
327 {
328 4,
329 {{NrControlMessage::RAR, SfnSf(1, 6, 2, 4).Normalize()}},
330 },
331 {
332 3,
333 {{NrControlMessage::RAR, SfnSf(1, 6, 2, 3).Normalize()}},
334 },
335 {
336 2,
337 {{NrControlMessage::RAR, SfnSf(1, 6, 2, 2).Normalize()}},
338 },
339 {
340 1,
341 {{NrControlMessage::RAR, SfnSf(1, 7, 0, 1).Normalize()}},
342 },
343 {
344 0,
345 {{NrControlMessage::RAR, SfnSf(1, 8, 0, 0).Normalize()}},
346 },
347 };
348
349 if (verbose && messageLog.at(msg->GetMessageType()))
350 {
351 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType()) << " at " << sfn
352 << " numerology " << m_numerology << " slot count " << sfn.Normalize() << " "
353 << Simulator::Now() << std::endl;
354 }
355
356 auto numMap = res.find(m_numerology);
357 if (numMap != res.end())
358 {
359 auto resMap = numMap->second.find(msg->GetMessageType());
360 if (resMap != numMap->second.end())
361 {
362 uint64_t slotN = resMap->second;
363 NS_TEST_ASSERT_MSG_EQ(slotN,
364 sfn.Normalize(),
365 "The message type " << TYPE_TO_STRING.at(msg->GetMessageType())
366 << " was supposed to be sent at slot "
367 << slotN << " but instead we sent it at "
368 << sfn.Normalize() << " in numerology "
369 << m_numerology);
370 return;
371 }
372 }
373
374 if (verbose && messageLog.at(msg->GetMessageType()))
375 {
376 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType())
377 << " not found in the result map;" << std::endl;
378 }
379}
380
381void
382NrTimingsTest::GnbMacRx(SfnSf sfn,
383 [[maybe_unused]] uint16_t nodeId,
384 [[maybe_unused]] uint16_t rnti,
385 [[maybe_unused]] uint8_t ccId,
386 Ptr<const NrControlMessage> msg)
387{
388 static NumerologyToType res = {
389 {
390 4,
391 {
393 {NrControlMessage::DL_HARQ, SfnSf(40, 0, 5, 4).Normalize()},
394 {NrControlMessage::DL_CQI, SfnSf(40, 0, 6, 4).Normalize()},
395 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 4).Normalize () },
396 },
397 },
398 {
399 3,
400 {
402 {NrControlMessage::DL_HARQ, SfnSf(40, 0, 5, 3).Normalize()},
403 {NrControlMessage::DL_CQI, SfnSf(40, 0, 6, 3).Normalize()},
404 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 3).Normalize () },
405 },
406 },
407 {
408 2,
409 {
411 {NrControlMessage::DL_HARQ, SfnSf(40, 1, 1, 2).Normalize()},
412 {NrControlMessage::DL_CQI, SfnSf(40, 1, 2, 2).Normalize()},
413 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 2).Normalize () },
414 },
415 },
416 {
417 1,
418 {
420 {NrControlMessage::DL_HARQ, SfnSf(40, 2, 1, 1).Normalize()},
421 {NrControlMessage::DL_CQI, SfnSf(40, 3, 0, 1).Normalize()},
422 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 1).Normalize () },
423 },
424 },
425 {
426 0,
427 {
429 {NrControlMessage::DL_HARQ, SfnSf(40, 5, 0, 0).Normalize()},
430 {NrControlMessage::DL_CQI, SfnSf(40, 6, 0, 0).Normalize()},
431 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 0).Normalize () },
432 },
433 },
434 };
435
436 if (verbose && messageLog.at(msg->GetMessageType()))
437 {
438 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType()) << " at " << sfn
439 << " numerology " << m_numerology << " slot count " << sfn.Normalize() << " "
440 << Simulator::Now() << std::endl;
441 }
442
443 auto numMap = res.find(m_numerology);
444 if (numMap != res.end())
445 {
446 auto resMap = numMap->second.find(msg->GetMessageType());
447 if (resMap != numMap->second.end())
448 {
449 uint64_t slotN = resMap->second;
450 NS_TEST_ASSERT_MSG_EQ(slotN,
451 sfn.Normalize(),
452 "The message type " << TYPE_TO_STRING.at(msg->GetMessageType())
453 << " was supposed to be sent at slot "
454 << slotN << " but instead we sent it at "
455 << sfn.Normalize() << " in numerology "
456 << m_numerology);
457 return;
458 }
459 }
460
461 if (verbose && messageLog.at(msg->GetMessageType()))
462 {
463 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType())
464 << " not found in the result map;" << std::endl;
465 }
466}
467
468// UE
469
470void
471NrTimingsTest::UePhyTx(SfnSf sfn,
472 [[maybe_unused]] uint16_t nodeId,
473 [[maybe_unused]] uint16_t rnti,
474 [[maybe_unused]] uint8_t ccId,
475 Ptr<const NrControlMessage> msg)
476{
477 static NumerologyToType res = {
478 {
479 4,
480 {
482 {NrControlMessage::DL_HARQ, SfnSf(40, 0, 4, 4).Normalize()},
483 {NrControlMessage::DL_CQI, SfnSf(40, 0, 5, 4).Normalize()},
484 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 4).Normalize () },
485 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 4).Normalize () },
486 },
487 },
488 {
489 3,
490 {
492 {NrControlMessage::DL_HARQ, SfnSf(40, 0, 4, 3).Normalize()},
493 {NrControlMessage::DL_CQI, SfnSf(40, 0, 5, 3).Normalize()},
494 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 3).Normalize () },
495 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 3).Normalize () },
496 },
497 },
498 {
499 2,
500 {
502 {NrControlMessage::DL_HARQ, SfnSf(40, 1, 0, 2).Normalize()},
503 {NrControlMessage::DL_CQI, SfnSf(40, 1, 1, 2).Normalize()},
504 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 2).Normalize () },
505 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 2).Normalize () },
506 },
507 },
508 {
509 1,
510 {
512 {NrControlMessage::DL_HARQ, SfnSf(40, 2, 0, 1).Normalize()},
513 {NrControlMessage::DL_CQI, SfnSf(40, 2, 1, 1).Normalize()},
514 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 1).Normalize () },
515 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 1).Normalize () },
516 },
517 },
518 {
519 0,
520 {
522 {NrControlMessage::DL_HARQ, SfnSf(40, 4, 0, 0).Normalize()},
523 {NrControlMessage::DL_CQI, SfnSf(40, 5, 0, 0).Normalize()},
524 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 0).Normalize () },
525 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 0).Normalize () },
526 },
527 },
528 };
529
530 if (verbose && messageLog.at(msg->GetMessageType()))
531 {
532 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType()) << " at " << sfn
533 << " numerology " << m_numerology << " slot count " << sfn.Normalize() << " "
534 << Simulator::Now() << std::endl;
535 }
536
537 auto numMap = res.find(m_numerology);
538 if (numMap != res.end())
539 {
540 auto resMap = numMap->second.find(msg->GetMessageType());
541 if (resMap != numMap->second.end())
542 {
543 uint64_t slotN = resMap->second;
544 NS_TEST_ASSERT_MSG_EQ(slotN,
545 sfn.Normalize(),
546 "The message type " << TYPE_TO_STRING.at(msg->GetMessageType())
547 << " was supposed to be sent at slot "
548 << slotN << " but instead we sent it at "
549 << sfn.Normalize() << " in numerology "
550 << m_numerology);
551 return;
552 }
553 }
554
555 if (verbose && messageLog.at(msg->GetMessageType()))
556 {
557 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType())
558 << " not found in the result map;" << std::endl;
559 }
560}
561
562void
563NrTimingsTest::UePhyRx(SfnSf sfn,
564 [[maybe_unused]] uint16_t nodeId,
565 [[maybe_unused]] uint16_t rnti,
566 [[maybe_unused]] uint8_t ccId,
567 Ptr<const NrControlMessage> msg)
568{
569 static NumerologyToType res = {
570 {
571 4,
572 {
573 {NrControlMessage::RAR, SfnSf(1, 6, 4, 4).Normalize()},
574 {NrControlMessage::DL_DCI, SfnSf(40, 0, 2, 4).Normalize()},
575 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 4).Normalize () },
576 },
577 },
578 {
579 3,
580 {
581 {NrControlMessage::RAR, SfnSf(1, 6, 4, 3).Normalize()},
582 {NrControlMessage::DL_DCI, SfnSf(40, 0, 2, 3).Normalize()},
583 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 3).Normalize () },
584 },
585 },
586 {
587 2,
588 {
589 {NrControlMessage::RAR, SfnSf(1, 7, 0, 2).Normalize()},
590 {NrControlMessage::DL_DCI, SfnSf(40, 0, 2, 2).Normalize()},
591 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 2).Normalize () },
592 },
593 },
594 {
595 1,
596 {
597 {NrControlMessage::RAR, SfnSf(1, 8, 0, 1).Normalize()},
598 {NrControlMessage::DL_DCI, SfnSf(40, 1, 0, 1).Normalize()},
599 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 1).Normalize () },
600 },
601 },
602 {
603 0,
604 {
605 {NrControlMessage::RAR, SfnSf(2, 0, 0, 0).Normalize()},
606 {NrControlMessage::DL_DCI, SfnSf(40, 2, 0, 0).Normalize()},
607 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 0).Normalize () },
608 },
609 },
610 };
611
612 if (verbose && messageLog.at(msg->GetMessageType()))
613 {
614 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType()) << " at " << sfn
615 << " numerology " << m_numerology << " slot count " << sfn.Normalize() << " "
616 << Simulator::Now() << std::endl;
617 }
618
619 auto numMap = res.find(m_numerology);
620 if (numMap != res.end())
621 {
622 auto resMap = numMap->second.find(msg->GetMessageType());
623 if (resMap != numMap->second.end())
624 {
625 uint64_t slotN = resMap->second;
626 NS_TEST_ASSERT_MSG_EQ(slotN,
627 sfn.Normalize(),
628 "The message type " << TYPE_TO_STRING.at(msg->GetMessageType())
629 << " was supposed to be sent at slot "
630 << slotN << " but instead we sent it at "
631 << sfn.Normalize() << " in numerology "
632 << m_numerology);
633 return;
634 }
635 }
636
637 if (verbose && messageLog.at(msg->GetMessageType()))
638 {
639 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType())
640 << " not found in the result map;" << std::endl;
641 }
642}
643
644void
645NrTimingsTest::UeMacTx(SfnSf sfn,
646 [[maybe_unused]] uint16_t nodeId,
647 [[maybe_unused]] uint16_t rnti,
648 [[maybe_unused]] uint8_t ccId,
649 Ptr<const NrControlMessage> msg)
650{
651 static NumerologyToType res = {
652 {
653 4,
654 {
656 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 4).Normalize () },
657 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 4).Normalize () },
658 },
659 },
660 {
661 3,
662 {
664 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 3).Normalize () },
665 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 3).Normalize () },
666 },
667 },
668 {
669 2,
670 {
672 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 2).Normalize () },
673 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 2).Normalize () },
674 },
675 },
676 {
677 1,
678 {
680 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 1).Normalize () },
681 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 1).Normalize () },
682 },
683 },
684 {
685 0,
686 {
688 //{ NrControlMessage::SR, SfnSf (80, 0, 0, 0).Normalize () },
689 //{ NrControlMessage::BSR, SfnSf (80, 0, 0, 0).Normalize () },
690 },
691 },
692 };
693
694 if (verbose && messageLog.at(msg->GetMessageType()))
695 {
696 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType()) << " at " << sfn
697 << " numerology " << m_numerology << " slot count " << sfn.Normalize() << " "
698 << Simulator::Now() << std::endl;
699 }
700
701 auto numMap = res.find(m_numerology);
702 if (numMap != res.end())
703 {
704 auto resMap = numMap->second.find(msg->GetMessageType());
705 if (resMap != numMap->second.end())
706 {
707 uint64_t slotN = resMap->second;
708 NS_TEST_ASSERT_MSG_EQ(slotN,
709 sfn.Normalize(),
710 "The message type " << TYPE_TO_STRING.at(msg->GetMessageType())
711 << " was supposed to be sent at slot "
712 << slotN << " but instead we sent it at "
713 << sfn.Normalize() << " in numerology "
714 << m_numerology);
715 return;
716 }
717 }
718
719 if (verbose && messageLog.at(msg->GetMessageType()))
720 {
721 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType())
722 << " not found in the result map;" << std::endl;
723 }
724}
725
726void
727NrTimingsTest::UeMacRx(SfnSf sfn,
728 [[maybe_unused]] uint16_t nodeId,
729 [[maybe_unused]] uint16_t rnti,
730 [[maybe_unused]] uint8_t ccId,
731 Ptr<const NrControlMessage> msg)
732{
733 static NumerologyToType res = {
734 {
735 4,
736 {
737 {NrControlMessage::RAR, SfnSf(1, 6, 4, 4).Normalize()},
738 {NrControlMessage::DL_DCI, SfnSf(40, 0, 2, 4).Normalize()},
739 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 4).Normalize () },
740 },
741 },
742 {
743 3,
744 {
745 {NrControlMessage::RAR, SfnSf(1, 6, 4, 3).Normalize()},
746 {NrControlMessage::DL_DCI, SfnSf(40, 0, 2, 3).Normalize()},
747 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 3).Normalize () },
748 },
749 },
750 {
751 2,
752 {
753 {NrControlMessage::RAR, SfnSf(1, 7, 0, 2).Normalize()},
754 {NrControlMessage::DL_DCI, SfnSf(40, 0, 2, 2).Normalize()},
755 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 2).Normalize () },
756 },
757 },
758 {
759 1,
760 {
761 {NrControlMessage::RAR, SfnSf(1, 8, 0, 1).Normalize()},
762 {NrControlMessage::DL_DCI, SfnSf(40, 1, 0, 1).Normalize()},
763 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 1).Normalize () },
764 },
765 },
766 {0,
767 {
768 {NrControlMessage::RAR, SfnSf(2, 0, 0, 0).Normalize()},
769 {NrControlMessage::DL_DCI, SfnSf(40, 2, 0, 0).Normalize()},
770 //{ NrControlMessage::DCI, SfnSf (80, 0, 2, 0).Normalize () },
771 }},
772 };
773
774 if (verbose && messageLog.at(msg->GetMessageType()))
775 {
776 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType()) << " at " << sfn
777 << " numerology " << m_numerology << " slot count " << sfn.Normalize() << " "
778 << Simulator::Now() << std::endl;
779 }
780
781 auto numMap = res.find(m_numerology);
782 if (numMap != res.end())
783 {
784 auto resMap = numMap->second.find(msg->GetMessageType());
785 if (resMap != numMap->second.end())
786 {
787 uint64_t slotN = resMap->second;
788 NS_TEST_ASSERT_MSG_EQ(slotN,
789 sfn.Normalize(),
790 "The message type " << TYPE_TO_STRING.at(msg->GetMessageType())
791 << " was supposed to be sent at slot "
792 << slotN << " but instead we sent it at "
793 << sfn.Normalize() << " in numerology "
794 << m_numerology);
795 return;
796 }
797 }
798
799 if (verbose && messageLog.at(msg->GetMessageType()))
800 {
801 std::cerr << __func__ << ": " << TYPE_TO_STRING.at(msg->GetMessageType())
802 << " not found in the result map;" << std::endl;
803 }
804}
805
806// Ugly pre-processor macro, to speed up writing. The best way would be to use
807// static functions... so please forget them, and remember that they work
808// only here in the DoRun function, as it is all hard-coded
809#define GET_GNB_PHY(X, Y) nrHelper->GetGnbPhy(gnbNetDev.Get(X), Y)
810#define GET_GNB_MAC(X, Y) nrHelper->GetGnbMac(gnbNetDev.Get(X), Y)
811
812#define GET_UE_PHY(X, Y) nrHelper->GetUePhy(ueNetDev.Get(X), Y)
813#define GET_UE_MAC(X, Y) nrHelper->GetUeMac(ueNetDev.Get(X), Y)
814
815void
816NrTimingsTest::DoRun()
817{
818 Ptr<Node> ueNode = CreateObject<Node>();
819 Ptr<Node> gNbNode = CreateObject<Node>();
820
821 MobilityHelper mobility;
822 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
823 mobility.Install(gNbNode);
824 mobility.Install(ueNode);
825 gNbNode->GetObject<MobilityModel>()->SetPosition(Vector(0.0, 0.0, 10));
826 ueNode->GetObject<MobilityModel>()->SetPosition(Vector(0, 10, 1.5));
827
828 RngSeedManager::SetSeed(1);
829 RngSeedManager::SetRun(1);
830
831 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
832 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
833 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
834 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
835 // Set the spectrum channel using the UMi scenario and some attributes
836 channelHelper->ConfigureFactories("UMi");
837 Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue(MilliSeconds(0)));
838
839 channelHelper->SetChannelConditionModelAttribute("UpdatePeriod", TimeValue(MilliSeconds(0)));
840 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(false));
841
842 // Put the pointers inside nrHelper
843 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
844 nrHelper->SetEpcHelper(nrEpcHelper);
845
847 CcBwpCreator ccBwpCreator;
848 const uint8_t numCcPerBand = 1; // in this example, both bands have a single CC
849
850 CcBwpCreator::SimpleOperationBandConf bandConf1(28e9, 100e6, numCcPerBand);
851 OperationBandInfo band1 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf1);
852 channelHelper->AssignChannelsToBands({band1});
853 allBwps = CcBwpCreator::GetAllBwps({band1});
854 // Beamforming method
855 idealBeamformingHelper->SetAttribute("BeamformingMethod",
856 TypeIdValue(DirectPathBeamforming::GetTypeId()));
857
858 // Core latency
859 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
860
861 // Antennas for all the UEs
862 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(2));
863 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(4));
864 nrHelper->SetUeAntennaAttribute("AntennaElement",
865 PointerValue(CreateObject<IsotropicAntennaModel>()));
866
867 // Antennas for all the gNbs
868 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(4));
869 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(8));
870 nrHelper->SetGnbAntennaAttribute("AntennaElement",
871 PointerValue(CreateObject<IsotropicAntennaModel>()));
872
873 nrHelper->SetSchedulerAttribute("StartingMcsDl", UintegerValue(28));
874 nrHelper->SetSchedulerAttribute("StartingMcsUl", UintegerValue(28));
875
876 nrHelper->SetGnbPhyAttribute("Numerology", UintegerValue(m_numerology));
877 nrHelper->SetGnbPhyAttribute("TxPower", DoubleValue(50.0));
878
879 nrHelper->SetUePhyAttribute("TxPower", DoubleValue(50.0));
880
881 NetDeviceContainer gnbNetDev = nrHelper->InstallGnbDevice(gNbNode, allBwps);
882 NetDeviceContainer ueNetDev = nrHelper->InstallUeDevice(ueNode, allBwps);
883
884 int64_t randomStream = 1;
885 randomStream += nrHelper->AssignStreams(gnbNetDev, randomStream);
886 randomStream += nrHelper->AssignStreams(ueNetDev, randomStream);
887
888 GET_GNB_PHY(0, 0)->TraceConnectWithoutContext("GnbPhyTxedCtrlMsgsTrace",
889 MakeCallback(&NrTimingsTest::GnbPhyTx, this));
890 GET_GNB_PHY(0, 0)->TraceConnectWithoutContext("GnbPhyRxedCtrlMsgsTrace",
891 MakeCallback(&NrTimingsTest::GnbPhyRx, this));
892
893 GET_GNB_MAC(0, 0)->TraceConnectWithoutContext("GnbMacTxedCtrlMsgsTrace",
894 MakeCallback(&NrTimingsTest::GnbMacTx, this));
895 GET_GNB_MAC(0, 0)->TraceConnectWithoutContext("GnbMacRxedCtrlMsgsTrace",
896 MakeCallback(&NrTimingsTest::GnbMacRx, this));
897
898 GET_UE_PHY(0, 0)->TraceConnectWithoutContext("UePhyTxedCtrlMsgsTrace",
899 MakeCallback(&NrTimingsTest::UePhyTx, this));
900 GET_UE_PHY(0, 0)->TraceConnectWithoutContext("UePhyRxedCtrlMsgsTrace",
901 MakeCallback(&NrTimingsTest::UePhyRx, this));
902
903 GET_UE_MAC(0, 0)->TraceConnectWithoutContext("UeMacTxedCtrlMsgsTrace",
904 MakeCallback(&NrTimingsTest::UeMacTx, this));
905 GET_UE_MAC(0, 0)->TraceConnectWithoutContext("UeMacRxedCtrlMsgsTrace",
906 MakeCallback(&NrTimingsTest::UeMacRx, this));
907
908 InternetStackHelper internet;
909 internet.Install(ueNode);
910 Ipv4InterfaceContainer ueIpIface;
911 ueIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueNetDev));
912
913 nrHelper->AttachToClosestGnb(ueNetDev, gnbNetDev);
914
915 // DL at 0.4
916 Simulator::Schedule(MilliSeconds(400),
917 &SendPacket,
918 gnbNetDev.Get(0),
919 ueNetDev.Get(0)->GetAddress());
920
921 // UL at 0.8
922 // Simulator::Schedule (MilliSeconds (800), &SendPacket, ueNetDev.Get(0),
923 // gnbNetDev.Get(0)->GetAddress ());
924
925 Simulator::Stop(MilliSeconds(1200));
926
927 if (verbose)
928 {
929 std::cerr << "Executing test for numerology " << m_numerology << std::endl;
930 }
931 Simulator::Run();
932 Simulator::Destroy();
933}
934
935class NrTimingsTestSuite : public TestSuite
936{
937 public:
938 NrTimingsTestSuite();
939};
940
941NrTimingsTestSuite::NrTimingsTestSuite()
942 : TestSuite("nr-test-timings", Type::SYSTEM)
943{
944 AddTestCase(new NrTimingsTest("num=4", 4, false), Duration::QUICK);
945 AddTestCase(new NrTimingsTest("num=3", 3, false), Duration::QUICK);
946 AddTestCase(new NrTimingsTest("num=2", 2, false), Duration::QUICK);
947 AddTestCase(new NrTimingsTest("num=1", 1, false), Duration::QUICK);
948 AddTestCase(new NrTimingsTest("num=0", 0, false), Duration::QUICK);
949}
950
951// Do not forget to allocate an instance of this TestSuite
952static NrTimingsTestSuite nrTimingsTestSuite;
Manages the correct creation of operation bands, component carriers and bandwidth parts.
OperationBandInfo CreateOperationBandContiguousCc(const SimpleOperationBandConf &conf)
Create an operation band with the CC specified.
static BandwidthPartInfoPtrVector GetAllBwps(const std::vector< std::reference_wrapper< OperationBandInfo > > &operationBands)
Get all the BWP pointers from the specified vector of operation bands.
static TypeId GetTypeId()
Get the type id.
@ DL_HARQ
DL HARQ feedback.
@ RACH_PREAMBLE
Random Access Preamble.
@ RAR
Random Access Response.
@ DL_DCI
The resources allocation map from the BS to the attached UEs (DL)
The SfnSf class.
Definition sfnsf.h:32
uint64_t Normalize() const
Normalize the SfnSf in slot number.
Definition sfnsf.cc:99
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Minimum configuration requirements for a OperationBand.
Operation band information structure.