LteMacBase.h Source File

Simu5G: LteMacBase.h Source File
Simu5G
LteMacBase.h
1//
2// Simu5G
3//
4// Copyright (C) 2012-2021 Giovanni Nardini, Giovanni Stea, Antonio Virdis et al. (University of Pisa)
5// Copyright (C) 2022-2026 Giovanni Nardini, Giovanni Stea et al. (University of Pisa)
6//
7// This file is part of a software released under the license included in file
8// "license.pdf". Please read LICENSE and README files before using it.
9// The above files and the present reference are part of the software itself,
10// and cannot be removed from it.
11//
12
13#ifndef _LTE_LTEMACBASE_H_
14#define _LTE_LTEMACBASE_H_
15
16#include <inet/common/ModuleRefByPar.h>
17
18#include "simu5g/common/binder/Binder.h"
19#include "simu5g/common/LteCommon.h"
20#include "simu5g/common/LteControlInfo.h"
21
22namespace simu5g {
23
24using namespace omnetpp;
25
26class LteHarqBufferTx;
27class LteHarqBufferRx;
28class Binder;
29class FlowControlInfo;
30class LteMacBuffer;
31
36typedef std::map<MacNodeId, LteHarqBufferTx *> HarqTxBuffers;
37
42typedef std::map<MacNodeId, LteHarqBufferRx *> HarqRxBuffers;
43
44/*
45 * MultiMap associating a LCG group with all connections belonging to it and
46 * corresponding virtual buffer pointer
47 */
48typedef std::pair<MacCid, LteMacBuffer *> CidBufferPair;
49typedef std::pair<Lcg, CidBufferPair> LcgPair;
50typedef std::multimap<Lcg, CidBufferPair> LcgMap;
51
52// The RLC/logical-channel configuration of one logical channel, as the configuring
53// entity (RRC) pushes it at bearer establishment via configureLogicalChannel().
54// Mirrors the info MAC gets from RLC-BearerConfig / mac-LogicalChannelConfig in
55// TS 38.331. One record per channel (MacCid = remote node + LCID), shared by the
56// outgoing and incoming direction.
57struct LogicalChannelConfig {
58 RlcMode rlcMode = UM; // rlc-Config: TM, UM or AM
59 bool soFraming = false; // wire format: false = LTE FI/concatenation (TS 36.322), true = NR SI/SO (TS 38.322)
60 unsigned int snFieldLength = 12; // sn-FieldLength, in bits
61 Lcg lcg = Lcg(0); // logicalChannelGroup
62};
63
64inline std::ostream& operator<<(std::ostream& os, const LogicalChannelConfig& e) {
65 os << "rlcMode=" << e.rlcMode << " soFraming=" << e.soFraming
66 << " snFieldLength=" << e.snFieldLength << " lcg=" << e.lcg;
67 return os;
68}
69
79class LteMacBase : public cSimpleModule
80{
81 friend class LteHarqBufferTx;
82 friend class LteHarqBufferRx;
83 // LteHarqBufferRxD2D needs the protected sendLowerPackets() (like LteHarqBufferRx);
84 // LteHarqBufferTxD2D touches no protected LteMacBase member, so it is not a friend.
85 // This is one of the three places the core names a class from the D2D package (the
86 // other two are in LteSchedulerEnb.h, documented there). A name only: no include,
87 // no NED import, no type lookup, so the core still builds with Simu5G_D2D disabled.
88 // Dropping it would mean making sendLowerPackets() public, which would equally
89 // dissolve LteHarqBufferRx's grant -- a core decision, not a D2D one.
90 friend class LteHarqBufferRxD2D;
91
92 protected:
93
94 unsigned int totalOverflowedBytes_ = 0;
95 static simsignal_t macBufferOverflowDlSignal_;
96 static simsignal_t macBufferOverflowUlSignal_;
97 static simsignal_t receivedPacketFromUpperLayerSignal_;
98 static simsignal_t receivedPacketFromLowerLayerSignal_;
99 static simsignal_t sentPacketToUpperLayerSignal_;
100 static simsignal_t sentPacketToLowerLayerSignal_;
101
102 /*
103 * Data Structures
104 */
105 inet::ModuleRefByPar<Binder> binder_;
106
107 /*
108 * Gates
109 */
110 cGate *upInGate_ = nullptr;
111 cGate *upOutGate_ = nullptr;
112 cGate *downInGate_ = nullptr;
113 cGate *downOutGate_ = nullptr;
114
115 /*
116 * MAC MIB Params
117 */
119
121 cMessage *ttiTick_ = nullptr;
122
124 double ttiPeriod_ = TTI;
125
127 MacNodeId nodeId_ = NODEID_NONE;
128
129 opp_component_ptr<cModule> networkNode_;
130
133
135 unsigned int queueSize_;
136
137 public:
138 /*
139 * Outgoing connection information structure
140 * Consolidates connection descriptor, real buffer, and virtual buffer
141 */
142 struct OutgoingConnectionInfo {
143 FlowDescriptor flowInfo; // Connection flow information
144 LteMacQueue *queue = nullptr; // Real MAC buffer for actual packets
145 LteMacBuffer *buffer = nullptr; // Virtual buffer for scheduling decisions
146
147 OutgoingConnectionInfo() {}
148 OutgoingConnectionInfo(const FlowDescriptor& info, LteMacQueue *q, LteMacBuffer *buf) : flowInfo(info), queue(q), buffer(buf) {}
149 };
150
151 protected:
153 std::map<MacCid, OutgoingConnectionInfo> connDescOut_;
154
156 std::map<GHz, MacPduList> macPduList_;
157
159 std::map<GHz, HarqTxBuffers> harqTxBuffers_;
160
162 std::map<GHz, HarqRxBuffers> harqRxBuffers_;
163
164 /* Incoming Connection Descriptors:
165 * a connection is stored at the first MAC SDU delivered to the RLC
166 */
167 std::map<MacCid, FlowDescriptor> connDescIn_;
168
171 std::map<MacCid, LogicalChannelConfig> lcConfig_;
172
173 /* LCG to CID and buffers map - used for supporting LCG - based scheduler operations
174 * TODO: delete/update entries on handover
175 */
176 LcgMap lcgMap_;
177
178 // Node Type
179 RanNodeType nodeType_;
180
181 // LTE or NR
182 bool isNr_ = false;
183
184 // record the last TTI that HARQ processes for a given UE have been aborted (useful for D2D switching)
185 std::map<MacNodeId, simtime_t> resetHarq_;
186
187 // reference to the phy layer
188 opp_component_ptr<PhyBase> phy_;
189
190 // signals for PacketFlowObserver
191 static simsignal_t macPduAckedSignal_;
192 static simsignal_t macPduDiscardedSignal_;
193 static simsignal_t rlcPduDiscardedSignal_;
194 static simsignal_t grantSentSignal_;
195 static simsignal_t ulMacPduArrivedSignal_;
196
197 // support to different numerologies
198 struct NumerologyPeriodCounter {
199 unsigned int max;
200 unsigned int current;
201
202 friend std::ostream& operator<<(std::ostream& os, const NumerologyPeriodCounter& e) {
203 os << "max=" << e.max << " current=" << e.current;
204 return os;
205 }
206 };
207 std::map<NumerologyIndex, NumerologyPeriodCounter> numerologyPeriodCounter_;
208
209 // statistics in visualization
210 bool statDisplay_;
211 uint64_t nrFromUpper_ = 0;
212 uint64_t nrFromLower_ = 0;
213 uint64_t nrToUpper_ = 0;
214 uint64_t nrToLower_ = 0;
215
216 // support to print harqErrorRate at the end of the simulation
217 unsigned int totalHarqErrorRateDlSum_ = 0;
218 unsigned int totalHarqErrorRateUlSum_ = 0;
219 unsigned int totalHarqErrorRateDlCount_ = 0;
220 unsigned int totalHarqErrorRateUlCount_ = 0;
221
222 protected:
223
224 unsigned int getNumerologyPeriodCounter(NumerologyIndex index) { return numerologyPeriodCounter_[index].current; }
225 virtual void decreaseNumerologyPeriodCounter();
226
227 public:
228
232 ~LteMacBase() override;
233
240 virtual void deleteQueues(MacNodeId nodeId);
241
249 virtual void deleteQueuesRadioLinkFailure(MacNodeId nodeId);
250
251 //* public utility function - drops ownership of an object
252 void dropObj(cOwnedObject *obj)
253 {
254 drop(obj);
255 }
256
257 //* public utility function - takes ownership of an object
258 void takeObj(cOwnedObject *obj)
259 {
260 take(obj);
261 }
262
263 /*
264 * DRB ID <-> LCID mapping
265 *
266 * In the current implementation, DRB IDs (used in PDCP/RLC) map 1:1 to
267 * Logical Channel IDs (used in MAC). These methods make the mapping explicit.
268 */
269
274 LogicalCid drbIdToLcid(DrbId drbId) { return LogicalCid(num(drbId)); }
275
280 DrbId lcidToDrbId(LogicalCid lcid) { return DrbId(num(lcid)); }
281
286 virtual MacCid ctrlInfoToMacCid(const FlowControlInfo *info) {
287 return MacCid(ctrlInfoToUeId(info), drbIdToLcid(info->getDrbId()));
288 }
289
290 /*
291 * Getters
292 */
293
294 double getTtiPeriod()
295 {
296 return ttiPeriod_;
297 }
298
299 PhyBase *getPhy()
300 {
301 return phy_;
302 }
303
304 MacNodeId getMacNodeId()
305 {
306 ASSERT(nodeId_ != NODEID_NONE);
307 return nodeId_;
308 }
309
310 MacCellId getMacCellId()
311 {
312 return cellId_;
313 }
314
315 // Returns the virtual buffer for a specific CID
316 LteMacBuffer* getMacBuffer(MacCid cid)
317 {
318 auto it = connDescOut_.find(cid);
319 if (it == connDescOut_.end())
320 throw cRuntimeError("LteMacBase::getMacBuffer - Buffer for CID %s not found", cid.str().c_str());
321 return it->second.buffer;
322 }
323
324 // Returns list of active buffer CIDs
325 std::vector<MacCid> getActiveMacBufferCids()
326 {
327 return getActiveConnectionCids();
328 }
329
330 // Returns the LCG-to-cid mapping
331 const LcgMap& getLcgMap()
332 {
333 return lcgMap_;
334 }
335
336 // Returns flow control info for a specific CID
337 const FlowDescriptor& getConnDesc(MacCid cid)
338 {
339 auto it = connDescOut_.find(cid);
340 if (it == connDescOut_.end())
341 throw cRuntimeError("LteMacBase: Connection %s not found", cid.str().c_str());
342 return it->second.flowInfo;
343 }
344
345 // Returns list of active connection CIDs
346 std::vector<MacCid> getActiveConnectionCids()
347 {
348 std::vector<MacCid> activeCids;
349 activeCids.reserve(connDescOut_.size());
350 for (const auto& [cid,_] : connDescOut_)
351 activeCids.push_back(cid);
352 return activeCids;
353 }
354
355 // Returns the harq tx buffers
356 std::map<GHz, HarqTxBuffers> *getHarqTxBuffers()
357 {
358 return &harqTxBuffers_;
359 }
360
361 // Returns the harq rx buffers
362 std::map<GHz, HarqRxBuffers> *getHarqRxBuffers()
363 {
364 return &harqRxBuffers_;
365 }
366
367 // Returns the harq tx buffers for the given carrier
368 HarqTxBuffers *getHarqTxBuffers(GHz carrierFrequency)
369 {
370 if (harqTxBuffers_.find(carrierFrequency) == harqTxBuffers_.end())
371 return nullptr;
372 return &harqTxBuffers_[carrierFrequency];
373 }
374
375 // Returns the harq rx buffers for the given carrier
376 HarqRxBuffers *getHarqRxBuffers(GHz carrierFrequency)
377 {
378 if (harqRxBuffers_.find(carrierFrequency) == harqRxBuffers_.end())
379 return nullptr;
380 return &harqRxBuffers_[carrierFrequency];
381 }
382
383 // Returns the outgoing connection information map (for iteration)
384 const std::map<MacCid, OutgoingConnectionInfo>& getOutgoingConnectionInfoMap() const
385 {
386 return connDescOut_;
387 }
388
389 // Returns the incoming connection descriptor map (for iteration)
390 const std::map<MacCid, FlowDescriptor>& getIncomingConnectionInfoMap() const
391 {
392 return connDescIn_;
393 }
394
395 // Returns number of Harq Processes
396 unsigned int harqProcesses() const
397 {
398 return harqProcesses_;
399 }
400
401 RanNodeType getNodeType()
402 {
403 return nodeType_;
404 }
405
406 // check whether HARQ processes have been aborted during this TTI
407 bool isHarqReset(MacNodeId srcId)
408 {
409 if (resetHarq_.find(srcId) != resetHarq_.end()) {
410 if (resetHarq_[srcId] == NOW)
411 return true;
412 }
413 return false;
414 }
415
416 // record that HARQ processes for the given node have been aborted during this TTI (e.g., D2D mode switch)
417 void recordHarqReset(MacNodeId srcId)
418 {
419 resetHarq_[srcId] = NOW;
420 }
421
422 virtual void unregisterHarqBufferRx(MacNodeId nodeId);
423
430 virtual void sendUpperPackets(cPacket *pkt);
431
432 // visualization
433 void refreshDisplay() const override;
434
435 virtual void recordHarqErrorRate(unsigned int sample, Direction dir);
436 virtual double getHarqErrorRate(Direction dir);
437
438 /*
439 * @author Alessandro Noferi
440 *
441 * methods called by mac layer and the HarqBuffers to notify
442 * MAC pdus events to packetFlowObserver
443 */
444 virtual void harqAckToFlowObserver(const inet::Packet *macPdu);
445 virtual void discardMacPdu(const inet::Packet *macPdu);
446
447 protected:
448
449 int numInitStages() const override { return inet::NUM_INIT_STAGES; }
450
455 void initialize(int stage) override;
456
461 void handleMessage(cMessage *msg) override;
462
466
473 void deleteModule() override;
474
480 virtual void handleSelfMessage() = 0;
481
488 virtual void sendLowerPackets(cPacket *pkt);
489
490 /*
491 * Functions to be redefined by derived classes
492 */
493
494 virtual void macPduMake(MacCid cid = MacCid()) = 0;
495 virtual void macPduUnmake(cPacket *pkt) = 0;
496
497 public:
502 virtual void createOutgoingConnection(MacCid cid, const FlowDescriptor& connInfo);
503
512
519
524 virtual void createIncomingConnection(MacCid cid, const FlowDescriptor& connInfo);
525
531 virtual void configureLogicalChannel(MacCid cid, const LogicalChannelConfig& cfg);
532
538 const LogicalChannelConfig *findLogicalChannelConfig(MacCid cid) const
539 {
540 auto it = lcConfig_.find(cid);
541 return it != lcConfig_.end() ? &it->second : nullptr;
542 }
543
549 const LogicalChannelConfig& getLogicalChannelConfig(MacCid cid) const;
550
551 protected:
556 virtual bool bufferizePacket(cPacket *pkt);
557
562 virtual void handleUpperMessage(cPacket *pkt)
563 {
564 bufferizePacket(pkt);
565 }
566
570 virtual void macHandleFeedbackPkt(cPacket *pkt)
571 {
572 }
573
574 /*
575 * Receives and handles scheduling grants - implemented in LteMacUe
576 */
577 virtual void macHandleGrant(cPacket *pkt)
578 {
579 }
580
581 /*
582 * Receives and handles RAC requests (eNodeB implementation) and responses (LteMacUe implementation)
583 */
584 virtual void macHandleRac(cPacket *pkt)
585 {
586 }
587
588 /*
589 * Update UserTxParam stored in every lteMacPdu when an rtx changes this information
590 */
591 virtual void updateUserTxParam(cPacket *pkt) = 0;
592
594 virtual void fromRlc(cPacket *pkt);
595
597 virtual void fromPhy(cPacket *pkt);
598
601 virtual LteHarqBufferRx *createRxHarqBuffer(MacNodeId src, const UserControlInfo *userInfo);
602
604 virtual void recordBufferOverflow(Direction dir, double sample);
605};
606
607} //namespace
608
609#endif
Definition Binder.h:48
Definition LteHarqBufferRx.h:37
MAC Layer.
Definition LteMacBase.h:80
std::map< MacCid, LogicalChannelConfig > lcConfig_
Definition LteMacBase.h:171
virtual LteHarqBufferRx * createRxHarqBuffer(MacNodeId src, const UserControlInfo *userInfo)
virtual void createOutgoingConnection(MacCid cid, const FlowDescriptor &connInfo)
std::map< GHz, HarqTxBuffers > harqTxBuffers_
Harq Tx Buffers (one entry per carrier)
Definition LteMacBase.h:159
std::map< GHz, HarqRxBuffers > harqRxBuffers_
Harq Rx Buffers (one entry per carrier)
Definition LteMacBase.h:162
virtual void createIncomingConnection(MacCid cid, const FlowDescriptor &connInfo)
void handleMessage(cMessage *msg) override
~LteMacBase() override
virtual void deleteQueuesRadioLinkFailure(MacNodeId nodeId)
virtual void sendUpperPackets(cPacket *pkt)
void deleteModule() override
unsigned int queueSize_
Mac Buffers maximum queue size.
Definition LteMacBase.h:135
virtual void fromRlc(cPacket *pkt)
Upper Layer Handler.
virtual void clearOutgoingConnectionBuffers(MacCid cid)
MacNodeId nodeId_
MacNodeId.
Definition LteMacBase.h:127
cGate * downInGate_
MAC --> RLC.
Definition LteMacBase.h:112
std::map< GHz, MacPduList > macPduList_
List of pdus finalized for each user on each codeword (one entry per carrier)
Definition LteMacBase.h:156
int harqProcesses_
MAC --> PHY.
Definition LteMacBase.h:118
virtual bool bufferizePacket(cPacket *pkt)
void initialize(int stage) override
virtual void deleteQueues(MacNodeId nodeId)
const LogicalChannelConfig * findLogicalChannelConfig(MacCid cid) const
Definition LteMacBase.h:538
DrbId lcidToDrbId(LogicalCid lcid)
Definition LteMacBase.h:280
virtual void macHandleFeedbackPkt(cPacket *pkt)
Definition LteMacBase.h:570
virtual MacCid ctrlInfoToMacCid(const FlowControlInfo *info)
Definition LteMacBase.h:286
virtual void handleSelfMessage()=0
std::map< MacCid, OutgoingConnectionInfo > connDescOut_
Consolidated outgoing connection information (replaces mbuf_, macBuffers_, and connDesc_)
Definition LteMacBase.h:153
const LogicalChannelConfig & getLogicalChannelConfig(MacCid cid) const
double ttiPeriod_
TTI for this node.
Definition LteMacBase.h:124
cGate * upOutGate_
MAC <– RLC.
Definition LteMacBase.h:111
virtual void sendLowerPackets(cPacket *pkt)
MacCellId cellId_
MacCellId.
Definition LteMacBase.h:132
cGate * downOutGate_
MAC <– PHY.
Definition LteMacBase.h:113
cMessage * ttiTick_
TTI self message.
Definition LteMacBase.h:121
LogicalCid drbIdToLcid(DrbId drbId)
Definition LteMacBase.h:274
virtual void deleteOutgoingConnection(MacCid cid)
virtual void recordBufferOverflow(Direction dir, double sample)
Records the buffer-overflow statistic for a dropped packet of the given direction.
virtual void handleUpperMessage(cPacket *pkt)
Definition LteMacBase.h:562
virtual void fromPhy(cPacket *pkt)
Lower Layer Handler.
virtual void configureLogicalChannel(MacCid cid, const LogicalChannelConfig &cfg)
Buffers for MAC packets.
Definition LteMacBuffer.h:28
Queue for MAC SDU packets.
Definition LteMacQueue.h:41
Definition LteTypes.h:153
Definition AlertReceiver.h:24
MacNodeId MacCellId
Cell node ID. It is numerically equal to eNodeB MAC node ID.
Definition LteTypes.h:66
unsigned short NumerologyIndex
Numerology Index.
Definition LteCommon.h:205
std::map< MacNodeId, LteHarqBufferRx * > HarqRxBuffers
Definition LteMacBase.h:42
std::map< MacNodeId, LteHarqBufferTx * > HarqTxBuffers
Definition LteMacBase.h:36
constexpr MacNodeId NODEID_NONE
MAC node ID.
Definition LteTypes.h:54