Skip to content

Commit 64203a0

Browse files
committed
MAC: Add RACH preamble collision modeling
UEs now pick a random preamble index (0..numPreambles-1) when sending RAC requests. The eNB buffers all RAC packets arriving during a TTI and resolves them at the start of the next TTI: if multiple UEs chose the same preamble, all of them fail (collision). Unique preambles succeed as before. Failed UEs exercise the existing backoff/retry path. New NED parameter `numPreambles` (default 64) on both LteMacUe and LteMacEnb controls the preamble pool size. While this is a simplified model of the multi-step exchange that actually takes place in real LTE and NR systems, it is still represents an improvement over the previous code that never reported collision.
1 parent f54753e commit 64203a0

8 files changed

Lines changed: 86 additions & 15 deletions

File tree

src/simu5g/stack/mac/LteMacEnb.cc

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ LteMacEnb::~LteMacEnb()
6464

6565
for (auto &[key, value] : bsrbuf_)
6666
delete value;
67+
68+
for (auto &[preamble, pkts] : pendingRacRequests_)
69+
for (auto *pkt : pkts)
70+
delete pkt;
6771
}
6872

6973
/***********************
@@ -130,6 +134,8 @@ void LteMacEnb::initialize(int stage)
130134

131135
cellId_ = nodeId_;
132136

137+
numPreambles_ = par("numPreambles");
138+
133139
cellInfo_.reference(this, "cellInfoModule", true);
134140

135141
eNodeBCount = par("eNodeBCount");
@@ -454,24 +460,62 @@ void LteMacEnb::sendGrants(std::map<GHz, LteMacScheduleList> *scheduleList)
454460

455461
void LteMacEnb::macHandleRac(cPacket *pktAux)
456462
{
457-
EV << NOW << "LteMacEnb::macHandleRac" << endl;
458-
459463
auto pkt = check_and_cast<Packet *>(pktAux);
464+
auto racPkt = pkt->peekAtFront<LteRac>();
465+
int preamble = racPkt->getPreambleIndex();
466+
467+
EV << NOW << "LteMacEnb::macHandleRac - buffering RAC from UE "
468+
<< pkt->getTag<UserControlInfo>()->getSourceId()
469+
<< " preamble=" << preamble << endl;
470+
471+
pendingRacRequests_[preamble].push_back(pkt);
472+
}
460473

461-
auto racPkt = pkt->removeAtFront<LteRac>();
462-
auto uinfo = pkt->getTagForUpdate<UserControlInfo>();
474+
void LteMacEnb::resolveRacCollisions()
475+
{
476+
if (pendingRacRequests_.empty())
477+
return;
463478

464-
enbSchedulerUl_->signalRac(uinfo->getSourceId(), uinfo->getCarrierFrequency());
479+
EV << NOW << "LteMacEnb::resolveRacCollisions - resolving "
480+
<< pendingRacRequests_.size() << " preamble groups" << endl;
465481

466-
// TODO: all RACs are marked as successful
467-
racPkt->setSuccess(true);
468-
pkt->insertAtFront(racPkt);
482+
for (auto& [preamble, pkts] : pendingRacRequests_) {
483+
bool collision = (pkts.size() > 1);
469484

470-
uinfo->setDestId(uinfo->getSourceId());
471-
uinfo->setSourceId(nodeId_);
472-
uinfo->setDirection(DL);
485+
if (collision) {
486+
EV << NOW << "LteMacEnb::resolveRacCollisions - COLLISION on preamble "
487+
<< preamble << " (" << pkts.size() << " UEs)" << endl;
488+
}
473489

474-
sendLowerPackets(pkt);
490+
for (auto *pkt : pkts) {
491+
auto racPkt = pkt->removeAtFront<LteRac>();
492+
auto uinfo = pkt->getTagForUpdate<UserControlInfo>();
493+
MacNodeId ueId = uinfo->getSourceId();
494+
495+
if (collision) {
496+
// preamble collision: RAC fails
497+
racPkt->setSuccess(false);
498+
EV << NOW << "LteMacEnb::resolveRacCollisions - UE " << ueId
499+
<< " RAC FAILED (preamble collision)" << endl;
500+
}
501+
else {
502+
// unique preamble: RAC succeeds
503+
racPkt->setSuccess(true);
504+
enbSchedulerUl_->signalRac(ueId, uinfo->getCarrierFrequency());
505+
EV << NOW << "LteMacEnb::resolveRacCollisions - UE " << ueId
506+
<< " RAC SUCCESS" << endl;
507+
}
508+
509+
pkt->insertAtFront(racPkt);
510+
511+
uinfo->setDestId(ueId);
512+
uinfo->setSourceId(nodeId_);
513+
uinfo->setDirection(DL);
514+
515+
sendLowerPackets(pkt);
516+
}
517+
}
518+
pendingRacRequests_.clear();
475519
}
476520

477521
void LteMacEnb::macPduMake(MacCid cid)
@@ -753,6 +797,9 @@ void LteMacEnb::handleSelfMessage()
753797

754798
EV << "-----" << "ENB MAIN LOOP -----" << endl;
755799

800+
// Resolve any RAC requests buffered since the last TTI (preamble collision detection)
801+
resolveRacCollisions();
802+
756803
// Reception
757804

758805
// extract PDUs from all HARQ RX buffers and pass them to unmaker

src/simu5g/stack/mac/LteMacEnb.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ class LteMacEnb : public LteMacBase
5151

5252
/*******************************************************************************************/
5353

54+
/// Number of RACH preambles for contention-based random access
55+
int numPreambles_ = 64;
56+
57+
/// Pending RAC requests received during this TTI, grouped by preamble index.
58+
/// Resolved at the start of handleSelfMessage() to detect collisions.
59+
std::map<int, std::vector<inet::Packet *>> pendingRacRequests_;
60+
5461
/// Buffer for the BSRs
5562
/// In the key (MacCid), lcid is a BsrType: one of SHORT_BSR, D2D_SHORT_BSR, D2D_MULTI_SHORT_BSR.
5663
std::map<MacCid, LteMacBuffer*> bsrbuf_;
@@ -154,10 +161,16 @@ class LteMacEnb : public LteMacBase
154161
void macHandleFeedbackPkt(cPacket *pkt) override;
155162

156163
/*
157-
* Receives and handles RAC requests.
164+
* Buffers incoming RAC requests for preamble collision detection.
158165
*/
159166
void macHandleRac(cPacket *pkt) override;
160167

168+
/*
169+
* Resolves buffered RAC requests: detects preamble collisions and sends
170+
* success/failure responses. Called at the start of each TTI.
171+
*/
172+
void resolveRacCollisions();
173+
161174
/*
162175
* Update UserTxParam stored in every lteMacPdu when an RTX changes this information.
163176
*/

src/simu5g/stack/mac/LteMacEnb.ned

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ simple LteMacEnb extends LteMacBase
7777

7878
string pilotMode @enum(IN_CQI,MAX_CQI,AVG_CQI,MEDIAN_CQI,ROBUST_CQI) = default("ROBUST_CQI");
7979

80+
int numPreambles = default(64); // number of RACH preambles available for contention-based random access
81+
8082
string cellInfoModule;
8183
string rlcUmModule = default("^.rlc.um");
8284
string pdcpModule = default("^.pdcp");

src/simu5g/stack/mac/LteMacUe.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ void LteMacUe::initialize(int stage)
6060
bool isNr = strcmp(getFullName(), "nrMac") == 0;
6161
nodeId_ = MacNodeId(networkNode_->par(isNr ? "nrMacNodeId" : "macNodeId").intValue());
6262

63+
numPreambles_ = par("numPreambles");
6364
maxRacTryouts_ = par("maxRacAttempts");
6465
minRacBackoff_ = par("racBackoffMin");
6566
maxRacBackoff_ = par("racBackoffMax");
@@ -876,6 +877,7 @@ void LteMacUe::checkRAC()
876877
auto pkt = new Packet("RacRequest");
877878

878879
auto racReq = makeShared<LteRac>();
880+
racReq->setPreambleIndex(intuniform(0, numPreambles_ - 1));
879881
pkt->insertAtFront(racReq);
880882

881883
GHz carrierFrequency = phy_->getPrimaryChannelModel()->getCarrierFrequency();
@@ -887,7 +889,8 @@ void LteMacUe::checkRAC()
887889

888890
sendLowerPackets(pkt);
889891

890-
EV << NOW << " UE " << nodeId_ << " cell " << cellId_ << " ,RAC request sent to PHY " << endl;
892+
EV << NOW << " UE " << nodeId_ << " cell " << cellId_ << " ,RAC request sent to PHY (preamble="
893+
<< racReq->getPreambleIndex() << ")" << endl;
891894

892895
// wait at least "raRespWinStart_" TTIs before another RAC request
893896
raRespTimer_ = raRespWinStart_;

src/simu5g/stack/mac/LteMacUe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class LteMacUe : public LteMacBase
5656

5757
// RAC and BSR configuration
5858
// TODO adjust C++ names to match NED parameter names
59+
int numPreambles_ = 64;
5960
unsigned int maxRacTryouts_ = 0;
6061
unsigned int minRacBackoff_ = 0;
6162
unsigned int maxRacBackoff_ = 0;

src/simu5g/stack/mac/LteMacUe.ned

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ simple LteMacUe extends LteMacBase
2727
@class("LteMacUe");
2828
string collectorModule = default("");
2929

30+
int numPreambles = default(64); // number of RACH preambles available for contention-based random access
3031
int maxRacAttempts = default(10); // preambleTransMax; max RAC attempts (0 = give up after first failure)
3132
int racBackoffMin = default(0); // min random backoff (TTIs) after failed RAC
3233
int racBackoffMax = default(20); // max random backoff (TTIs) after failed RAC (0 = no backoff, instant retry)

src/simu5g/stack/mac/LteMacUeD2D.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,13 @@ void LteMacUeD2D::checkRAC()
524524
pkt->addTagIfAbsent<UserControlInfo>()->setFrameType(RACPKT);
525525

526526
auto racReq = makeShared<LteRac>();
527+
racReq->setPreambleIndex(intuniform(0, numPreambles_ - 1));
527528

528529
pkt->insertAtFront(racReq);
529530
sendLowerPackets(pkt);
530531

531-
EV << NOW << " Ue " << nodeId_ << " cell " << cellId_ << ", RAC request sent to PHY " << endl;
532+
EV << NOW << " Ue " << nodeId_ << " cell " << cellId_ << ", RAC request sent to PHY (preamble="
533+
<< racReq->getPreambleIndex() << ")" << endl;
532534

533535
// wait at least "raRespWinStart_" TTIs before another RAC request
534536
raRespTimer_ = raRespWinStart_;

src/simu5g/stack/mac/packet/LteRac.msg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@ class LteRac extends inet::FieldsChunk
1818
{
1919
// meaningful only for DL (response) RAC packets : if true RAC request has been admitted.
2020
bool success;
21+
// preamble index chosen by UE (0..numPreambles-1); used for collision detection at eNB
22+
int preambleIndex = -1;
2123
chunkLength = inet::B(1); // TODO: size 0
2224
}

0 commit comments

Comments
 (0)