D2dEnbMacBase.h Source File

Simu5G: D2dEnbMacBase.h Source File
Simu5G
D2dEnbMacBase.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 STACK_D2D_MAC_D2DENBMACBASE_H_
14#define STACK_D2D_MAC_D2DENBMACBASE_H_
15
16#include "simu5g/stack/mac/LteMacEnb.h"
17#include "simu5g/stack/mac/buffer/harq/LteHarqBufferRx.h"
18#include "simu5g/stack/d2d/mac/harq/LteHarqBufferMirrorD2D.h"
19#include "simu5g/stack/d2d/mac/harq/LteHarqBufferRxD2D.h"
20#include "simu5g/stack/d2d/binder/D2dBinder.h"
21#include "simu5g/stack/d2d/mac/amc/AmcPilotD2D.h"
22#include "simu5g/stack/d2d/mac/conflictgraph/ConflictGraph.h"
23#include "simu5g/stack/d2d/mac/ID2dAmc.h"
24#include "simu5g/stack/d2d/mac/ID2dMacEnb.h"
25#include "simu5g/stack/d2d/mac/D2dEnbMacHelper.h"
26#include "simu5g/stack/d2d/rrc/D2DModeSwitchNotification_m.h"
27#include "simu5g/stack/phy/packet/LteFeedbackPkt.h"
28#include "simu5g/stack/rrc/ConnectionControlEnb.h"
29
30namespace simu5g {
31
32using namespace omnetpp;
33
55template<class Base>
56class D2dEnbMacBase : public Base, public ID2dMacEnb
57{
58 protected:
59 // holds the D2D-specific eNB-MAC state and logic
60 D2dEnbMacHelper d2dEnbHelper_;
61
62 void macHandleFeedbackPkt(cPacket *pkt) override;
63
68 void flushHarqBuffers() override;
69
71 void fromPhy(cPacket *pkt) override;
72
74 LteHarqBufferRx *createRxHarqBuffer(MacNodeId src, const UserControlInfo *userInfo) override;
75
76 // the node's control-plane entry point, which knows the UEs handing over
77 inet::ModuleRefByPar<ConnectionControlEnb> connectionControl_;
78
79 // the network-wide D2D state, which the conflict graph is built from
80 inet::ModuleRefByPar<D2dBinder> d2dBinder_;
81
82 public:
83 D2dEnbMacBase() : d2dEnbHelper_(this)
84 {
85 }
86
90 void initialize(int stage) override;
91
93 void handleMessage(cMessage *msg) override;
94
95 // ---- ID2dMacEnb ----
96
97 bool isReuseD2DEnabled() override
98 {
99 return d2dEnbHelper_.getReuseD2D();
100 }
101
102 bool isReuseD2DMultiEnabled() override
103 {
104 return d2dEnbHelper_.getReuseD2DMulti();
105 }
106
107 ConflictGraph *getConflictGraph() override
108 {
109 return d2dEnbHelper_.getConflictGraph();
110 }
111
112 void deleteHarqBuffersMirrorD2D(MacNodeId txPeer, MacNodeId rxPeer) override;
113
120 void deleteQueues(MacNodeId nodeId) override;
121
122 // get the reference to the "mirror" buffers
123 HarqBuffersMirrorD2D *getHarqBuffersMirrorD2D(GHz carrierFrequency) override;
124
125 // delete the "mirror" Harq Buffer for this node (useful at handover)
126 virtual void deleteHarqBuffersMirrorD2D(MacNodeId nodeId);
127
128 // send the D2D Mode Switch signal to the transmitter of the given flow
129 void sendModeSwitchNotification(MacNodeId srcId, MacNodeId dst, LteD2DMode oldMode, LteD2DMode newMode) override;
130
131 bool isMsHarqInterrupt() override { return d2dEnbHelper_.getMsHarqInterrupt(); }
132};
133
134template<class Base>
136{
137 Base::initialize(stage);
138 if (stage == inet::INITSTAGE_LOCAL) {
139 connectionControl_.reference(this, "connectionControlModule", true);
140 d2dBinder_.reference(this, "d2dBinderModule", true);
141 d2dEnbHelper_.initWatches();
142 }
143 // (the AMC pilot/mode-switch parameter setup historically also ran at
144 // INITSTAGE_PHYSICAL_ENVIRONMENT -- an identical, idempotent copy of the
145 // INITSTAGE_SIMU5G_AMC_SETUP block below; the early copy is gone)
146 if (stage == inet::INITSTAGE_LAST) { // be sure that all UEs have been initialized
147 d2dEnbHelper_.setReuseD2D(this->par("reuseD2D"));
148 d2dEnbHelper_.setReuseD2DMulti(this->par("reuseD2DMulti"));
149
150 if (d2dEnbHelper_.getReuseD2D() || d2dEnbHelper_.getReuseD2DMulti()) {
151 d2dEnbHelper_.setConflictGraphUpdatePeriod(this->par("conflictGraphUpdatePeriod"));
152
153 d2dEnbHelper_.createDistanceBasedConflictGraph(this->binder_, d2dBinder_.get(), this->par("conflictGraphThreshold"),
154 this->par("conflictGraphD2DInterferenceRadius"), this->par("conflictGraphD2DMultiTxRadius"), this->par("conflictGraphD2DMultiInterferenceRadius"));
155
156 this->scheduleAt(NOW + 0.05, new cMessage("updateConflictGraph"));
157 }
158 }
159 else if (stage == INITSTAGE_SIMU5G_AMC_SETUP) {
160 bool usePreconfiguredTxParams = this->par("usePreconfiguredTxParams");
161 Cqi d2dCqi = this->par("d2dCqi");
162 if (usePreconfiguredTxParams)
163 check_and_cast<AmcPilotD2D *>(this->amc_->getPilot())->setPreconfiguredTxParams(d2dCqi);
164
165 d2dEnbHelper_.setMsHarqInterrupt(this->par("msHarqInterrupt").boolValue());
166 d2dEnbHelper_.setMsClearRlcBuffer(this->par("msClearRlcBuffer").boolValue());
167 }
168}
169
170template<class Base>
171void D2dEnbMacBase<Base>::macHandleFeedbackPkt(cPacket *pktAux)
172{
173 auto pkt = check_and_cast<inet::Packet *>(pktAux);
174 auto fb = pkt->peekAtFront<LteFeedbackPkt>();
175 auto lteInfo = pkt->getTag<UserControlInfo>();
176
177 std::map<MacNodeId, LteFeedbackDoubleVector> fbMapD2D = fb->getLteFeedbackDoubleVectorD2D();
178
179 // skip if no D2D CQI has been reported
180 if (!fbMapD2D.empty()) {
181 // the AMC of a D2D-capable eNB is always a D2D AMC
182 ID2dAmc *d2dAmc = check_and_cast<ID2dAmc *>(this->amc_);
183
184 MacNodeId id = fb->getSourceNodeId();
185
186 // extract feedback for D2D links
187 for (const auto& mapIt : fbMapD2D) {
188 MacNodeId peerId = mapIt.first;
189 for (const auto& it : mapIt.second) {
190 for (const auto& jt : it) {
191 if (!jt.isEmptyFeedback()) {
192 d2dAmc->pushFeedbackD2D(id, jt, peerId, lteInfo->getCarrierFrequency());
193 }
194 }
195 }
196 }
197 }
198 Base::macHandleFeedbackPkt(pkt);
199}
200
201template<class Base>
203{
204 if (msg->isSelfMessage() && msg->isName("D2DModeSwitchNotification")) {
205 cPacket *pkt = check_and_cast<cPacket *>(msg);
206 d2dEnbHelper_.macHandleD2DModeSwitch(pkt);
207 delete pkt;
208 }
209 else if (msg->isSelfMessage() && msg->isName("updateConflictGraph")) {
210 // compute conflict graph for resource allocation
211 d2dEnbHelper_.computeConflictGraph();
212
213 this->scheduleAt(NOW + d2dEnbHelper_.getConflictGraphUpdatePeriod(), msg);
214 }
215 else
216 Base::handleMessage(msg);
217}
218
219template<class Base>
220HarqBuffersMirrorD2D *D2dEnbMacBase<Base>::getHarqBuffersMirrorD2D(GHz carrierFrequency)
221{
222 return d2dEnbHelper_.getHarqBuffersMirrorD2D(carrierFrequency);
223}
224
225template<class Base>
227{
228 Base::deleteQueues(nodeId);
229 deleteHarqBuffersMirrorD2D(nodeId);
230}
231
232template<class Base>
233void D2dEnbMacBase<Base>::deleteHarqBuffersMirrorD2D(MacNodeId nodeId)
234{
235 d2dEnbHelper_.deleteHarqBuffersMirrorD2D(nodeId);
236}
237
238template<class Base>
239void D2dEnbMacBase<Base>::deleteHarqBuffersMirrorD2D(MacNodeId txPeer, MacNodeId rxPeer)
240{
241 d2dEnbHelper_.deleteHarqBuffersMirrorD2D(txPeer, rxPeer);
242}
243
244template<class Base>
245void D2dEnbMacBase<Base>::sendModeSwitchNotification(MacNodeId srcId, MacNodeId dstId, LteD2DMode oldMode, LteD2DMode newMode)
246{
247 Enter_Method_Silent("sendModeSwitchNotification");
248
249 EV << NOW << " D2dEnbMacBase::sendModeSwitchNotification - " << srcId << " --> " << dstId << " going from " << d2dModeToA(oldMode) << " to " << d2dModeToA(newMode) << endl;
250
251 // send switch notification to both the tx and rx side of the flow
252
253 auto pktTx = new inet::Packet("D2DModeSwitchNotification");
254
255 auto switchPktTx = inet::makeShared<D2DModeSwitchNotification>();
256 switchPktTx->setTxSide(true);
257 switchPktTx->setPeerId(dstId);
258 switchPktTx->setOldMode(oldMode);
259 switchPktTx->setNewMode(newMode);
260 switchPktTx->setInterruptHarq(d2dEnbHelper_.getMsHarqInterrupt());
261 switchPktTx->setClearRlcBuffer(d2dEnbHelper_.getMsClearRlcBuffer());
262
263 pktTx->addTagIfAbsent<UserControlInfo>()->setSourceId(this->nodeId_);
264 pktTx->addTagIfAbsent<UserControlInfo>()->setDestId(srcId);
265 pktTx->addTagIfAbsent<UserControlInfo>()->setFrameType(D2DMODESWITCHPKT);
266
267 pktTx->insertAtFront(switchPktTx);
268 auto switchPktTx_local = pktTx->dup();
269 this->sendLowerPackets(pktTx);
270
271 auto pktRx = new inet::Packet("D2DModeSwitchNotification");
272 auto switchPktRx = inet::makeShared<D2DModeSwitchNotification>();
273 switchPktRx->setTxSide(false);
274 switchPktRx->setPeerId(srcId);
275 switchPktRx->setOldMode(oldMode);
276 switchPktRx->setNewMode(newMode);
277 switchPktRx->setInterruptHarq(d2dEnbHelper_.getMsHarqInterrupt());
278 switchPktRx->setClearRlcBuffer(d2dEnbHelper_.getMsClearRlcBuffer());
279
280 pktRx->addTagIfAbsent<UserControlInfo>()->setSourceId(this->nodeId_);
281 pktRx->addTagIfAbsent<UserControlInfo>()->setDestId(dstId);
282 pktRx->addTagIfAbsent<UserControlInfo>()->setFrameType(D2DMODESWITCHPKT);
283 pktRx->insertAtFront(switchPktRx);
284
285 auto switchPktRx_local = pktRx->dup();
286 this->sendLowerPackets(pktRx);
287
288 this->scheduleAt(NOW + TTI, switchPktTx_local);
289 this->scheduleAt(NOW + TTI, switchPktRx_local);
290}
291
292template<class Base>
294{
295 Base::flushHarqBuffers();
296
297 // flush mirror buffer
298 for (auto& mirr_mit : d2dEnbHelper_.getHarqBuffersMirrorD2DMap()) {
299 for (auto& mirr_it : mirr_mit.second)
300 mirr_it.second->markSelectedAsWaiting();
301 }
302}
303
304template<class Base>
305LteHarqBufferRx *D2dEnbMacBase<Base>::createRxHarqBuffer(MacNodeId src, const UserControlInfo *userInfo)
306{
307 Direction dir = (Direction)userInfo->getDirection();
308 if (dir == D2D || dir == D2D_MULTI)
309 return new LteHarqBufferRxD2D(this->harqProcesses_, this, this->binder_, src, (dir == D2D_MULTI));
310 return Base::createRxHarqBuffer(src, userInfo);
311}
312
313template<class Base>
314void D2dEnbMacBase<Base>::fromPhy(cPacket *pktAux)
315{
316 auto pkt = check_and_cast<inet::Packet *>(pktAux);
317 auto userInfo = pkt->getTag<UserControlInfo>();
318 if (userInfo->getFrameType() == HARQPKT) {
319 MacNodeId src = userInfo->getSourceId();
320 GHz carrierFrequency = userInfo->getCarrierFrequency();
321
322 // this feedback refers to a mirrored H-ARQ buffer
323 auto hfbpkt = pkt->peekAtFront<LteHarqFeedback>();
324 if (!hfbpkt->getD2dFeedback()) { // this is not a mirror feedback
326 return;
327 }
328
329 // H-ARQ feedback, send it to the mirror buffer of the D2D pair
330 auto mfbpkt = pkt->peekAtFront<LteHarqFeedbackMirror>();
331 MacNodeId d2dSender = mfbpkt->getD2dSenderId();
332 MacNodeId d2dReceiver = mfbpkt->getD2dReceiverId();
333 D2DPair pair(d2dSender, d2dReceiver);
334 auto& harqBuffersMirrorD2D = d2dEnbHelper_.getHarqBuffersMirrorD2DMap();
335 HarqBuffersMirrorD2D::iterator hit = harqBuffersMirrorD2D[carrierFrequency].find(pair);
336 EV << NOW << "D2dEnbMacBase::fromPhy - node " << this->nodeId_ << " Received HARQ Feedback pkt (mirrored)" << endl;
337 if (hit == harqBuffersMirrorD2D[carrierFrequency].end()) {
338 // if feedback arrives, a buffer should exist (unless it is a handover scenario
339 // where the HARQ buffer was deleted but feedback was in transit)
340 // this case must be taken care of
341 if (connectionControl_->isHandingOver(src))
342 return;
343
344 // create buffer
345 LteHarqBufferMirrorD2D *hb = new LteHarqBufferMirrorD2D((unsigned int)this->harqProcesses_, (unsigned char)this->par("maxHarqRtx"), this);
346 harqBuffersMirrorD2D[carrierFrequency][pair] = hb;
347 hb->receiveHarqFeedback(pkt);
348 }
349 else {
350 hit->second->receiveHarqFeedback(pkt);
351 }
352 }
353 else {
355 }
356}
357
358} //namespace
359
360#endif
void flushHarqBuffers() override
Definition D2dEnbMacBase.h:293
LteHarqBufferRx * createRxHarqBuffer(MacNodeId src, const UserControlInfo *userInfo) override
HARQ RX buffer factory: adds support for the D2D and D2D_MULTI directions.
Definition D2dEnbMacBase.h:305
void handleMessage(cMessage *msg) override
intercepts the D2D self-messages (mode switch, conflict graph update)
Definition D2dEnbMacBase.h:202
void initialize(int stage) override
Definition D2dEnbMacBase.h:135
void deleteQueues(MacNodeId nodeId) override
Definition D2dEnbMacBase.h:226
void fromPhy(cPacket *pkt) override
Lower Layer Handler: intercepts mirrored D2D H-ARQ feedback.
Definition D2dEnbMacBase.h:314
Definition LteHarqBufferRxD2D.h:36
Definition LteHarqBufferRx.h:37
virtual void fromPhy(cPacket *pkt)
Lower Layer Handler.
Definition AlertReceiver.h:24
unsigned short Cqi
Channel Quality Indicator.
Definition LteTypes.h:133