5G-LENA nr-v4.1
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-ue-mac.cc
1// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#define NS_LOG_APPEND_CONTEXT \
6 do \
7 { \
8 std::clog << " [ CellId " << GetCellId() << ", bwpId " << GetBwpId() << ", rnti " \
9 << m_rnti << "] "; \
10 } while (false);
11
12#include "nr-ue-mac.h"
13
14#include "nr-control-messages.h"
15#include "nr-mac-header-vs.h"
16#include "nr-mac-short-bsr-ce.h"
17#include "nr-phy-sap.h"
18#include "nr-radio-bearer-tag.h"
19
20#include "ns3/boolean.h"
21#include "ns3/log.h"
22#include "ns3/random-variable-stream.h"
23#include "ns3/uinteger.h"
24
25namespace ns3
26{
27
28NS_LOG_COMPONENT_DEFINE("NrUeMac");
29NS_OBJECT_ENSURE_REGISTERED(NrUeMac);
30
31uint8_t NrUeMac::g_raPreambleId = 0;
32
34// SAP forwarders
36
37class UeMemberNrUeCmacSapProvider : public NrUeCmacSapProvider
38{
39 public:
40 UeMemberNrUeCmacSapProvider(NrUeMac* mac);
41
42 // inherited from NrUeCmacSapProvider
43 void ConfigureRach(RachConfig rc) override;
44 void StartContentionBasedRandomAccessProcedure() override;
45 void StartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
46 uint8_t preambleId,
47 uint8_t prachMask) override;
48 void AddLc(uint8_t lcId,
49 NrUeCmacSapProvider::LogicalChannelConfig lcConfig,
50 NrMacSapUser* msu) override;
51 void RemoveLc(uint8_t lcId) override;
52 void Reset() override;
53 void SetRnti(uint16_t rnti) override;
54 void NotifyConnectionSuccessful() override;
55 void SetImsi(uint64_t imsi) override;
56
57 private:
58 NrUeMac* m_mac;
59};
60
61UeMemberNrUeCmacSapProvider::UeMemberNrUeCmacSapProvider(NrUeMac* mac)
62 : m_mac(mac)
63{
64}
65
66void
67UeMemberNrUeCmacSapProvider::ConfigureRach(RachConfig rc)
68{
69 m_mac->DoConfigureRach(rc);
70}
71
72void
73UeMemberNrUeCmacSapProvider::StartContentionBasedRandomAccessProcedure()
74{
75 m_mac->DoStartContentionBasedRandomAccessProcedure();
76}
77
78void
79UeMemberNrUeCmacSapProvider::StartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
80 uint8_t preambleId,
81 uint8_t prachMask)
82{
83 m_mac->DoStartNonContentionBasedRandomAccessProcedure(rnti, preambleId, prachMask);
84}
85
86void
87UeMemberNrUeCmacSapProvider::AddLc(uint8_t lcId, LogicalChannelConfig lcConfig, NrMacSapUser* msu)
88{
89 m_mac->AddLc(lcId, lcConfig, msu);
90}
91
92void
93UeMemberNrUeCmacSapProvider::RemoveLc(uint8_t lcid)
94{
95 m_mac->DoRemoveLc(lcid);
96}
97
98void
99UeMemberNrUeCmacSapProvider::Reset()
100{
101 m_mac->DoReset();
102}
103
104void
105UeMemberNrUeCmacSapProvider::SetRnti(uint16_t rnti)
106{
107 m_mac->SetRnti(rnti);
108}
109
110void
111UeMemberNrUeCmacSapProvider::NotifyConnectionSuccessful()
112{
113 m_mac->DoNotifyConnectionSuccessful();
114}
115
116void
117UeMemberNrUeCmacSapProvider::SetImsi(uint64_t imsi)
118{
119 m_mac->DoSetImsi(imsi);
120}
121
122class UeMemberNrMacSapProvider : public NrMacSapProvider
123{
124 public:
125 UeMemberNrMacSapProvider(NrUeMac* mac);
126
127 // inherited from NrMacSapProvider
128 void TransmitPdu(TransmitPduParameters params) override;
129 void BufferStatusReport(BufferStatusReportParameters params) override;
130
131 private:
132 NrUeMac* m_mac;
133};
134
135UeMemberNrMacSapProvider::UeMemberNrMacSapProvider(NrUeMac* mac)
136 : m_mac(mac)
137{
138}
139
140void
141UeMemberNrMacSapProvider::TransmitPdu(TransmitPduParameters params)
142{
143 m_mac->DoTransmitPdu(params);
144}
145
146void
147UeMemberNrMacSapProvider::BufferStatusReport(BufferStatusReportParameters params)
148{
149 m_mac->DoTransmitBufferStatusReport(params);
150}
151
152class NrUePhySapUser;
153
154class MacUeMemberPhySapUser : public NrUePhySapUser
155{
156 public:
157 MacUeMemberPhySapUser(NrUeMac* mac);
158
159 void ReceivePhyPdu(Ptr<Packet> p) override;
160
161 void ReceiveControlMessage(Ptr<NrControlMessage> msg) override;
162
163 void SlotIndication(SfnSf sfn) override;
164
165 // virtual void NotifyHarqDeliveryFailure (uint8_t harqId);
166
167 uint8_t GetNumHarqProcess() const override;
168
169 private:
170 NrUeMac* m_mac;
171};
172
173MacUeMemberPhySapUser::MacUeMemberPhySapUser(NrUeMac* mac)
174 : m_mac(mac)
175{
176}
177
178void
179MacUeMemberPhySapUser::ReceivePhyPdu(Ptr<Packet> p)
180{
181 m_mac->DoReceivePhyPdu(p);
182}
183
184void
185MacUeMemberPhySapUser::ReceiveControlMessage(Ptr<NrControlMessage> msg)
186{
187 m_mac->DoReceiveControlMessage(msg);
188}
189
190void
191MacUeMemberPhySapUser::SlotIndication(SfnSf sfn)
192{
193 m_mac->DoSlotIndication(sfn);
194}
195
196uint8_t
197MacUeMemberPhySapUser::GetNumHarqProcess() const
198{
199 return m_mac->GetNumHarqProcess();
200}
201
202//-----------------------------------------------------------------------
203
204TypeId
205NrUeMac::GetTypeId()
206{
207 static TypeId tid =
208 TypeId("ns3::NrUeMac")
209 .SetParent<Object>()
210 .AddConstructor<NrUeMac>()
211 .AddAttribute(
212 "NumHarqProcess",
213 "Number of concurrent stop-and-wait Hybrid ARQ processes per user",
214 UintegerValue(16),
215 MakeUintegerAccessor(&NrUeMac::SetNumHarqProcess, &NrUeMac::GetNumHarqProcess),
216 MakeUintegerChecker<uint8_t>())
217 .AddTraceSource("UeMacRxedCtrlMsgsTrace",
218 "Ue MAC Control Messages Traces.",
219 MakeTraceSourceAccessor(&NrUeMac::m_macRxedCtrlMsgsTrace),
220 "ns3::NrMacRxTrace::RxedUeMacCtrlMsgsTracedCallback")
221 .AddTraceSource("UeMacTxedCtrlMsgsTrace",
222 "Ue MAC Control Messages Traces.",
223 MakeTraceSourceAccessor(&NrUeMac::m_macTxedCtrlMsgsTrace),
224 "ns3::NrMacRxTrace::TxedUeMacCtrlMsgsTracedCallback")
225 .AddTraceSource("RaResponseTimeout",
226 "Trace fired upon RA response timeout",
227 MakeTraceSourceAccessor(&NrUeMac::m_raResponseTimeoutTrace),
228 "ns3::NrUeMac::RaResponseTimeoutTracedCallback")
229 .AddTraceSource("UeMacStateMachineTrace",
230 "UE MAC state machine trace",
231 MakeTraceSourceAccessor(&NrUeMac::m_macUeStateMachine),
232 "ns3::NrUeMac::UeMacStateMachineTracedCallback");
233 return tid;
234}
235
236NrUeMac::NrUeMac()
237 : Object()
238{
239 NS_LOG_FUNCTION(this);
240 m_cmacSapProvider = new UeMemberNrUeCmacSapProvider(this);
241 m_macSapProvider = new UeMemberNrMacSapProvider(this);
242 m_phySapUser = new MacUeMemberPhySapUser(this);
243 m_raPreambleUniformVariable = CreateObject<UniformRandomVariable>();
244}
245
249
250void
252{
253 m_miUlHarqProcessesPacket.clear();
254 m_miUlHarqProcessesPacketTimer.clear();
255 m_ulBsrReceived.clear();
256 m_lcInfoMap.clear();
257 m_raPreambleUniformVariable = nullptr;
258 delete m_macSapProvider;
259 delete m_cmacSapProvider;
260 delete m_phySapUser;
261}
262
263void
264NrUeMac::SetRnti(uint16_t rnti)
265{
266 NS_LOG_FUNCTION(this);
267 m_rnti = rnti;
268}
269
270void
271NrUeMac::DoNotifyConnectionSuccessful()
272{
273 NS_LOG_FUNCTION(this);
274 m_phySapProvider->NotifyConnectionSuccessful();
275}
276
277void
278NrUeMac::DoSetImsi(uint64_t imsi)
279{
280 NS_LOG_FUNCTION(this);
281 m_imsi = imsi;
282}
283
284uint16_t
286{
287 if (m_phySapProvider)
288 {
289 return m_phySapProvider->GetBwpId();
290 }
291 else
292 {
293 return UINT16_MAX;
294 }
295}
296
297uint16_t
299{
300 if (m_phySapProvider)
301 {
302 return m_phySapProvider->GetCellId();
303 }
304 else
305 {
306 return UINT16_MAX;
307 }
308}
309
310uint16_t
312{
313 return m_rnti;
314}
315
316uint64_t
318{
319 return m_imsi;
320}
321
322void
324{
325 m_currentSlot = sfn;
326}
327
328uint32_t
329NrUeMac::GetTotalBufSize() const
330{
331 uint32_t ret = 0;
332 for (const auto& it : m_ulBsrReceived)
333 {
334 ret += (it.second.txQueueSize + it.second.retxQueueSize + it.second.statusPduSize);
335 }
336 return ret;
337}
338
343void
344NrUeMac::SetNumHarqProcess(uint8_t numHarqProcess)
345{
346 m_numHarqProcess = numHarqProcess;
347
348 m_miUlHarqProcessesPacket.resize(GetNumHarqProcess());
349 for (auto& i : m_miUlHarqProcessesPacket)
350 {
351 if (i.m_pktBurst == nullptr)
352 {
353 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
354 i.m_pktBurst = pb;
355 }
356 }
357 m_miUlHarqProcessesPacketTimer.resize(GetNumHarqProcess(), 0);
358}
359
363uint8_t
365{
366 return m_numHarqProcess;
367}
368
369// forwarded from MAC SAP
370void
371NrUeMac::DoTransmitPdu(NrMacSapProvider::TransmitPduParameters params)
372{
373 NS_LOG_FUNCTION(this);
374 if (m_ulDci == nullptr)
375 {
376 return;
377 }
378 NS_ASSERT(m_ulDci);
379 NS_ASSERT(m_ulDci->m_harqProcess == params.harqProcessId);
380
381 m_miUlHarqProcessesPacket.at(params.harqProcessId).m_lcidList.push_back(params.lcid);
382
383 NrMacHeaderVs header;
384 header.SetLcId(params.lcid);
385 header.SetSize(params.pdu->GetSize());
386
387 params.pdu->AddHeader(header);
388
389 NrRadioBearerTag bearerTag(params.rnti, params.lcid, 0);
390 params.pdu->AddPacketTag(bearerTag);
391
392 if (!m_miUlHarqProcessesPacket.at(params.harqProcessId).m_pktBurst)
393 {
394 m_miUlHarqProcessesPacket.at(params.harqProcessId).m_pktBurst = CreateObject<PacketBurst>();
395 }
396 m_miUlHarqProcessesPacket.at(params.harqProcessId).m_pktBurst->AddPacket(params.pdu);
397 m_miUlHarqProcessesPacketTimer.at(params.harqProcessId) = GetNumHarqProcess();
398
399 m_ulDciTotalUsed += params.pdu->GetSize();
400
401 NS_ASSERT_MSG(m_ulDciTotalUsed <= m_ulDci->m_tbSize,
402 "We used more data than the DCI allowed us.");
403
404 m_phySapProvider->SendMacPdu(params.pdu, m_ulDciSfnsf, m_ulDci->m_symStart, m_ulDci->m_rnti);
405}
406
407void
408NrUeMac::DoTransmitBufferStatusReport(NrMacSapProvider::BufferStatusReportParameters params)
409{
410 NS_LOG_FUNCTION(this << static_cast<uint32_t>(params.lcid));
411
412 auto it = m_ulBsrReceived.find(params.lcid);
413
414 NS_LOG_INFO("Received BSR for LC Id" << static_cast<uint32_t>(params.lcid));
415
416 if (it != m_ulBsrReceived.end())
417 {
418 // update entry
419 (*it).second = params;
420 }
421 else
422 {
423 it = m_ulBsrReceived.insert(std::make_pair(params.lcid, params)).first;
424 }
425
426 if (m_srState == INACTIVE ||
427 (params.expBsrTimer && m_srState == ACTIVE && m_ulDci->m_harqProcess > 0 &&
428 m_ulDci->m_rv == 3) ||
429 (params.expBsrTimer && m_srState == ACTIVE && m_ulDci->m_harqProcess == 0))
430 {
431 if (m_srState == INACTIVE)
432 {
433 NS_LOG_INFO("m_srState = INACTIVE -> TO_SEND, bufSize " << GetTotalBufSize());
434 m_macUeStateMachine(m_currentSlot,
435 GetCellId(),
436 m_rnti,
437 GetBwpId(),
438 m_srState,
439 m_ulBsrReceived,
440 1,
441 "DoTransmitBufferStatusReport");
442 }
443 else
444 {
445 NS_LOG_INFO("m_srState = ACTIVE (BSR Timer expired) -> TO_SEND, bufSize "
446 << GetTotalBufSize());
447 m_macUeStateMachine(m_currentSlot,
448 GetCellId(),
449 m_rnti,
450 GetBwpId(),
451 m_srState,
452 m_ulBsrReceived,
453 0,
454 "DoTransmitBufferStatusReport");
455 }
456 m_srState = TO_SEND;
457 }
458}
459
460void
461NrUeMac::SendBufferStatusReport(const SfnSf& dataSfn, uint8_t symStart)
462{
463 NS_LOG_FUNCTION(this);
464
465 if (m_rnti == 0)
466 {
467 NS_LOG_INFO("MAC not initialized, BSR deferred");
468 return;
469 }
470
471 if (m_ulBsrReceived.empty())
472 {
473 NS_LOG_INFO("No BSR report to transmit");
474 return;
475 }
476 MacCeElement bsr = MacCeElement();
477 bsr.m_rnti = m_rnti;
478 bsr.m_macCeType = MacCeElement::BSR;
479
480 // BSR is reported for each LCG
481 std::unordered_map<uint8_t, NrMacSapProvider::BufferStatusReportParameters>::iterator it;
482 std::vector<uint32_t> queue(4, 0); // one value per each of the 4 LCGs, initialized to 0
483 for (it = m_ulBsrReceived.begin(); it != m_ulBsrReceived.end(); it++)
484 {
485 uint8_t lcid = it->first;
486 std::unordered_map<uint8_t, LcInfo>::iterator lcInfoMapIt;
487 lcInfoMapIt = m_lcInfoMap.find(lcid);
488 NS_ASSERT(lcInfoMapIt != m_lcInfoMap.end());
489 NS_ASSERT_MSG((lcid != 0) ||
490 (((*it).second.txQueueSize == 0) && ((*it).second.retxQueueSize == 0) &&
491 ((*it).second.statusPduSize == 0)),
492 "BSR should not be used for LCID 0");
493 uint8_t lcg = lcInfoMapIt->second.lcConfig.logicalChannelGroup;
494 queue.at(lcg) +=
495 ((*it).second.txQueueSize + (*it).second.retxQueueSize + (*it).second.statusPduSize);
496
497 if (queue.at(lcg) != 0)
498 {
499 NS_LOG_DEBUG("Adding 5 bytes for SHORT_BSR.");
500 queue.at(lcg) += 5;
501 }
502 if ((*it).second.txQueueSize > 0)
503 {
504 NS_LOG_DEBUG("Adding 3 bytes for TX subheader.");
505 queue.at(lcg) += 3;
506 }
507 if ((*it).second.retxQueueSize > 0)
508 {
509 NS_LOG_DEBUG("Adding 3 bytes for RX subheader.");
510 queue.at(lcg) += 3;
511 }
512 }
513
514 NS_LOG_INFO("Sending BSR with this info for the LCG: "
515 << queue.at(0) << " " << queue.at(1) << " " << queue.at(2) << " " << queue.at(3));
516 // FF API says that all 4 LCGs are always present
517 bsr.m_macCeValue.m_bufferStatus.push_back(NrMacShortBsrCe::FromBytesToLevel(queue.at(0)));
518 bsr.m_macCeValue.m_bufferStatus.push_back(NrMacShortBsrCe::FromBytesToLevel(queue.at(1)));
519 bsr.m_macCeValue.m_bufferStatus.push_back(NrMacShortBsrCe::FromBytesToLevel(queue.at(2)));
520 bsr.m_macCeValue.m_bufferStatus.push_back(NrMacShortBsrCe::FromBytesToLevel(queue.at(3)));
521
522 // create the message. It is used only for tracing, but we don't send it...
523 Ptr<NrBsrMessage> msg = Create<NrBsrMessage>();
524 msg->SetSourceBwp(GetBwpId());
525 msg->SetBsr(bsr);
526
527 m_macTxedCtrlMsgsTrace(m_currentSlot, GetCellId(), bsr.m_rnti, GetBwpId(), msg);
528
529 // Here we send the real SHORT_BSR, as a subpdu.
530 Ptr<Packet> p = Create<Packet>();
531
532 // Please note that the levels are defined from the standard. In this case,
533 // we have 5 bit available, so use such standard levels. In the future,
534 // when LONG BSR will be implemented, this have to change.
535 NrMacShortBsrCe header;
536 header.m_bufferSizeLevel_0 = NrMacShortBsrCe::FromBytesToLevel(queue.at(0));
537 header.m_bufferSizeLevel_1 = NrMacShortBsrCe::FromBytesToLevel(queue.at(1));
538 header.m_bufferSizeLevel_2 = NrMacShortBsrCe::FromBytesToLevel(queue.at(2));
539 header.m_bufferSizeLevel_3 = NrMacShortBsrCe::FromBytesToLevel(queue.at(3));
540
541 p->AddHeader(header);
542
543 NrRadioBearerTag bearerTag(m_rnti, NrMacHeaderFsUl::SHORT_BSR, 0);
544 p->AddPacketTag(bearerTag);
545
546 m_ulDciTotalUsed += p->GetSize();
547 NS_ASSERT_MSG(m_ulDciTotalUsed <= m_ulDci->m_tbSize,
548 "We used more data than the DCI allowed us.");
549
550 m_phySapProvider->SendMacPdu(p, dataSfn, symStart, m_ulDci->m_rnti);
551
552 m_macUeStateMachine(m_currentSlot,
553 GetCellId(),
554 m_rnti,
555 GetBwpId(),
556 m_srState,
557 m_ulBsrReceived,
558 m_ulDci->m_ndi,
559 "SendBufferStatusReport");
560}
561
562void
564{
565 m_cmacSapUser = s;
566}
567
570{
571 return m_cmacSapProvider;
572}
573
574void
575NrUeMac::RefreshHarqProcessesPacketBuffer()
576{
577 NS_LOG_FUNCTION(this);
578
579 for (std::size_t i = 0; i < m_miUlHarqProcessesPacketTimer.size(); i++)
580 {
581 if (m_miUlHarqProcessesPacketTimer.at(i) == 0 && m_miUlHarqProcessesPacket.at(i).m_pktBurst)
582 {
583 if (m_miUlHarqProcessesPacket.at(i).m_pktBurst->GetSize() > 0)
584 {
585 // timer expired: drop packets in buffer for this process
586 NS_LOG_INFO("HARQ Proc Id " << i << " packets buffer expired");
587 Ptr<PacketBurst> emptyPb = CreateObject<PacketBurst>();
588 m_miUlHarqProcessesPacket.at(i).m_pktBurst = emptyPb;
589 m_miUlHarqProcessesPacket.at(i).m_lcidList.clear();
590 }
591 }
592 else
593 {
594 // m_miUlHarqProcessesPacketTimer.at (i)--; // ignore HARQ timeout
595 }
596 }
597}
598
599void
600NrUeMac::DoSlotIndication(const SfnSf& sfn)
601{
602 NS_LOG_FUNCTION(this);
603 m_currentSlot = sfn;
604 NS_LOG_INFO("Slot " << m_currentSlot);
605
606 RefreshHarqProcessesPacketBuffer();
607
608 if (m_srState == TO_SEND)
609 {
610 NS_LOG_INFO("Sending SR to PHY in slot " << sfn);
611 SendSR();
612 m_srState = ACTIVE;
613 NS_LOG_INFO("m_srState = TO_SEND -> ACTIVE");
614 m_macUeStateMachine(m_currentSlot,
615 GetCellId(),
616 m_rnti,
617 GetBwpId(),
618 m_srState,
619 m_ulBsrReceived,
620 1,
621 "DoSlotIndication");
622 }
623
624 // Feedback missing
625}
626
627void
628NrUeMac::SendSR() const
629{
630 NS_LOG_FUNCTION(this);
631
632 if (m_rnti == 0)
633 {
634 NS_LOG_INFO("MAC not initialized, SR deferred");
635 return;
636 }
637
638 // create the SR to send to the gNB
639 Ptr<NrSRMessage> msg = Create<NrSRMessage>();
640 msg->SetSourceBwp(GetBwpId());
641 msg->SetRNTI(m_rnti);
642
643 m_macTxedCtrlMsgsTrace(m_currentSlot, GetCellId(), m_rnti, GetBwpId(), msg);
644 m_phySapProvider->SendControlMessage(msg);
645}
646
647void
648NrUeMac::DoReceivePhyPdu(Ptr<Packet> p)
649{
650 NS_LOG_FUNCTION(this);
651
652 NrRadioBearerTag tag;
653 p->RemovePacketTag(tag);
654
655 if (tag.GetRnti() != m_rnti) // Packet is for another user
656 {
657 return;
658 }
659
660 NrMacHeaderVs header;
661 p->RemoveHeader(header);
662
663 NrMacSapUser::ReceivePduParameters rxParams;
664 rxParams.p = p;
665 rxParams.rnti = m_rnti;
666 rxParams.lcid = header.GetLcId();
667
668 auto it = m_lcInfoMap.find(header.GetLcId());
669 // Ignore non-existing lcids
670 if (it == m_lcInfoMap.end())
671 {
672 return;
673 }
674
675 // p can be empty. Well, right now no, but when someone will add CE in downlink,
676 // then p can be empty.
677 if (rxParams.p->GetSize() > 0)
678 {
679 it->second.macSapUser->ReceivePdu(rxParams);
680 }
681}
682
683void
684NrUeMac::RecvRaResponse(NrBuildRarListElement_s raResponse)
685{
686 NS_LOG_FUNCTION(this);
687 m_waitingForRaResponse = false;
688 m_noRaResponseReceivedEvent.Cancel();
689 NS_LOG_INFO(" IMSI " << m_imsi << " RNTI " << m_rnti << " received RAR for RA preamble ID "
690 << +m_raPreambleId
691 << ", setting T-C-RNTI = " << raResponse.ulMsg3Dci->m_rnti
692 << " at: " << Simulator::Now().As(Time::MS));
693 m_rnti = raResponse.ulMsg3Dci->m_rnti;
694 m_cmacSapUser->SetTemporaryCellRnti(m_rnti);
695 // in principle we should wait for contention resolution,
696 // but in the current NR model when two or more identical
697 // preambles are sent no one is received, so there is no need
698 // for contention resolution
699 m_cmacSapUser->NotifyRandomAccessSuccessful();
700 // Trigger Tx opportunity for Message 3 over LC 0
701 // this is needed since Message 3's UL GRANT is in the RAR, not in UL-DCIs
702 const uint8_t lc0Lcid = 0;
703 auto lc0InfoIt = m_lcInfoMap.find(lc0Lcid);
704 NS_ASSERT_MSG(lc0InfoIt != m_lcInfoMap.end(),
705 "LC0 not mapped to this UE MAC with bwpId:" << GetBwpId());
706 auto lc0BsrIt = m_ulBsrReceived.find(lc0Lcid);
707 if ((lc0BsrIt != m_ulBsrReceived.end()) && (lc0BsrIt->second.txQueueSize > 0))
708 {
709 NS_LOG_INFO(
710 "Notify RLC about transmission opportunity for sending RRC CONNECTION REQUEST.");
711 NS_ASSERT_MSG(raResponse.ulMsg3Dci->m_tbSize > lc0BsrIt->second.txQueueSize,
712 "segmentation of Message 3 is not allowed");
713 NrMacSapUser::TxOpportunityParameters txOpParams;
714 txOpParams.lcid = lc0Lcid;
715 txOpParams.rnti = m_rnti;
716 txOpParams.bytes = raResponse.ulMsg3Dci->m_tbSize;
717 txOpParams.layer = 0;
718 txOpParams.harqId = 0;
719 txOpParams.componentCarrierId = GetBwpId();
720
721 lc0InfoIt->second.macSapUser->NotifyTxOpportunity(txOpParams);
722 lc0BsrIt->second.txQueueSize = 0;
723 lc0BsrIt->second.retxQueueSize = 0;
724 lc0BsrIt->second.statusPduSize = 0;
725 m_ulBsrReceived.erase(lc0BsrIt);
726 }
727}
728
729void
730NrUeMac::ProcessUlDci(const Ptr<NrUlDciMessage>& dciMsg)
731{
732 NS_LOG_FUNCTION(this);
733
734 SfnSf dataSfn = m_currentSlot;
735 dataSfn.Add(dciMsg->GetKDelay());
736
737 // Saving the data we need in DoTransmitPdu
738 m_ulDciSfnsf = dataSfn;
739 m_ulDciTotalUsed = 0;
740 m_ulDci = dciMsg->GetDciInfoElement();
741
742 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), m_rnti, GetBwpId(), dciMsg);
743
744 NS_LOG_INFO("UL DCI received, transmit data in slot "
745 << dataSfn << " Harq Process " << +m_ulDci->m_harqProcess << " TBS "
746 << m_ulDci->m_tbSize << " total queue " << GetTotalBufSize());
747
748 if (m_ulDci->m_ndi == 0)
749 {
750 // This method will retransmit the data saved in the harq buffer
751 TransmitRetx();
752 m_macUeStateMachine(m_currentSlot,
753 GetCellId(),
754 m_rnti,
755 GetBwpId(),
756 m_srState,
757 m_ulBsrReceived,
758 m_ulDci->m_ndi,
759 "ProcessUlDci");
760
761 // This method will transmit a new BSR.
762 SendBufferStatusReport(dataSfn, m_ulDci->m_symStart);
763 }
764 else if (m_ulDci->m_ndi == 1)
765 {
766 SendNewData();
767 m_macUeStateMachine(m_currentSlot,
768 GetCellId(),
769 m_rnti,
770 GetBwpId(),
771 m_srState,
772 m_ulBsrReceived,
773 m_ulDci->m_ndi,
774 "ProcessUlDci");
775
776 NS_LOG_INFO("After sending NewData, bufSize " << GetTotalBufSize());
777
778 // Send a new BSR. SendNewData() already took into account the size of
779 // the BSR.
780 SendBufferStatusReport(dataSfn, m_ulDci->m_symStart);
781
782 NS_LOG_INFO("UL DCI processing done, sent to PHY a total of "
783 << m_ulDciTotalUsed << " B out of " << m_ulDci->m_tbSize
784 << " allocated bytes ");
785
786 if (GetTotalBufSize() == 0)
787 {
788 m_srState = INACTIVE;
789 NS_LOG_INFO("m_srState = ACTIVE -> INACTIVE, bufSize " << GetTotalBufSize());
790
791 // the UE may have been scheduled, but we didn't use a single byte
792 // of the allocation. So send an empty PDU. This happens because the
793 // byte reporting in the BSR is not accurate, due to RLC and/or
794 // BSR quantization.
795 if (m_ulDciTotalUsed == 0)
796 {
797 NS_LOG_WARN("No byte used for this UL-DCI, sending empty PDU");
798
799 NrMacSapProvider::TransmitPduParameters txParams;
800
801 txParams.pdu = Create<Packet>();
802 txParams.lcid = 3;
803 txParams.rnti = m_rnti;
804 txParams.layer = 0;
805 txParams.harqProcessId = m_ulDci->m_harqProcess;
806 txParams.componentCarrierId = GetBwpId();
807
808 DoTransmitPdu(txParams);
809 }
810 }
811 }
812}
813
814void
815NrUeMac::TransmitRetx()
816{
817 NS_LOG_FUNCTION(this);
818
819 Ptr<PacketBurst> pb = m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst;
820
821 if (pb == nullptr)
822 {
823 NS_LOG_WARN(
824 "The previous transmission did not contain any new data; "
825 "probably it was BSR only. To not send an old BSR to the scheduler, "
826 "we don't send anything back in this allocation. Eventually, "
827 "the Harq timer at gnb will expire, and soon this allocation will be forgotten.");
828 return;
829 }
830
831 NS_LOG_DEBUG("UE MAC RETX HARQ " << +m_ulDci->m_harqProcess);
832
833 NS_ASSERT(pb->GetNPackets() > 0);
834
835 for (std::list<Ptr<Packet>>::const_iterator j = pb->Begin(); j != pb->End(); ++j)
836 {
837 Ptr<Packet> pkt = (*j)->Copy();
838 NrRadioBearerTag bearerTag;
839 if (!pkt->PeekPacketTag(bearerTag))
840 {
841 NS_FATAL_ERROR("No radio bearer tag");
842 }
843 m_phySapProvider->SendMacPdu(pkt, m_ulDciSfnsf, m_ulDci->m_symStart, m_ulDci->m_rnti);
844 }
845
846 m_miUlHarqProcessesPacketTimer.at(m_ulDci->m_harqProcess) = GetNumHarqProcess();
847}
848
849void
850NrUeMac::SendRetxData(uint32_t usefulTbs, uint32_t activeLcsRetx)
851{
852 NS_LOG_FUNCTION(this);
853
854 if (activeLcsRetx == 0)
855 {
856 return;
857 }
858
859 uint32_t bytesPerLcId = usefulTbs / activeLcsRetx;
860
861 for (auto& itBsr : m_ulBsrReceived)
862 {
863 auto& bsr = itBsr.second;
864
865 if (m_ulDciTotalUsed + bytesPerLcId <= usefulTbs)
866 {
867 NrMacSapUser::TxOpportunityParameters txParams;
868 txParams.lcid = bsr.lcid;
869 txParams.rnti = m_rnti;
870 txParams.bytes = bytesPerLcId;
871 txParams.layer = 0;
872 txParams.harqId = m_ulDci->m_harqProcess;
873 txParams.componentCarrierId = GetBwpId();
874
875 NS_LOG_INFO("Notifying RLC of LCID " << +bsr.lcid
876 << " of a TxOpp "
877 "of "
878 << bytesPerLcId << " B for a RETX PDU");
879
880 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
881 // After this call, m_ulDciTotalUsed has been updated with the
882 // correct amount of bytes... but it is up to us in updating the BSR
883 // value, subtracting the amount of bytes transmitted
884
885 // We need to use std::min here because bytesPerLcId can be
886 // greater than bsr.txQueueSize because scheduler can assign
887 // more bytes than needed due to how TB size is computed.
888 bsr.retxQueueSize -= std::min(bytesPerLcId, bsr.retxQueueSize);
889 }
890 else
891 {
892 NS_LOG_DEBUG("Something wrong with the calculation of overhead."
893 "Active LCS Retx: "
894 << activeLcsRetx << " assigned to this: " << bytesPerLcId
895 << ", with TBS of " << m_ulDci->m_tbSize << " usefulTbs " << usefulTbs
896 << " and total used " << m_ulDciTotalUsed);
897 }
898 }
899}
900
901void
902NrUeMac::SendTxData(uint32_t usefulTbs, uint32_t activeTx)
903{
904 NS_LOG_FUNCTION(this);
905
906 if (activeTx == 0)
907 {
908 return;
909 }
910
911 uint32_t bytesPerLcId = usefulTbs / activeTx;
912
913 for (auto& itBsr : m_ulBsrReceived)
914 {
915 auto& bsr = itBsr.second;
916
917 if (m_ulDciTotalUsed + bytesPerLcId <= usefulTbs)
918 {
919 NrMacSapUser::TxOpportunityParameters txParams;
920 txParams.lcid = bsr.lcid;
921 txParams.rnti = m_rnti;
922 txParams.bytes = bytesPerLcId;
923 txParams.layer = 0;
924 txParams.harqId = m_ulDci->m_harqProcess;
925 txParams.componentCarrierId = GetBwpId();
926
927 NS_LOG_INFO("Notifying RLC of LCID " << +bsr.lcid
928 << " of a TxOpp "
929 "of "
930 << bytesPerLcId << " B for a TX PDU");
931
932 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
933 // After this call, m_ulDciTotalUsed has been updated with the
934 // correct amount of bytes... but it is up to us in updating the BSR
935 // value, subtracting the amount of bytes transmitted
936
937 // We need to use std::min here because bytesPerLcId can be
938 // greater than bsr.txQueueSize because scheduler can assign
939 // more bytes than needed due to how TB size is computed.
940 bsr.txQueueSize -= std::min(bytesPerLcId, bsr.txQueueSize);
941 }
942 else
943 {
944 NS_LOG_DEBUG("Something wrong with the calculation of overhead."
945 "Active LCS TX: "
946 << activeTx << " assigned to this: " << bytesPerLcId << ", with TBS of "
947 << m_ulDci->m_tbSize << " usefulTbs " << usefulTbs << " and total used "
948 << m_ulDciTotalUsed);
949 }
950 }
951}
952
953void
954NrUeMac::SendNewData()
955{
956 NS_LOG_FUNCTION(this);
957 // New transmission -> empty pkt buffer queue (for deleting eventual pkts not acked )
958 Ptr<PacketBurst> pb = CreateObject<PacketBurst>();
959 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst = pb;
960 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_lcidList.clear();
961 NS_LOG_INFO("Reset HARQP " << +m_ulDci->m_harqProcess);
962
963 // Sending the status data has no boundary: let's try to send the ACK as
964 // soon as possible, filling the TBS, if necessary.
965 SendNewStatusData();
966
967 // Let's count how many LC we have, that are waiting with some data
968 uint16_t activeLcsRetx = 0;
969 uint16_t activeLcsTx = 0;
970 for (const auto& itBsr : m_ulBsrReceived)
971 {
972 if (itBsr.second.retxQueueSize > 0)
973 {
974 activeLcsRetx++;
975 }
976 if (itBsr.second.txQueueSize > 0)
977 {
978 activeLcsTx++;
979 }
980 }
981
982 // Of the TBS we received in the DCI, one part is gone for the status pdu,
983 // where we didn't check much as it is the most important data, that has to go
984 // out. For the rest that we have left, we can use only a part of it because of
985 // the overhead of the SHORT_BSR, which is 5 bytes.
986 NS_ASSERT_MSG(m_ulDciTotalUsed + 5 <= m_ulDci->m_tbSize,
987 "The StatusPDU used " << m_ulDciTotalUsed
988 << " B, we don't have any for the SHORT_BSR.");
989 // reserve some data for the SHORT_BSR
990 uint32_t usefulTbs = m_ulDci->m_tbSize - m_ulDciTotalUsed - 5;
991
992 // Now, we have 3 bytes of overhead for each subPDU. Let's try to serve all
993 // the queues with some RETX data.
994 if (activeLcsRetx == 0 && activeLcsTx == 0 && usefulTbs > 0)
995 {
996 NS_LOG_LOGIC("This UE tx opportunity will be wasted: " << usefulTbs << " bytes.");
997 }
998
999 // this check is needed, because if there are no active LCS we should not
1000 // enter into else and call the function SendRetxData
1001 if (activeLcsRetx > 0 && usefulTbs > 0) // the queues with some RETX data.
1002 {
1003 // 10 because 3 bytes will go for MAC subheader
1004 // and we should ensure to pass to RLC AM at least 7 bytes
1005 if (activeLcsRetx * 10 > usefulTbs)
1006 {
1007 NS_LOG_DEBUG("The overhead for transmitting retx data is greater than the space for "
1008 "transmitting it."
1009 "Ignore the TBS of "
1010 << usefulTbs << " B.");
1011 }
1012 else
1013 {
1014 usefulTbs -= activeLcsRetx * 3;
1015 SendRetxData(usefulTbs, activeLcsRetx);
1016 }
1017 }
1018
1019 // Now we have to update our useful TBS for the next transmission.
1020 // Remember that m_ulDciTotalUsed keep count of data and overhead that we
1021 // used till now.
1022 NS_ASSERT_MSG(
1023 m_ulDciTotalUsed + 5 <= m_ulDci->m_tbSize,
1024 "The StatusPDU and RETX sending required all space, we don't have any for the SHORT_BSR.");
1025 usefulTbs = m_ulDci->m_tbSize - m_ulDciTotalUsed - 5; // Update the usefulTbs.
1026
1027 // The last part is for the queues with some non-RETX data. If there is no space left,
1028 // then nothing.
1029 if (activeLcsTx > 0 && usefulTbs > 0) // the queues with some TX data.
1030 {
1031 // 10 because 3 bytes will go for MAC subheader
1032 // and we should ensure to pass to RLC AM at least 7 bytes
1033 if (activeLcsTx * 10 > usefulTbs)
1034 {
1035 NS_LOG_DEBUG("The overhead for transmitting new data is greater than the space for "
1036 "transmitting it."
1037 "Ignore the TBS of "
1038 << usefulTbs << " B.");
1039 }
1040 else
1041 {
1042 usefulTbs -= activeLcsTx * 3;
1043 SendTxData(usefulTbs, activeLcsTx);
1044 }
1045 }
1046
1047 // If we did not used the packet burst, explicitly signal it to the HARQ
1048 // retx, if any.
1049 if (m_ulDciTotalUsed == 0)
1050 {
1051 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_pktBurst = nullptr;
1052 m_miUlHarqProcessesPacket.at(m_ulDci->m_harqProcess).m_lcidList.clear();
1053 }
1054}
1055
1056void
1057NrUeMac::SendNewStatusData()
1058{
1059 NS_LOG_FUNCTION(this);
1060
1061 bool hasStatusPdu = false;
1062 bool sentOneStatusPdu = false;
1063
1064 for (auto& bsrIt : m_ulBsrReceived)
1065 {
1066 auto& bsr = bsrIt.second;
1067
1068 if (bsr.statusPduSize > 0)
1069 {
1070 hasStatusPdu = true;
1071
1072 // Check if we have room to transmit the statusPdu
1073 if (m_ulDciTotalUsed + bsr.statusPduSize <= m_ulDci->m_tbSize)
1074 {
1075 NrMacSapUser::TxOpportunityParameters txParams;
1076 txParams.lcid = bsr.lcid;
1077 txParams.rnti = m_rnti;
1078 txParams.bytes = bsr.statusPduSize;
1079 txParams.layer = 0;
1080 txParams.harqId = m_ulDci->m_harqProcess;
1081 txParams.componentCarrierId = GetBwpId();
1082
1083 NS_LOG_INFO("Notifying RLC of LCID " << +bsr.lcid
1084 << " of a TxOpp "
1085 "of "
1086 << bsr.statusPduSize << " B for a status PDU");
1087
1088 m_lcInfoMap.at(bsr.lcid).macSapUser->NotifyTxOpportunity(txParams);
1089 // After this call, m_ulDciTotalUsed has been updated with the
1090 // correct amount of bytes... but it is up to us in updating the BSR
1091 // value, subtracting the amount of bytes transmitted
1092 bsr.statusPduSize = 0;
1093 sentOneStatusPdu = true;
1094 }
1095 else
1096 {
1097 NS_LOG_INFO("Cannot send StatusPdu of " << bsr.statusPduSize
1098 << " B, we already used all the TBS");
1099 }
1100 }
1101 }
1102
1103 NS_ABORT_MSG_IF(hasStatusPdu && !sentOneStatusPdu,
1104 "The TBS of size " << m_ulDci->m_tbSize
1105 << " doesn't allow us "
1106 "to send one status PDU...");
1107}
1108
1109void
1110NrUeMac::DoReceiveControlMessage(Ptr<NrControlMessage> msg)
1111{
1112 NS_LOG_FUNCTION(this << msg);
1113
1114 switch (msg->GetMessageType())
1115 {
1116 case (NrControlMessage::UL_DCI): {
1117 ProcessUlDci(DynamicCast<NrUlDciMessage>(msg));
1118 break;
1119 }
1120 case (NrControlMessage::RAR): {
1121 NS_LOG_INFO("Received RAR in slot " << m_currentSlot);
1122
1123 m_macRxedCtrlMsgsTrace(m_currentSlot, GetCellId(), m_rnti, GetBwpId(), msg);
1124
1125 if (m_waitingForRaResponse)
1126 {
1127 Ptr<NrRarMessage> rarMsg = DynamicCast<NrRarMessage>(msg);
1128 NS_LOG_LOGIC("got RAR with RA-RNTI " << +rarMsg->GetRaRnti() << ", expecting "
1129 << +m_raRnti);
1130 for (auto it = rarMsg->RarListBegin(); it != rarMsg->RarListEnd(); ++it)
1131 {
1132 if (it->rarPayload.raPreambleId == m_raPreambleId)
1133 {
1134 RecvRaResponse(it->rarPayload);
1135 }
1136 }
1137 }
1138 break;
1139 }
1140
1141 default:
1142 NS_LOG_LOGIC("Control message not supported/expected");
1143 }
1144}
1145
1146NrUePhySapUser*
1148{
1149 return m_phySapUser;
1150}
1151
1152void
1154{
1155 m_phySapProvider = ptr;
1156}
1157
1158void
1159NrUeMac::RaResponseTimeout(bool contention)
1160{
1161 NS_LOG_FUNCTION(this << contention);
1162 m_waitingForRaResponse = false;
1163 // 3GPP 36.321 5.1.4
1164 ++m_preambleTransmissionCounter;
1165 // fire RA response timeout trace
1166 m_raResponseTimeoutTrace(m_imsi,
1167 contention,
1168 m_preambleTransmissionCounter,
1169 m_rachConfig.preambleTransMax + 1);
1170 if (m_preambleTransmissionCounter == m_rachConfig.preambleTransMax + 1)
1171 {
1172 NS_LOG_INFO("RAR timeout, preambleTransMax reached => giving up");
1173 m_cmacSapUser->NotifyRandomAccessFailed();
1174 }
1175 else
1176 {
1177 NS_LOG_INFO("RAR timeout while waiting for raPreambleId " << +m_raPreambleId
1178 << " re-send preamble");
1179 if (contention)
1180 {
1181 RandomlySelectAndSendRaPreamble();
1182 }
1183 else
1184 {
1185 SendRaPreamble(contention);
1186 }
1187 }
1188}
1189
1190void
1191NrUeMac::DoConfigureRach(NrUeCmacSapProvider::RachConfig rc)
1192{
1193 NS_LOG_FUNCTION(this);
1194 m_rachConfig = rc;
1195 m_rachConfigured = true;
1196}
1197
1198void
1199NrUeMac::DoStartContentionBasedRandomAccessProcedure()
1200{
1201 NS_LOG_FUNCTION(this);
1202 RandomlySelectAndSendRaPreamble();
1203}
1204
1205void
1206NrUeMac::RandomlySelectAndSendRaPreamble()
1207{
1208 NS_LOG_FUNCTION(this);
1209 // 3GPP 36.321 5.1.1
1210 NS_ASSERT_MSG(m_rachConfigured, "RACH not configured");
1211 // assume that there is no Random Access Preambles group B
1212 m_raPreambleId =
1213 m_raPreambleUniformVariable->GetInteger(0, m_rachConfig.numberOfRaPreambles - 1);
1214 NS_LOG_DEBUG(m_currentSlot << " Received System Information, send to PHY the "
1215 "RA preamble: "
1216 << m_raPreambleId);
1217 SendRaPreamble(true);
1218}
1219
1220void
1221NrUeMac::SendRaPreamble(bool contention)
1222{
1223 NS_LOG_FUNCTION(this << (uint32_t)m_raPreambleId << contention);
1224
1225 if (contention)
1226 {
1227 // m_raPreambleId = m_raPreambleUniformVariable->GetInteger (0, 64 - 1);
1228 m_raPreambleId = g_raPreambleId++;
1229 bool preambleOverflow = m_raPreambleId == 255;
1230 m_raPreambleId += preambleOverflow;
1231 g_raPreambleId += preambleOverflow;
1232 }
1233 /*raRnti should be subframeNo -1 */
1234 m_raRnti = 1;
1235
1236 // 3GPP 36.321 5.1.4
1237 m_phySapProvider->SendRachPreamble(m_raPreambleId, m_raRnti);
1238 NS_LOG_INFO(" Sent preamble id " << +m_raPreambleId
1239 << " at: " << Simulator::Now().As(Time::MS));
1240 Time raWindowBegin = m_phySapProvider->GetSlotPeriod();
1241 Time raWindowEnd = m_phySapProvider->GetSlotPeriod() * (6 + m_rachConfig.raResponseWindowSize);
1242 Simulator::Schedule(raWindowBegin, &NrUeMac::StartWaitingForRaResponse, this);
1243 m_noRaResponseReceivedEvent =
1244 Simulator::Schedule(raWindowEnd, &NrUeMac::RaResponseTimeout, this, contention);
1245
1246 // Tracing purposes
1247 Ptr<NrRachPreambleMessage> rachMsg = Create<NrRachPreambleMessage>();
1248 rachMsg->SetSourceBwp(GetBwpId());
1249 m_macTxedCtrlMsgsTrace(m_currentSlot, GetCellId(), m_rnti, GetBwpId(), rachMsg);
1250}
1251
1252void
1253NrUeMac::StartWaitingForRaResponse()
1254{
1255 NS_LOG_FUNCTION(this);
1256 m_waitingForRaResponse = true;
1257}
1258
1259void
1260NrUeMac::DoStartNonContentionBasedRandomAccessProcedure(uint16_t rnti,
1261 [[maybe_unused]] uint8_t preambleId,
1262 uint8_t prachMask)
1263{
1264 NS_LOG_FUNCTION(this << rnti << (uint16_t)preambleId << (uint16_t)prachMask);
1265 NS_ASSERT_MSG(prachMask == 0,
1266 "requested PRACH MASK = " << (uint32_t)prachMask
1267 << ", but only PRACH MASK = 0 is supported");
1268 m_rnti = rnti;
1269 m_raPreambleId = preambleId;
1270 m_preambleTransmissionCounter = 0;
1271 bool contention = false;
1272 SendRaPreamble(contention);
1273}
1274
1275void
1276NrUeMac::AddLc(uint8_t lcId, NrUeCmacSapProvider::LogicalChannelConfig lcConfig, NrMacSapUser* msu)
1277{
1278 NS_LOG_FUNCTION(this << " lcId" << (uint32_t)lcId);
1279 NS_ASSERT_MSG(m_lcInfoMap.find(lcId) == m_lcInfoMap.end(),
1280 "cannot add channel because LCID " << (uint16_t)lcId << " is already present");
1281
1282 LcInfo lcInfo;
1283 lcInfo.lcConfig = lcConfig;
1284 lcInfo.macSapUser = msu;
1285 m_lcInfoMap[lcId] = lcInfo;
1286}
1287
1288void
1289NrUeMac::DoRemoveLc(uint8_t lcId)
1290{
1291 NS_LOG_FUNCTION(this << " lcId" << lcId);
1292 NS_ASSERT_MSG(m_lcInfoMap.find(lcId) != m_lcInfoMap.end(),
1293 "could not find LCID " << (uint16_t)lcId);
1294 m_lcInfoMap.erase(lcId);
1295 m_ulBsrReceived.erase(lcId); // empty BSR buffer for this lcId
1296 // for (auto& harqProcess: m_miUlHarqProcessesPacket)
1297 //{
1298 // uint32_t packets = harqProcess.m_pktBurst->GetNPackets();
1299 // auto itPackets = harqProcess.m_pktBurst->GetPackets();
1300 // for (uint32_t p = 0; p < packets; p++)
1301 // {
1302 // uint32_t i = packets-p-1;
1303 // if (harqProcess.m_lcidList.at(i) == lcId)
1304 // {
1305 // // how to erase from packetburst?
1306 // //auto it = itPackets.begin();
1307 // //std::advance(it, i);
1308 // //harqProcess.m_pktBurst->GetPackets().erase(it);
1309 // auto it2 = harqProcess.m_lcidList.begin();
1310 // std::advance(it2, i);
1311 // harqProcess.m_lcidList.erase(it2);
1312 // }
1313 // }
1314 // }
1315}
1316
1317NrMacSapProvider*
1319{
1320 return m_macSapProvider;
1321}
1322
1323void
1324NrUeMac::DoReset()
1325{
1326 NS_LOG_FUNCTION(this);
1327 auto it = m_lcInfoMap.begin();
1328 while (it != m_lcInfoMap.end())
1329 {
1330 // don't delete CCCH)
1331 if (it->first == 0)
1332 {
1333 ++it;
1334 }
1335 else
1336 {
1337 // note: use of postfix operator preserves validity of iterator
1338 m_lcInfoMap.erase(it++);
1339 }
1340 }
1341 // note: rnti will be assigned by the gNB using RA response message
1342 m_rnti = 0;
1343 m_noRaResponseReceivedEvent.Cancel();
1344 m_rachConfigured = false;
1345 m_ulBsrReceived.clear();
1346}
1347
1349
1350int64_t
1352{
1353 return DoAssignStreams(stream);
1354}
1355
1356int64_t
1358{
1359 NS_LOG_FUNCTION(this << stream);
1360 m_raPreambleUniformVariable->SetStream(stream);
1361 return 1;
1362}
1363
1364} // namespace ns3
@ UL_DCI
The resources allocation map from the BS to the attached UEs (UL)
@ RAR
Random Access Response.
static const uint8_t SHORT_BSR
Short BSR.
static uint8_t FromBytesToLevel(uint64_t bufferSize)
Convert a bytes value into the 3GPP-standard level to write in the BSR.
SAP interface between the MAC and the PHY.
Definition nr-phy-sap.h:36
virtual Time GetSlotPeriod() const =0
Retrieve the slot period.
virtual void SendMacPdu(const Ptr< Packet > &p, const SfnSf &sfn, uint8_t symStart, uint16_t rnti)=0
Send a Mac PDU.
virtual uint16_t GetCellId() const =0
Retrieve the cell id.
virtual void SendControlMessage(Ptr< NrControlMessage > msg)=0
Send a control message.
virtual void NotifyConnectionSuccessful()=0
Notify PHY about the successful RRC connection establishment.
virtual uint16_t GetBwpId() const =0
Retrieve the bandwidth part id.
virtual void SendRachPreamble(uint8_t PreambleId, uint8_t Rnti)=0
Send the RACH preamble.
virtual void NotifyRandomAccessSuccessful()=0
virtual void SetTemporaryCellRnti(uint16_t rnti)=0
virtual void NotifyRandomAccessFailed()=0
void SetCurrentSlot(const SfnSf &sfn)
Set the frame/subframe/slot counter.
Definition nr-ue-mac.cc:323
NrUePhySapUser * GetPhySapUser()
Get the PHY SAP User (AKA the MAC representation for the PHY)
uint64_t GetImsi() const
Get the IMSI.
Definition nr-ue-mac.cc:317
void DoDispose() override
DoDispose method inherited from Object.
Definition nr-ue-mac.cc:251
void SetPhySapProvider(NrPhySapProvider *ptr)
Set PHY SAP provider (AKA the PHY representation for the MAC)
uint8_t GetNumHarqProcess() const
Please remember that this number is obtained by the GNB, the UE cannot configure it.
Definition nr-ue-mac.cc:364
NrMacSapProvider * GetUeMacSapProvider()
Get the Mac SAP provider (AKA the MAC representation for the RLC)
virtual int64_t DoAssignStreams(int64_t stream)
void SetNumHarqProcess(uint8_t numHarqProcesses)
Sets the number of HARQ processes. Called by the helper at the moment of UE attachment.
Definition nr-ue-mac.cc:344
NrUeCmacSapProvider * GetUeCmacSapProvider()
Get the C MAC SAP provider (AKA the MAC representation for the RRC)
Definition nr-ue-mac.cc:569
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model....
uint16_t GetCellId() const
Get the cell id of this MAC.
Definition nr-ue-mac.cc:298
uint16_t GetBwpId() const
Get the bwp id of this MAC.
Definition nr-ue-mac.cc:285
uint16_t GetRnti() const
Get the RNTI.
Definition nr-ue-mac.cc:311
void SetUeCmacSapUser(NrUeCmacSapUser *s)
Set the C MAC SAP user (AKA the RRC representation for the MAC)
Definition nr-ue-mac.cc:563
~NrUeMac() override
Deconstructor.
Definition nr-ue-mac.cc:246
@ INACTIVE
no SR nor BSR.. initial state
Definition nr-ue-mac.h:145
@ TO_SEND
We have to send the BSR when possible.
Definition nr-ue-mac.h:146
@ ACTIVE
SR or BSR sent; now the source of information is the vector m_bsrReservedSpace.
Definition nr-ue-mac.h:147
The SfnSf class.
Definition sfnsf.h:32
void Add(uint32_t slotN)
Add to this SfnSf a number of slot indicated by the first parameter.
Definition sfnsf.cc:117
uint8_t preambleTransMax
preamble transmit maximum
uint8_t raResponseWindowSize
RA response window size.
uint8_t numberOfRaPreambles
number of RA preambles