Skip to content

Commit 71e1a6a

Browse files
committed
MAC: fix ASSERT failure on D2D mode switching
Repro: $ cd simulations/nr/d2d && simu5g_dbg -u Cmdenv -c SinglePair-modeSwitching-UDP <!> Error: ASSERT: Condition 'connDescOut_.find(cid) != connDescOut_.end()' does not hold in function 'bufferizePacket' at simu5g/stack/mac/LteMacUe.cc:259 -- in module (simu5g::NrMacUe) SingleCell_Standalone_D2D.ueD2DTx[0].cellularNic.nrMac (id=309), at t=15.05952167965s, event #172116 Root cause: When D2D mode switches from DM->IM, macHandleD2DModeSwitch() calls deleteOutgoingConnection() which permanently destroys the MAC connection (connDescOut_ entry, queue, and virtual buffer). However, the PDCP layer retains its LCID table entry and TX entity for that CID. When the mode switches back (IM->DM), PDCP considers the connection "existing" and doesn't trigger binder_->establishUnidirectionalDataConnection(). The packet flows down to MAC which ASSERTs the connection exists - but it was permanently deleted. Fix: LteMacBase: Added clearOutgoingConnectionBuffers(MacCid) that empties queue and virtual buffer contents without destroying the connection structure LteMacUeD2D: Replaced deleteOutgoingConnection(cid) with clearOutgoingConnectionBuffers(cid) in the mode switch handler, and removed the now-unnecessary redundant lcgMap_ cleanup code (which was dead code since deleteOutgoingConnection already cleaned it) This ensures the MAC connection persists across mode switches with empty buffers, ready to receive data when the mode switches back. The idle connection with empty buffers has zero scheduling impact.
1 parent 88160e1 commit 71e1a6a

3 files changed

Lines changed: 26 additions & 14 deletions

File tree

src/simu5g/stack/mac/LteMacBase.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,23 @@ void LteMacBase::deleteOutgoingConnection(MacCid cid)
234234
connDescOut_.erase(it);
235235
}
236236

237+
void LteMacBase::clearOutgoingConnectionBuffers(MacCid cid)
238+
{
239+
auto it = connDescOut_.find(cid);
240+
if (it == connDescOut_.end())
241+
throw cRuntimeError("LteMacBase::clearOutgoingConnectionBuffers - Connection %s not found", cid.str().c_str());
242+
243+
OutgoingConnectionInfo& connInfo = it->second;
244+
245+
// Empty the real buffer (drop all packets)
246+
while (!connInfo.queue->isEmpty())
247+
delete connInfo.queue->popFront();
248+
249+
// Empty the virtual buffer
250+
while (!connInfo.buffer->isEmpty())
251+
connInfo.buffer->popFront();
252+
}
253+
237254
void LteMacBase::createIncomingConnection(MacCid cid, const FlowDescriptor& connInfo)
238255
{
239256
Enter_Method("createIncomingConnection(%s)", cid.str().c_str());

src/simu5g/stack/mac/LteMacBase.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,13 @@ class LteMacBase : public cSimpleModule
428428
*/
429429
virtual void deleteOutgoingConnection(MacCid cid);
430430

431+
/**
432+
* clearOutgoingConnectionBuffers() empties the MAC queues and virtual buffers
433+
* for a given CID without destroying the connection. Used during D2D mode switch
434+
* to preserve the connection for potential mode switch back.
435+
*/
436+
virtual void clearOutgoingConnectionBuffers(MacCid cid);
437+
431438
/**
432439
* createIncomingConnection() registers an incoming connection for a given CID
433440
* if it doesn't already exist

src/simu5g/stack/mac/LteMacUeD2D.cc

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,8 @@ void LteMacUeD2D::macHandleD2DModeSwitch(cPacket *pktAux)
848848
if (switchPkt->getClearRlcBuffer()) {
849849
EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - erasing buffered data" << endl;
850850

851-
deleteOutgoingConnection(cid);
851+
// Clear buffers but keep the connection alive for potential mode switch back
852+
clearOutgoingConnectionBuffers(cid);
852853
}
853854

854855
if (switchPkt->getInterruptHarq()) {
@@ -886,19 +887,6 @@ void LteMacUeD2D::macHandleD2DModeSwitch(cPacket *pktAux)
886887
*(pktDup->addTagIfAbsent<FlowControlInfo>()) = connInfo;
887888
sendUpperPackets(pktDup);
888889

889-
if (oldDirection != newDirection && switchPkt->getClearRlcBuffer()) {
890-
EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - clearing LCG map" << endl;
891-
892-
// Remove entry from lcgMap
893-
for (auto lt = lcgMap_.begin(); lt != lcgMap_.end(); ) {
894-
if (lt->second.first == cid) {
895-
lt = lcgMap_.erase(lt);
896-
}
897-
else {
898-
++lt;
899-
}
900-
}
901-
}
902890
EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - send switch signal to the RLC TX entity corresponding to the old mode, cid " << cid << endl;
903891
}
904892

0 commit comments

Comments
 (0)