@@ -842,156 +842,181 @@ void LteMacUeD2D::macHandleD2DModeSwitch(cPacket *pktAux)
842842 Direction newDirection = (newMode == DM ) ? D2D : UL ;
843843 Direction oldDirection = (oldMode == DM ) ? D2D : UL ;
844844
845- // Find the correct connection involved in the mode switch
846- for (auto & it : connDesc_) {
847- MacCid cid = it.first ;
848- FlowControlInfo *lteInfo = &(it.second );
849-
850- if (lteInfo->getD2dRxPeerId () == peerId && (Direction)lteInfo->getDirection () == oldDirection) {
851- EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - found old connection with cid " << cid << " , erasing buffered data" << endl;
852- if (oldDirection != newDirection) {
853- if (switchPkt->getClearRlcBuffer ()) {
854- EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - erasing buffered data" << endl;
855-
856- // Empty virtual buffer for the selected cid
857- auto macBuff_it = macBuffers_.find (cid);
858- if (macBuff_it != macBuffers_.end ()) {
859- while (!(macBuff_it->second ->isEmpty ()))
860- macBuff_it->second ->popFront ();
861- delete macBuff_it->second ;
862- macBuffers_.erase (macBuff_it);
863- }
845+ // Find the correct connections involved in the mode switch
846+ // Use two-phase approach: first collect, then process
864847
865- // Empty real buffer for the selected cid (they should be already empty)
866- auto qit = macQueues_.find (cid);
867- if (qit != macQueues_.end ()) {
868- while (qit->second ->getQueueLength () > 0 ) {
869- cPacket *pdu = qit->second ->popFront ();
870- delete pdu;
871- }
872- delete qit->second ;
873- macQueues_.erase (qit);
848+ // Phase 1: Collect CIDs and flow info that need processing
849+ std::vector<std::pair<MacCid, FlowControlInfo>> oldConnections;
850+ std::vector<std::pair<MacCid, FlowControlInfo>> newConnections;
851+
852+ for (const auto & [cid, lteInfo] : connDesc_) {
853+ if (lteInfo.getD2dRxPeerId () == peerId && (Direction)lteInfo.getDirection () == oldDirection) {
854+ oldConnections.emplace_back (cid, lteInfo);
855+ }
856+ else if (lteInfo.getD2dRxPeerId () == peerId && (Direction)lteInfo.getDirection () == newDirection) {
857+ newConnections.emplace_back (cid, lteInfo);
858+ }
859+ }
860+
861+ // Phase 2: Process old connections (safe to modify containers now)
862+ for (const auto & [cid, lteInfo] : oldConnections) {
863+ EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - found old connection with cid " << cid << " , erasing buffered data" << endl;
864+ if (oldDirection != newDirection) {
865+ if (switchPkt->getClearRlcBuffer ()) {
866+ EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - erasing buffered data" << endl;
867+
868+ // Empty virtual buffer for the selected cid
869+ auto macBuff_it = macBuffers_.find (cid);
870+ if (macBuff_it != macBuffers_.end ()) {
871+ while (!(macBuff_it->second ->isEmpty ()))
872+ macBuff_it->second ->popFront ();
873+ delete macBuff_it->second ;
874+ macBuffers_.erase (macBuff_it);
875+ }
876+
877+ // Empty real buffer for the selected cid (they should be already empty)
878+ auto qit = macQueues_.find (cid);
879+ if (qit != macQueues_.end ()) {
880+ while (qit->second ->getQueueLength () > 0 ) {
881+ cPacket *pdu = qit->second ->popFront ();
882+ delete pdu;
874883 }
884+ delete qit->second ;
885+ macQueues_.erase (qit);
875886 }
887+ }
876888
877- if (switchPkt->getInterruptHarq ()) {
878- EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - interrupting H-ARQ processes" << endl;
889+ if (switchPkt->getInterruptHarq ()) {
890+ EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - interrupting H-ARQ processes" << endl;
879891
880- // Interrupt H-ARQ processes for SL
881- MacNodeId id = peerId;
882- for (auto & mtit : harqTxBuffers_) {
883- HarqTxBuffers::iterator hit = mtit.second .find (id);
884- if (hit != mtit.second .end ()) {
885- for (int proc = 0 ; proc < (unsigned int )UE_TX_HARQ_PROCESSES ; proc++) {
886- hit->second ->forceDropProcess (proc);
887- }
892+ // Interrupt H-ARQ processes for SL
893+ MacNodeId id = peerId;
894+ for (auto & mtit : harqTxBuffers_) {
895+ HarqTxBuffers::iterator hit = mtit.second .find (id);
896+ if (hit != mtit.second .end ()) {
897+ for (int proc = 0 ; proc < (unsigned int )UE_TX_HARQ_PROCESSES ; proc++) {
898+ hit->second ->forceDropProcess (proc);
888899 }
900+ }
889901
890- // Interrupt H-ARQ processes for UL
891- id = getMacCellId ();
892- hit = mtit.second .find (id);
893- if (hit != mtit.second .end ()) {
894- for (int proc = 0 ; proc < (unsigned int )UE_TX_HARQ_PROCESSES ; proc++) {
895- hit->second ->forceDropProcess (proc);
896- }
902+ // Interrupt H-ARQ processes for UL
903+ id = getMacCellId ();
904+ hit = mtit.second .find (id);
905+ if (hit != mtit.second .end ()) {
906+ for (int proc = 0 ; proc < (unsigned int )UE_TX_HARQ_PROCESSES ; proc++) {
907+ hit->second ->forceDropProcess (proc);
897908 }
898909 }
899910 }
900911 }
912+ }
901913
902- // Abort BSR requests
903- bsrTriggered_ = false ;
914+ // Abort BSR requests
915+ bsrTriggered_ = false ;
904916
905- auto pktDup = pkt->dup ();
906- auto switchPkt_dup = pktDup->removeAtFront <D2DModeSwitchNotification>();
907- switchPkt_dup->setOldConnection (true );
908- pktDup->insertAtFront (switchPkt_dup);
909- *(pktDup->addTagIfAbsent <FlowControlInfo>()) = * lteInfo;
910- sendUpperPackets (pktDup);
917+ auto pktDup = pkt->dup ();
918+ auto switchPkt_dup = pktDup->removeAtFront <D2DModeSwitchNotification>();
919+ switchPkt_dup->setOldConnection (true );
920+ pktDup->insertAtFront (switchPkt_dup);
921+ *(pktDup->addTagIfAbsent <FlowControlInfo>()) = lteInfo;
922+ sendUpperPackets (pktDup);
911923
912- if (oldDirection != newDirection && switchPkt->getClearRlcBuffer ()) {
913- EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - clearing LCG map" << endl;
924+ if (oldDirection != newDirection && switchPkt->getClearRlcBuffer ()) {
925+ EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - clearing LCG map" << endl;
914926
915- // Remove entry from lcgMap
916- for (auto lt = lcgMap_.begin (); lt != lcgMap_.end (); ) {
917- if (lt->second .first == cid) {
918- lt = lcgMap_.erase (lt);
919- }
920- else {
921- ++lt;
922- }
927+ // Remove entry from lcgMap
928+ for (auto lt = lcgMap_.begin (); lt != lcgMap_.end (); ) {
929+ if (lt->second .first == cid) {
930+ lt = lcgMap_.erase (lt);
931+ }
932+ else {
933+ ++lt;
923934 }
924935 }
925- EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - send switch signal to the RLC TX entity corresponding to the old mode, cid " << cid << endl;
926936 }
927- else if (lteInfo->getD2dRxPeerId () == peerId && (Direction)lteInfo->getDirection () == newDirection) {
928- EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - send switch signal to the RLC TX entity corresponding to the new mode, cid " << cid << endl;
929- if (oldDirection != newDirection) {
930-
931- auto pktDup = pkt->dup ();
932- auto switchPkt_dup = pktDup->removeAtFront <D2DModeSwitchNotification>();
933- switchPkt_dup->setOldConnection (false );
934- // switchPkt_dup->setSchedulingPriority(1); // always after the old mode
935- pktDup->insertAtFront (switchPkt_dup);
936- *(pktDup->addTagIfAbsent <FlowControlInfo>()) = *lteInfo;
937- sendUpperPackets (pktDup);
938- }
937+ EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - send switch signal to the RLC TX entity corresponding to the old mode, cid " << cid << endl;
938+ }
939+
940+ // Phase 3: Process new connections
941+ for (const auto & [cid, lteInfo] : newConnections) {
942+ EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - send switch signal to the RLC TX entity corresponding to the new mode, cid " << cid << endl;
943+ if (oldDirection != newDirection) {
944+ auto pktDup = pkt->dup ();
945+ auto switchPkt_dup = pktDup->removeAtFront <D2DModeSwitchNotification>();
946+ switchPkt_dup->setOldConnection (false );
947+ // switchPkt_dup->setSchedulingPriority(1); // always after the old mode
948+ pktDup->insertAtFront (switchPkt_dup);
949+ *(pktDup->addTagIfAbsent <FlowControlInfo>()) = lteInfo;
950+ sendUpperPackets (pktDup);
939951 }
940952 }
941953 }
942954 else { // rx side
943955 Direction newDirection = (newMode == DM ) ? D2D : DL ;
944956 Direction oldDirection = (oldMode == DM ) ? D2D : DL ;
945957
946- // Find the correct connection involved in the mode switch
947- for (auto & item : connDescIn_) {
948- MacCid cid = item.first ;
949- FlowControlInfo *lteInfo = &(item.second );
950- if (lteInfo->getD2dTxPeerId () == peerId && (Direction)lteInfo->getDirection () == oldDirection) {
951- EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - found old connection with cid " << cid << " , send signal to the RLC RX entity" << endl;
952- if (oldDirection != newDirection) {
953- if (switchPkt->getInterruptHarq ()) {
954- // Interrupt H-ARQ processes for SL
955- MacNodeId id = peerId;
956- for (auto & mrit : harqRxBuffers_) {
957- HarqRxBuffers::iterator hit = mrit.second .find (id);
958- if (hit != mrit.second .end ()) {
959- for (unsigned int proc = 0 ; proc < (unsigned int )UE_RX_HARQ_PROCESSES ; proc++) {
960- unsigned int numUnits = hit->second ->getProcess (proc)->getNumHarqUnits ();
961- for (unsigned int i = 0 ; i < numUnits; i++) {
962- hit->second ->getProcess (proc)->purgeCorruptedPdu (i); // delete contained PDU
963- hit->second ->getProcess (proc)->resetCodeword (i); // reset unit
964- }
958+ // Find the correct connections involved in the mode switch
959+ // Use two-phase approach: first collect, then process
960+
961+ // Phase 1: Collect CIDs and flow info that need processing
962+ std::vector<std::pair<MacCid, FlowControlInfo>> oldRxConnections;
963+ std::vector<std::pair<MacCid, FlowControlInfo>> newRxConnections;
964+
965+ for (const auto & [cid, lteInfo] : connDescIn_) {
966+ if (lteInfo.getD2dTxPeerId () == peerId && (Direction)lteInfo.getDirection () == oldDirection) {
967+ oldRxConnections.emplace_back (cid, lteInfo);
968+ }
969+ else if (lteInfo.getD2dTxPeerId () == peerId && (Direction)lteInfo.getDirection () == newDirection) {
970+ newRxConnections.emplace_back (cid, lteInfo);
971+ }
972+ }
973+
974+ // Phase 2: Process old RX connections
975+ for (const auto & [cid, lteInfo] : oldRxConnections) {
976+ EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - found old connection with cid " << cid << " , send signal to the RLC RX entity" << endl;
977+ if (oldDirection != newDirection) {
978+ if (switchPkt->getInterruptHarq ()) {
979+ // Interrupt H-ARQ processes for SL
980+ MacNodeId id = peerId;
981+ for (auto & mrit : harqRxBuffers_) {
982+ HarqRxBuffers::iterator hit = mrit.second .find (id);
983+ if (hit != mrit.second .end ()) {
984+ for (unsigned int proc = 0 ; proc < (unsigned int )UE_RX_HARQ_PROCESSES ; proc++) {
985+ unsigned int numUnits = hit->second ->getProcess (proc)->getNumHarqUnits ();
986+ for (unsigned int i = 0 ; i < numUnits; i++) {
987+ hit->second ->getProcess (proc)->purgeCorruptedPdu (i); // delete contained PDU
988+ hit->second ->getProcess (proc)->resetCodeword (i); // reset unit
965989 }
966990 }
967991 }
968-
969- // Clear mirror H-ARQ buffers
970- enb_->deleteHarqBuffersMirrorD2D (peerId, nodeId_);
971-
972- // Notify that this UE is switching during this TTI
973- resetHarq_[peerId] = NOW ;
974992 }
975993
976- auto pktDup = pkt->dup ();
977- auto switchPkt_dup = pktDup->removeAtFront <D2DModeSwitchNotification>();
978- switchPkt_dup->setOldConnection (true );
979- pktDup->insertAtFront (switchPkt_dup);
980- *(pktDup->addTagIfAbsent <FlowControlInfo>()) = *lteInfo;
981- sendUpperPackets (pktDup);
994+ // Clear mirror H-ARQ buffers
995+ enb_->deleteHarqBuffersMirrorD2D (peerId, nodeId_);
996+
997+ // Notify that this UE is switching during this TTI
998+ resetHarq_[peerId] = NOW ;
982999 }
1000+
1001+ auto pktDup = pkt->dup ();
1002+ auto switchPkt_dup = pktDup->removeAtFront <D2DModeSwitchNotification>();
1003+ switchPkt_dup->setOldConnection (true );
1004+ pktDup->insertAtFront (switchPkt_dup);
1005+ *(pktDup->addTagIfAbsent <FlowControlInfo>()) = lteInfo;
1006+ sendUpperPackets (pktDup);
9831007 }
984- else if (lteInfo->getD2dTxPeerId () == peerId && (Direction)lteInfo->getDirection () == newDirection) {
985- EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - found new connection with cid " << cid << " , send signal to the RLC RX entity" << endl;
986- if (oldDirection != newDirection) {
987-
988- auto pktDup = pkt->dup ();
989- auto switchPkt_dup = pktDup->removeAtFront <D2DModeSwitchNotification>();
990- switchPkt_dup->setOldConnection (false );
991- pktDup->insertAtFront (switchPkt_dup);
992- *(pktDup->addTagIfAbsent <FlowControlInfo>()) = *lteInfo;
993- sendUpperPackets (pktDup);
994- }
1008+ }
1009+
1010+ // Phase 3: Process new RX connections
1011+ for (const auto & [cid, lteInfo] : newRxConnections) {
1012+ EV << NOW << " LteMacUeD2D::macHandleD2DModeSwitch - found new connection with cid " << cid << " , send signal to the RLC RX entity" << endl;
1013+ if (oldDirection != newDirection) {
1014+ auto pktDup = pkt->dup ();
1015+ auto switchPkt_dup = pktDup->removeAtFront <D2DModeSwitchNotification>();
1016+ switchPkt_dup->setOldConnection (false );
1017+ pktDup->insertAtFront (switchPkt_dup);
1018+ *(pktDup->addTagIfAbsent <FlowControlInfo>()) = lteInfo;
1019+ sendUpperPackets (pktDup);
9951020 }
9961021 }
9971022 }
0 commit comments