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"
15#include <unordered_map>
32static uint32_t packetSize = 21;
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},
47typedef std::unordered_map<NrControlMessage::messageType, uint64_t, std::hash<int>> TypeToResult;
48typedef std::unordered_map<uint32_t, TypeToResult> NumerologyToType;
50class NrTimingsTest :
public TestCase
53 NrTimingsTest(
const std::string& name, uint32_t numerology,
bool verbose);
54 ~NrTimingsTest()
override;
57 void DoRun()
override;
58 void GnbPhyTx(
SfnSf sfn,
62 Ptr<const NrControlMessage> msg);
63 void GnbPhyRx(
SfnSf sfn,
67 Ptr<const NrControlMessage> msg);
69 void GnbMacTx(
SfnSf sfn,
73 Ptr<const NrControlMessage> msg);
74 void GnbMacRx(
SfnSf sfn,
78 Ptr<const NrControlMessage> msg);
80 void UePhyTx(
SfnSf sfn,
84 Ptr<const NrControlMessage> msg);
85 void UePhyRx(
SfnSf sfn,
89 Ptr<const NrControlMessage> msg);
91 void UeMacTx(
SfnSf sfn,
95 Ptr<const NrControlMessage> msg);
96 void UeMacRx(
SfnSf sfn,
100 Ptr<const NrControlMessage> msg);
102 uint32_t m_numerology;
106NrTimingsTest::NrTimingsTest(
const std::string& name, uint32_t numerology,
bool verbose)
108 m_numerology(numerology),
113NrTimingsTest::~NrTimingsTest()
118SendPacket(
const Ptr<NetDevice>& device,
const Address& addr)
121 NS_ASSERT(packetSize > header.GetSerializedSize());
122 Ptr<Packet> pkt = Create<Packet>(packetSize - header.GetSerializedSize());
123 header.SetProtocol(0x06);
125 pkt->AddPacketTag(tag);
126 pkt->AddHeader(header);
127 device->Send(pkt, addr, Ipv4L3Protocol::PROT_NUMBER);
130static const std::unordered_map<NrControlMessage::messageType, std::string, std::hash<int>>
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"},
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)
151 static NumerologyToType res = {
195 if (verbose && messageLog.at(msg->GetMessageType()))
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;
202 auto numMap = res.find(m_numerology);
203 if (numMap != res.end())
205 auto resMap = numMap->second.find(msg->GetMessageType());
206 if (resMap != numMap->second.end())
208 uint64_t slotN = resMap->second;
209 NS_TEST_ASSERT_MSG_EQ(slotN,
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 "
220 if (verbose && messageLog.at(msg->GetMessageType()))
222 std::cerr << __func__ <<
": " << TYPE_TO_STRING.at(msg->GetMessageType())
223 <<
" not found in the result map;" << std::endl;
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)
234 static NumerologyToType res = {
287 if (verbose && messageLog.at(msg->GetMessageType()))
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;
294 auto numMap = res.find(m_numerology);
295 if (numMap != res.end())
297 auto resMap = numMap->second.find(msg->GetMessageType());
298 if (resMap != numMap->second.end())
300 uint64_t slotN = resMap->second;
301 NS_TEST_ASSERT_MSG_EQ(slotN,
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 "
312 if (verbose && messageLog.at(msg->GetMessageType()))
314 std::cerr << __func__ <<
": " << TYPE_TO_STRING.at(msg->GetMessageType())
315 <<
" not found in the result map;" << std::endl;
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)
326 static NumerologyToType res = {
349 if (verbose && messageLog.at(msg->GetMessageType()))
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;
356 auto numMap = res.find(m_numerology);
357 if (numMap != res.end())
359 auto resMap = numMap->second.find(msg->GetMessageType());
360 if (resMap != numMap->second.end())
362 uint64_t slotN = resMap->second;
363 NS_TEST_ASSERT_MSG_EQ(slotN,
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 "
374 if (verbose && messageLog.at(msg->GetMessageType()))
376 std::cerr << __func__ <<
": " << TYPE_TO_STRING.at(msg->GetMessageType())
377 <<
" not found in the result map;" << std::endl;
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)
388 static NumerologyToType res = {
436 if (verbose && messageLog.at(msg->GetMessageType()))
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;
443 auto numMap = res.find(m_numerology);
444 if (numMap != res.end())
446 auto resMap = numMap->second.find(msg->GetMessageType());
447 if (resMap != numMap->second.end())
449 uint64_t slotN = resMap->second;
450 NS_TEST_ASSERT_MSG_EQ(slotN,
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 "
461 if (verbose && messageLog.at(msg->GetMessageType()))
463 std::cerr << __func__ <<
": " << TYPE_TO_STRING.at(msg->GetMessageType())
464 <<
" not found in the result map;" << std::endl;
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)
477 static NumerologyToType res = {
530 if (verbose && messageLog.at(msg->GetMessageType()))
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;
537 auto numMap = res.find(m_numerology);
538 if (numMap != res.end())
540 auto resMap = numMap->second.find(msg->GetMessageType());
541 if (resMap != numMap->second.end())
543 uint64_t slotN = resMap->second;
544 NS_TEST_ASSERT_MSG_EQ(slotN,
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 "
555 if (verbose && messageLog.at(msg->GetMessageType()))
557 std::cerr << __func__ <<
": " << TYPE_TO_STRING.at(msg->GetMessageType())
558 <<
" not found in the result map;" << std::endl;
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)
569 static NumerologyToType res = {
612 if (verbose && messageLog.at(msg->GetMessageType()))
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;
619 auto numMap = res.find(m_numerology);
620 if (numMap != res.end())
622 auto resMap = numMap->second.find(msg->GetMessageType());
623 if (resMap != numMap->second.end())
625 uint64_t slotN = resMap->second;
626 NS_TEST_ASSERT_MSG_EQ(slotN,
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 "
637 if (verbose && messageLog.at(msg->GetMessageType()))
639 std::cerr << __func__ <<
": " << TYPE_TO_STRING.at(msg->GetMessageType())
640 <<
" not found in the result map;" << std::endl;
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)
651 static NumerologyToType res = {
694 if (verbose && messageLog.at(msg->GetMessageType()))
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;
701 auto numMap = res.find(m_numerology);
702 if (numMap != res.end())
704 auto resMap = numMap->second.find(msg->GetMessageType());
705 if (resMap != numMap->second.end())
707 uint64_t slotN = resMap->second;
708 NS_TEST_ASSERT_MSG_EQ(slotN,
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 "
719 if (verbose && messageLog.at(msg->GetMessageType()))
721 std::cerr << __func__ <<
": " << TYPE_TO_STRING.at(msg->GetMessageType())
722 <<
" not found in the result map;" << std::endl;
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)
733 static NumerologyToType res = {
774 if (verbose && messageLog.at(msg->GetMessageType()))
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;
781 auto numMap = res.find(m_numerology);
782 if (numMap != res.end())
784 auto resMap = numMap->second.find(msg->GetMessageType());
785 if (resMap != numMap->second.end())
787 uint64_t slotN = resMap->second;
788 NS_TEST_ASSERT_MSG_EQ(slotN,
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 "
799 if (verbose && messageLog.at(msg->GetMessageType()))
801 std::cerr << __func__ <<
": " << TYPE_TO_STRING.at(msg->GetMessageType())
802 <<
" not found in the result map;" << std::endl;
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)
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)
816NrTimingsTest::DoRun()
818 Ptr<Node> ueNode = CreateObject<Node>();
819 Ptr<Node> gNbNode = CreateObject<Node>();
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));
828 RngSeedManager::SetSeed(1);
829 RngSeedManager::SetRun(1);
831 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
832 Ptr<IdealBeamformingHelper> idealBeamformingHelper = CreateObject<IdealBeamformingHelper>();
833 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
834 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
836 channelHelper->ConfigureFactories(
"UMi");
837 Config::SetDefault(
"ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue(MilliSeconds(0)));
839 channelHelper->SetChannelConditionModelAttribute(
"UpdatePeriod", TimeValue(MilliSeconds(0)));
840 channelHelper->SetPathlossAttribute(
"ShadowingEnabled", BooleanValue(
false));
843 nrHelper->SetBeamformingHelper(idealBeamformingHelper);
844 nrHelper->SetEpcHelper(nrEpcHelper);
848 const uint8_t numCcPerBand = 1;
852 channelHelper->AssignChannelsToBands({band1});
855 idealBeamformingHelper->SetAttribute(
"BeamformingMethod",
859 nrEpcHelper->SetAttribute(
"S1uLinkDelay", TimeValue(MilliSeconds(0)));
862 nrHelper->SetUeAntennaAttribute(
"NumRows", UintegerValue(2));
863 nrHelper->SetUeAntennaAttribute(
"NumColumns", UintegerValue(4));
864 nrHelper->SetUeAntennaAttribute(
"AntennaElement",
865 PointerValue(CreateObject<IsotropicAntennaModel>()));
868 nrHelper->SetGnbAntennaAttribute(
"NumRows", UintegerValue(4));
869 nrHelper->SetGnbAntennaAttribute(
"NumColumns", UintegerValue(8));
870 nrHelper->SetGnbAntennaAttribute(
"AntennaElement",
871 PointerValue(CreateObject<IsotropicAntennaModel>()));
873 nrHelper->SetSchedulerAttribute(
"StartingMcsDl", UintegerValue(28));
874 nrHelper->SetSchedulerAttribute(
"StartingMcsUl", UintegerValue(28));
876 nrHelper->SetGnbPhyAttribute(
"Numerology", UintegerValue(m_numerology));
877 nrHelper->SetGnbPhyAttribute(
"TxPower", DoubleValue(50.0));
879 nrHelper->SetUePhyAttribute(
"TxPower", DoubleValue(50.0));
881 NetDeviceContainer gnbNetDev = nrHelper->InstallGnbDevice(gNbNode, allBwps);
882 NetDeviceContainer ueNetDev = nrHelper->InstallUeDevice(ueNode, allBwps);
884 int64_t randomStream = 1;
885 randomStream += nrHelper->AssignStreams(gnbNetDev, randomStream);
886 randomStream += nrHelper->AssignStreams(ueNetDev, randomStream);
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));
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));
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));
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));
908 InternetStackHelper internet;
909 internet.Install(ueNode);
910 Ipv4InterfaceContainer ueIpIface;
911 ueIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueNetDev));
913 nrHelper->AttachToClosestGnb(ueNetDev, gnbNetDev);
916 Simulator::Schedule(MilliSeconds(400),
919 ueNetDev.Get(0)->GetAddress());
925 Simulator::Stop(MilliSeconds(1200));
929 std::cerr <<
"Executing test for numerology " << m_numerology << std::endl;
932 Simulator::Destroy();
935class NrTimingsTestSuite :
public TestSuite
938 NrTimingsTestSuite();
941NrTimingsTestSuite::NrTimingsTestSuite()
942 : TestSuite(
"nr-test-timings", Type::SYSTEM)
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);
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.
@ 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)
uint64_t Normalize() const
Normalize the SfnSf in slot number.
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Minimum configuration requirements for a OperationBand.
Operation band information structure.