Skip to content

Commit 5b36325

Browse files
committed
Pdcp: Fix previously demostrated bug with Dual Connectivity setups.
In DC setups, both "legs" of PDCP should be handled by the *same* PDCP entity, both on the NODEB and UE side. The code now makes sure to use the same key for both leg when looking up the PDCP entity, therefore ensuring that the two legs will use the same entity (rather than 2 separate ones). This fix changes the operation and results of 5 simulation configs, causing fingerprint mismatches (see below). It also breaks one packet loss statistic in RLC-UM (rlcPacketLossUl:mean, etc), because it (*incorrectly!*) relied on PDCP sequence numbers for loss detection. PDCP numbers in RLC-UM used to be contiguous before the fix, but now they are not. E.g. if every other packet goes via Secondary, then RLC on one leg sees sequence numbers 0,2,4,6,.., and the other sees 1,3,5,7,... This will be rectified in a later commit. FAILED (failures=5) Failures: /simulations/nr/dualConnectivity_multicell/ -f omnetpp.ini -c SplitBearer-CBR-DL -r 0 (some fingerprint mismatch: actual '09f4-2368/tplx;9051-9bc4/sz', expected: '08b0-117e/tplx;6ae8-d7e6/sz') /simulations/nr/dualConnectivity/ -f omnetpp.ini -c DualConn-SplitBearer-DL -r 0 (some fingerprint mismatch: actual '8374-3d2c/tplx;b1ad-9eca/sz', expected: '2a68-ef06/tplx;a8eb-317b/sz') /simulations/nr/dualConnectivity/ -f omnetpp.ini -c DualConn-SplitBearer-UL -r 0 (some fingerprint mismatch: actual '4a58-fbc0/tplx;10fc-8897/~tNl;8d56-a05a/sz', expected: '1edd-20b8/tplx;918b-7244/~tNl;d494-fafd/sz') /simulations/nr/test_numerology/ -f omnetpp.ini -c MultiCell-CBR-DL -r 0 (some fingerprint mismatch: actual '734e-aeb6/tplx;ba3b-79af/sz', expected: 'dc64-0700/tplx;2be7-67b0/sz') /simulations/nr/test_numerology/ -f omnetpp.ini -c MultiCell-CBR-UL -r 0 (some fingerprint mismatch: actual '9fa6-61ae/tplx;fbcb-904c/~tNl;7037-b0f5/sz', expected: '29d2-5907/tplx;6ea1-c40a/~tNl;e70b-6f52/sz') ---------------------------------------------------------------------- Ran 127 tests in 164.289s FAILED (failures=5)
1 parent 80f3028 commit 5b36325

File tree

1 file changed

+74
-23
lines changed

1 file changed

+74
-23
lines changed

src/simu5g/stack/pdcp/LtePdcp.cc

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
#include "simu5g/stack/pdcp/LtePdcp.h"
1313

14-
#include <inet/common/stlutils.h>
1514
#include <inet/networklayer/ipv4/Ipv4Header_m.h>
1615
#include <inet/transportlayer/tcp_common/TcpHeader.h>
1716
#include <inet/transportlayer/udp/UdpHeader_m.h>
@@ -155,6 +154,25 @@ void LtePdcpBase::fromDataPort(cPacket *pktAux)
155154

156155
MacCid cid = MacCid(lteInfo->getDestId(), lteInfo->getLcid());
157156

157+
if (isDualConnectivityEnabled() && lteInfo->getMulticastGroupId() == -1) {
158+
// Handle DC setup: Assume packet arrives in Master nodeB (LTE), and wants to use Secondary nodeB (NR).
159+
// Packet is processed by local PDCP entity, then needs to be tunneled over X2 to Secondary for transmission.
160+
// However, local PDCP entity is keyed on LTE nodeIds, so we need to tweak the cid and replace NR nodeId
161+
// with LTE nodeId so that lookup succeeds.
162+
if (getNodeTypeById(nodeId_) == ENODEB && binder_->isGNodeB(nodeId_) != isNrUe(lteInfo->getDestId()) ) {
163+
// use another CID whose technology matches the nodeB
164+
MacNodeId otherDestId = binder_->getUeNodeId(lteInfo->getDestId(), !isNrUe(lteInfo->getDestId()));
165+
ASSERT(otherDestId != NODEID_NONE);
166+
cid = MacCid(otherDestId, lteInfo->getLcid());
167+
}
168+
169+
// Handle DC setup on UE side: both legs should use the *same* key for entity lookup
170+
if (getNodeTypeById(nodeId_) == UE && getNodeTypeById(lteInfo->getDestId()) == ENODEB) {
171+
MacNodeId lteNodeB = binder_->getServingNode(nodeId_);
172+
cid = MacCid(lteNodeB, lteInfo->getLcid());
173+
}
174+
}
175+
158176
LteTxPdcpEntity *entity = lookupTxEntity(cid);
159177

160178
// get the PDCP entity for this LCID and process the packet
@@ -163,18 +181,8 @@ void LtePdcpBase::fromDataPort(cPacket *pktAux)
163181
<< " multicast=" << lteInfo->getMulticastGroupId() << " direction=" << dirToA((Direction)lteInfo->getDirection())
164182
<< " ---> CID " << cid << (entity == nullptr ? " (NEW)" : " (existing)") << std::endl;
165183

166-
if (entity == nullptr) {
184+
if (entity == nullptr)
167185
entity = createTxEntity(cid);
168-
169-
// check for bug
170-
if (getNodeTypeById(nodeId_) == ENODEB && lteInfo->getMulticastGroupId() == -1) {
171-
MacCid lteCid = MacCid(binder_->getUeNodeId(lteInfo->getDestId(), false), lteInfo->getLcid());
172-
MacCid nrCid = MacCid(binder_->getUeNodeId(lteInfo->getDestId(), true), lteInfo->getLcid());
173-
if (inet::containsKey(txEntities_, lteCid) && inet::containsKey(txEntities_, nrCid))
174-
throw cRuntimeError("Both LTE and NR cids of same UE are present as txEntities_ keys: %s, %s", lteCid.str().c_str(), nrCid.str().c_str());
175-
}
176-
}
177-
178186
entity->handlePacketFromUpperLayer(pkt);
179187
}
180188

@@ -189,21 +197,64 @@ void LtePdcpBase::fromLowerLayer(cPacket *pktAux)
189197

190198
auto lteInfo = pkt->getTag<FlowControlInfo>();
191199

192-
MacCid cid = MacCid(lteInfo->getSourceId(), lteInfo->getLcid()); // TODO: check if you have to get master node id
193-
194-
LteRxPdcpEntity *entity = lookupRxEntity(cid);
195-
if (entity == nullptr) {
196-
entity = createRxEntity(cid);
200+
MacCid cid = MacCid(lteInfo->getSourceId(), lteInfo->getLcid());
201+
202+
if (isDualConnectivityEnabled()) {
203+
// Handle DC setup: Assume packet arrives at this Master nodeB (LTE) from Secondary (NR) over X2.
204+
// Packet needs to be processed by local PDCP entity. However, local PDCP entity is keyed on LTE nodeIds,
205+
// so we need to tweak the cid and replace NR nodeId with LTE nodeId so that lookup succeeds.
206+
if (getNodeTypeById(nodeId_) == ENODEB && binder_->isGNodeB(nodeId_) != isNrUe(lteInfo->getSourceId()) ) {
207+
// use another CID whose technology matches the nodeB
208+
MacNodeId otherSourceId = binder_->getUeNodeId(lteInfo->getSourceId(), !isNrUe(lteInfo->getSourceId()));
209+
ASSERT(otherSourceId != NODEID_NONE);
210+
cid = MacCid(otherSourceId, lteInfo->getLcid());
211+
}
197212

198-
// check for bug
199-
if (getNodeTypeById(nodeId_) == ENODEB && lteInfo->getMulticastGroupId() == -1) {
200-
MacCid lteCid = MacCid(binder_->getUeNodeId(lteInfo->getSourceId(), false), lteInfo->getLcid());
201-
MacCid nrCid = MacCid(binder_->getUeNodeId(lteInfo->getSourceId(), true), lteInfo->getLcid());
202-
if (inet::containsKey(rxEntities_, lteCid) && inet::containsKey(rxEntities_, nrCid))
203-
throw cRuntimeError("Both LTE and NR cids of same UE are present as rxEntities_ keys: %s, %s", lteCid.str().c_str(), nrCid.str().c_str());
213+
// Handle DC setup on UE side: both legs should use the *same* key for entity lookup
214+
if (getNodeTypeById(nodeId_) == UE && getNodeTypeById(lteInfo->getSourceId()) == ENODEB) {
215+
MacNodeId lteNodeB = binder_->getServingNode(nodeId_);
216+
cid = MacCid(lteNodeB, lteInfo->getLcid());
204217
}
218+
}
205219

220+
// Handle DC setup on UE side: UE receives packet from base station
221+
// and needs to use the correct PDCP entity based on technology matching
222+
if (getNodeTypeById(nodeId_) == UE && lteInfo->getMulticastGroupId() == -1 && isDualConnectivityEnabled()) {
223+
MacNodeId servingNodeId = binder_->getServingNode(nodeId_);
224+
225+
// Check if there's a technology mismatch between packet source and UE's serving base station
226+
if (servingNodeId != NODEID_NONE &&
227+
binder_->isGNodeB(lteInfo->getSourceId()) != binder_->isGNodeB(servingNodeId)) {
228+
229+
// Use alternate base station nodeId (Master or Secondary) for proper PDCP entity lookup
230+
MacNodeId otherSrcId;
231+
if (binder_->isGNodeB(lteInfo->getSourceId())) {
232+
// Packet came from gNodeB, get its master (LTE eNodeB)
233+
otherSrcId = binder_->getMasterNodeOrSelf(lteInfo->getSourceId());
234+
} else {
235+
// Packet came from eNodeB, get its secondary (NR gNodeB)
236+
otherSrcId = binder_->getSecondaryNode(lteInfo->getSourceId());
237+
}
238+
239+
if (otherSrcId != NODEID_NONE && otherSrcId != lteInfo->getSourceId()) {
240+
cid = MacCid(otherSrcId, lteInfo->getLcid());
241+
242+
EV << "LtePdcp: UE DC RX - Using alternate base station ID " << otherSrcId
243+
<< " instead of " << lteInfo->getSourceId()
244+
<< " for technology match with serving node " << servingNodeId << endl;
245+
}
246+
}
206247
}
248+
249+
LteRxPdcpEntity *entity = lookupRxEntity(cid);
250+
251+
EV << "fromLowerLayer in " << getFullPath() << " event #" << getSimulation()->getEventNumber()
252+
<< ": Processing packet " << pkt->getName() << " src=" << lteInfo->getSourceId() << " dest=" << lteInfo->getDestId()
253+
<< " multicast=" << lteInfo->getMulticastGroupId() << " direction=" << dirToA((Direction)lteInfo->getDirection())
254+
<< " ---> CID " << cid << (entity == nullptr ? " (NEW)" : " (existing)") << std::endl;
255+
256+
if (entity == nullptr)
257+
entity = createRxEntity(cid);
207258
entity->handlePacketFromLowerLayer(pkt);
208259
}
209260

0 commit comments

Comments
 (0)