5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-epc-x2.cc
1// Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4//
5// Author: Manuel Requena <manuel.requena@cttc.es>
6
7#include "nr-epc-x2.h"
8
9#include "nr-epc-gtpu-header.h"
10#include "nr-epc-x2-header.h"
11
12#include "ns3/inet-socket-address.h"
13#include "ns3/log.h"
14#include "ns3/node.h"
15#include "ns3/packet.h"
16
17namespace ns3
18{
19
20NS_LOG_COMPONENT_DEFINE("NrEpcX2");
21
22NrX2IfaceInfo::NrX2IfaceInfo(Ipv4Address remoteIpAddr,
23 Ptr<Socket> localCtrlPlaneSocket,
24 Ptr<Socket> localUserPlaneSocket)
25{
26 m_remoteIpAddr = remoteIpAddr;
27 m_localCtrlPlaneSocket = localCtrlPlaneSocket;
28 m_localUserPlaneSocket = localUserPlaneSocket;
29}
30
31NrX2IfaceInfo::~NrX2IfaceInfo()
32{
33 m_localCtrlPlaneSocket = nullptr;
34 m_localUserPlaneSocket = nullptr;
35}
36
37NrX2IfaceInfo&
39{
40 NS_LOG_FUNCTION(this);
44 return *this;
45}
46
48
49NrX2CellInfo::NrX2CellInfo(std::vector<uint16_t> localCellIds, std::vector<uint16_t> remoteCellIds)
50 : m_localCellIds{localCellIds},
51 m_remoteCellIds{remoteCellIds}
52{
53}
54
55NrX2CellInfo::~NrX2CellInfo()
56{
57}
58
59NrX2CellInfo&
61{
62 NS_LOG_FUNCTION(this);
65 return *this;
66}
67
69
70NS_OBJECT_ENSURE_REGISTERED(NrEpcX2);
71
73 : m_x2cUdpPort(4444),
74 m_x2uUdpPort(2152)
75{
76 NS_LOG_FUNCTION(this);
77
79}
80
82{
83 NS_LOG_FUNCTION(this);
84}
85
86void
87NrEpcX2::DoDispose()
88{
89 NS_LOG_FUNCTION(this);
90
91 m_x2InterfaceSockets.clear();
92 m_x2InterfaceCellIds.clear();
93 delete m_x2SapProvider;
94}
95
96TypeId
98{
99 static TypeId tid = TypeId("ns3::NrEpcX2").SetParent<Object>().SetGroupName("Nr");
100 return tid;
101}
102
103void
105{
106 NS_LOG_FUNCTION(this << s);
107 m_x2SapUser = s;
108}
109
112{
113 NS_LOG_FUNCTION(this);
114 return m_x2SapProvider;
115}
116
117void
118NrEpcX2::AddX2Interface(uint16_t localCellId,
119 Ipv4Address localX2Address,
120 std::vector<uint16_t> remoteCellIds,
121 Ipv4Address remoteX2Address)
122{
123 uint16_t remoteCellId = remoteCellIds.at(0);
124 NS_LOG_FUNCTION(this << localCellId << localX2Address << remoteCellId << remoteX2Address);
125
126 int retval;
127
128 // Get local gNB where this X2 entity belongs to
129 Ptr<Node> localGnb = GetObject<Node>();
130
131 // Create X2-C socket for the local gNB
132 Ptr<Socket> localX2cSocket =
133 Socket::CreateSocket(localGnb, TypeId::LookupByName("ns3::UdpSocketFactory"));
134 retval = localX2cSocket->Bind(InetSocketAddress(localX2Address, m_x2cUdpPort));
135 NS_ASSERT(retval == 0);
136 localX2cSocket->SetRecvCallback(MakeCallback(&NrEpcX2::RecvFromX2cSocket, this));
137
138 // Create X2-U socket for the local gNB
139 Ptr<Socket> localX2uSocket =
140 Socket::CreateSocket(localGnb, TypeId::LookupByName("ns3::UdpSocketFactory"));
141 retval = localX2uSocket->Bind(InetSocketAddress(localX2Address, m_x2uUdpPort));
142 NS_ASSERT(retval == 0);
143 localX2uSocket->SetRecvCallback(MakeCallback(&NrEpcX2::RecvFromX2uSocket, this));
144
145 std::vector<uint16_t> localCellIds;
146 localCellIds.push_back(localCellId);
147
148 NS_ASSERT_MSG(m_x2InterfaceSockets.find(remoteCellId) == m_x2InterfaceSockets.end(),
149 "Mapping for remoteCellId = " << remoteCellId << " is already known");
150 for (uint16_t remoteCellId : remoteCellIds)
151 {
152 m_x2InterfaceSockets[remoteCellId] =
153 Create<NrX2IfaceInfo>(remoteX2Address, localX2cSocket, localX2uSocket);
154 }
155
156 NS_ASSERT_MSG(m_x2InterfaceCellIds.find(localX2cSocket) == m_x2InterfaceCellIds.end(),
157 "Mapping for control plane localSocket = " << localX2cSocket
158 << " is already known");
159 m_x2InterfaceCellIds[localX2cSocket] = Create<NrX2CellInfo>(localCellIds, remoteCellIds);
160
161 NS_ASSERT_MSG(m_x2InterfaceCellIds.find(localX2uSocket) == m_x2InterfaceCellIds.end(),
162 "Mapping for data plane localSocket = " << localX2uSocket << " is already known");
163 m_x2InterfaceCellIds[localX2uSocket] = Create<NrX2CellInfo>(localCellIds, remoteCellIds);
164}
165
166void
167NrEpcX2::RecvFromX2cSocket(Ptr<Socket> socket)
168{
169 NS_LOG_FUNCTION(this << socket);
170
171 NS_LOG_LOGIC("Recv X2 message: from Socket");
172 Ptr<Packet> packet = socket->Recv();
173 NS_LOG_LOGIC("packetLen = " << packet->GetSize());
174
175 NS_ASSERT_MSG(m_x2InterfaceCellIds.find(socket) != m_x2InterfaceCellIds.end(),
176 "Missing infos of local and remote CellId");
177 Ptr<NrX2CellInfo> cellsInfo = m_x2InterfaceCellIds[socket];
178
179 NrEpcX2Header x2Header;
180 packet->RemoveHeader(x2Header);
181
182 NS_LOG_LOGIC("X2 header: " << x2Header);
183
184 uint8_t messageType = x2Header.GetMessageType();
185 uint8_t procedureCode = x2Header.GetProcedureCode();
186
187 if (procedureCode == NrEpcX2Header::HandoverPreparation)
188 {
189 if (messageType == NrEpcX2Header::InitiatingMessage)
190 {
191 NS_LOG_LOGIC("Recv X2 message: HANDOVER REQUEST");
192
193 NrEpcX2HandoverRequestHeader x2HoReqHeader;
194 packet->RemoveHeader(x2HoReqHeader);
195
196 NS_LOG_INFO("X2 HandoverRequest header: " << x2HoReqHeader);
197
199 params.oldGnbUeX2apId = x2HoReqHeader.GetOldGnbUeX2apId();
200 params.cause = x2HoReqHeader.GetCause();
201 params.sourceCellId = cellsInfo->m_remoteCellIds.at(0);
202 params.targetCellId = x2HoReqHeader.GetTargetCellId();
203 params.mmeUeS1apId = x2HoReqHeader.GetMmeUeS1apId();
206 params.bearers = x2HoReqHeader.GetBearers();
207 params.rrcContext = packet;
208
209 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
210 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
211 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
212 NS_LOG_LOGIC("mmeUeS1apId = " << params.mmeUeS1apId);
213 NS_LOG_LOGIC("cellsInfo->m_localCellId = " << cellsInfo->m_localCellIds.at(0));
214
216 }
217 else if (messageType == NrEpcX2Header::SuccessfulOutcome)
218 {
219 NS_LOG_LOGIC("Recv X2 message: HANDOVER REQUEST ACK");
220
221 NrEpcX2HandoverRequestAckHeader x2HoReqAckHeader;
222 packet->RemoveHeader(x2HoReqAckHeader);
223
224 NS_LOG_INFO("X2 HandoverRequestAck header: " << x2HoReqAckHeader);
225
227 params.oldGnbUeX2apId = x2HoReqAckHeader.GetOldGnbUeX2apId();
228 params.newGnbUeX2apId = x2HoReqAckHeader.GetNewGnbUeX2apId();
229 params.sourceCellId = cellsInfo->m_localCellIds.at(0);
230 params.targetCellId = cellsInfo->m_remoteCellIds.at(0);
231 params.admittedBearers = x2HoReqAckHeader.GetAdmittedBearers();
232 params.notAdmittedBearers = x2HoReqAckHeader.GetNotAdmittedBearers();
233 params.rrcContext = packet;
234
235 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
236 NS_LOG_LOGIC("newGnbUeX2apId = " << params.newGnbUeX2apId);
237 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
238 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
239
241 }
242 else // messageType == NrEpcX2Header::UnsuccessfulOutcome
243 {
244 NS_LOG_LOGIC("Recv X2 message: HANDOVER PREPARATION FAILURE");
245
247 packet->RemoveHeader(x2HoPrepFailHeader);
248
249 NS_LOG_INFO("X2 HandoverPreparationFailure header: " << x2HoPrepFailHeader);
250
252 params.oldGnbUeX2apId = x2HoPrepFailHeader.GetOldGnbUeX2apId();
253 params.sourceCellId = cellsInfo->m_localCellIds.at(0);
254 params.targetCellId = cellsInfo->m_remoteCellIds.at(0);
255 params.cause = x2HoPrepFailHeader.GetCause();
256 params.criticalityDiagnostics = x2HoPrepFailHeader.GetCriticalityDiagnostics();
257
258 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
259 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
260 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
261 NS_LOG_LOGIC("cause = " << params.cause);
262 NS_LOG_LOGIC("criticalityDiagnostics = " << params.criticalityDiagnostics);
263
265 }
266 }
267 else if (procedureCode == NrEpcX2Header::LoadIndication)
268 {
269 if (messageType == NrEpcX2Header::InitiatingMessage)
270 {
271 NS_LOG_LOGIC("Recv X2 message: LOAD INFORMATION");
272
273 NrEpcX2LoadInformationHeader x2LoadInfoHeader;
274 packet->RemoveHeader(x2LoadInfoHeader);
275
276 NS_LOG_INFO("X2 LoadInformation header: " << x2LoadInfoHeader);
277
279 params.cellInformationList = x2LoadInfoHeader.GetCellInformationList();
280
281 NS_LOG_LOGIC("cellInformationList size = " << params.cellInformationList.size());
282
284 }
285 }
286 else if (procedureCode == NrEpcX2Header::SnStatusTransfer)
287 {
288 if (messageType == NrEpcX2Header::InitiatingMessage)
289 {
290 NS_LOG_LOGIC("Recv X2 message: SN STATUS TRANSFER");
291
292 NrEpcX2SnStatusTransferHeader x2SnStatusXferHeader;
293 packet->RemoveHeader(x2SnStatusXferHeader);
294
295 NS_LOG_INFO("X2 SnStatusTransfer header: " << x2SnStatusXferHeader);
296
298 params.oldGnbUeX2apId = x2SnStatusXferHeader.GetOldGnbUeX2apId();
299 params.newGnbUeX2apId = x2SnStatusXferHeader.GetNewGnbUeX2apId();
300 params.sourceCellId = cellsInfo->m_remoteCellIds.at(0);
301 params.targetCellId = cellsInfo->m_localCellIds.at(0);
303 x2SnStatusXferHeader.GetErabsSubjectToStatusTransferList();
304
305 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
306 NS_LOG_LOGIC("newGnbUeX2apId = " << params.newGnbUeX2apId);
307 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
308 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
309 NS_LOG_LOGIC("erabsList size = " << params.erabsSubjectToStatusTransferList.size());
310
312 }
313 }
314 else if (procedureCode == NrEpcX2Header::UeContextRelease)
315 {
316 if (messageType == NrEpcX2Header::InitiatingMessage)
317 {
318 NS_LOG_LOGIC("Recv X2 message: UE CONTEXT RELEASE");
319
320 NrEpcX2UeContextReleaseHeader x2UeCtxReleaseHeader;
321 packet->RemoveHeader(x2UeCtxReleaseHeader);
322
323 NS_LOG_INFO("X2 UeContextRelease header: " << x2UeCtxReleaseHeader);
324
326 params.oldGnbUeX2apId = x2UeCtxReleaseHeader.GetOldGnbUeX2apId();
327 params.newGnbUeX2apId = x2UeCtxReleaseHeader.GetNewGnbUeX2apId();
328
329 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
330 NS_LOG_LOGIC("newGnbUeX2apId = " << params.newGnbUeX2apId);
331
333 }
334 }
335 else if (procedureCode == NrEpcX2Header::ResourceStatusReporting)
336 {
337 if (messageType == NrEpcX2Header::InitiatingMessage)
338 {
339 NS_LOG_LOGIC("Recv X2 message: RESOURCE STATUS UPDATE");
340
341 NrEpcX2ResourceStatusUpdateHeader x2ResStatUpdHeader;
342 packet->RemoveHeader(x2ResStatUpdHeader);
343
344 NS_LOG_INFO("X2 ResourceStatusUpdate header: " << x2ResStatUpdHeader);
345
347 params.targetCellId = 0;
348 params.gnb1MeasurementId = x2ResStatUpdHeader.GetGnb1MeasurementId();
349 params.gnb2MeasurementId = x2ResStatUpdHeader.GetGnb2MeasurementId();
350 params.cellMeasurementResultList = x2ResStatUpdHeader.GetCellMeasurementResultList();
351
352 NS_LOG_LOGIC("gnb1MeasurementId = " << params.gnb1MeasurementId);
353 NS_LOG_LOGIC("gnb2MeasurementId = " << params.gnb2MeasurementId);
354 NS_LOG_LOGIC(
355 "cellMeasurementResultList size = " << params.cellMeasurementResultList.size());
356
358 }
359 }
360 else if (procedureCode == NrEpcX2Header::HandoverCancel)
361 {
362 if (messageType == NrEpcX2Header::SuccessfulOutcome)
363 {
364 NS_LOG_LOGIC("Recv X2 message: HANDOVER CANCEL");
365
366 NrEpcX2HandoverCancelHeader x2HoCancelHeader;
367 packet->RemoveHeader(x2HoCancelHeader);
368
369 NS_LOG_INFO("X2 HandoverCancel header: " << x2HoCancelHeader);
370
372 params.oldGnbUeX2apId = x2HoCancelHeader.GetOldGnbUeX2apId();
373 params.newGnbUeX2apId = x2HoCancelHeader.GetNewGnbUeX2apId();
374 params.sourceCellId = cellsInfo->m_localCellIds.at(0);
375 params.targetCellId = cellsInfo->m_remoteCellIds.at(0);
376 params.cause = x2HoCancelHeader.GetCause();
377
378 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
379 NS_LOG_LOGIC("newGnbUeX2apId = " << params.newGnbUeX2apId);
380 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
381 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
382 NS_LOG_LOGIC("cause = " << params.cause);
383
385 }
386 }
387 else
388 {
389 NS_ASSERT_MSG(false, "ProcedureCode NOT SUPPORTED!!!");
390 }
391}
392
393void
394NrEpcX2::RecvFromX2uSocket(Ptr<Socket> socket)
395{
396 NS_LOG_FUNCTION(this << socket);
397
398 NS_LOG_LOGIC("Recv UE DATA through X2-U interface from Socket");
399 Ptr<Packet> packet = socket->Recv();
400 NS_LOG_LOGIC("packetLen = " << packet->GetSize());
401
402 NS_ASSERT_MSG(m_x2InterfaceCellIds.find(socket) != m_x2InterfaceCellIds.end(),
403 "Missing infos of local and remote CellId");
404 Ptr<NrX2CellInfo> cellsInfo = m_x2InterfaceCellIds[socket];
405
406 NrGtpuHeader gtpu;
407 packet->RemoveHeader(gtpu);
408
409 NS_LOG_LOGIC("GTP-U header: " << gtpu);
410
412 params.sourceCellId = cellsInfo->m_remoteCellIds.at(0);
413 params.targetCellId = cellsInfo->m_localCellIds.at(0);
414 params.gtpTeid = gtpu.GetTeid();
415 params.ueData = packet;
416
417 m_x2SapUser->RecvUeData(params);
418}
419
420//
421// Implementation of the X2 SAP Provider
422//
423void
425{
426 NS_LOG_FUNCTION(this);
427
428 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
429 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
430 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
431 NS_LOG_LOGIC("mmeUeS1apId = " << params.mmeUeS1apId);
432
433 NS_ASSERT_MSG(m_x2InterfaceSockets.find(params.targetCellId) != m_x2InterfaceSockets.end(),
434 "Missing infos for targetCellId = " << params.targetCellId);
435 Ptr<NrX2IfaceInfo> socketInfo = m_x2InterfaceSockets[params.targetCellId];
436 Ptr<Socket> sourceSocket = socketInfo->m_localCtrlPlaneSocket;
437 Ipv4Address targetIpAddr = socketInfo->m_remoteIpAddr;
438
439 NS_LOG_LOGIC("sourceSocket = " << sourceSocket);
440 NS_LOG_LOGIC("targetIpAddr = " << targetIpAddr);
441
442 NS_LOG_INFO("Send X2 message: HANDOVER REQUEST");
443
444 // Build the X2 message
445 NrEpcX2HandoverRequestHeader x2HoReqHeader;
446 x2HoReqHeader.SetOldGnbUeX2apId(params.oldGnbUeX2apId);
447 x2HoReqHeader.SetCause(params.cause);
448 x2HoReqHeader.SetTargetCellId(params.targetCellId);
449 x2HoReqHeader.SetMmeUeS1apId(params.mmeUeS1apId);
452 x2HoReqHeader.SetBearers(params.bearers);
453
454 NrEpcX2Header x2Header;
455 x2Header.SetMessageType(NrEpcX2Header::InitiatingMessage);
456 x2Header.SetProcedureCode(NrEpcX2Header::HandoverPreparation);
457 x2Header.SetLengthOfIes(x2HoReqHeader.GetLengthOfIes());
458 x2Header.SetNumberOfIes(x2HoReqHeader.GetNumberOfIes());
459
460 NS_LOG_INFO("X2 header: " << x2Header);
461 NS_LOG_INFO("X2 HandoverRequest header: " << x2HoReqHeader);
462
463 // Build the X2 packet
464 Ptr<Packet> packet = (params.rrcContext) ? (params.rrcContext) : (Create<Packet>());
465 packet->AddHeader(x2HoReqHeader);
466 packet->AddHeader(x2Header);
467 NS_LOG_INFO("packetLen = " << packet->GetSize());
468
469 // Send the X2 message through the socket
470 sourceSocket->SendTo(packet, 0, InetSocketAddress(targetIpAddr, m_x2cUdpPort));
471}
472
473void
475{
476 NS_LOG_FUNCTION(this);
477
478 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
479 NS_LOG_LOGIC("newGnbUeX2apId = " << params.newGnbUeX2apId);
480 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
481 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
482
483 NS_ASSERT_MSG(m_x2InterfaceSockets.find(params.sourceCellId) != m_x2InterfaceSockets.end(),
484 "Socket infos not defined for sourceCellId = " << params.sourceCellId);
485
486 Ptr<Socket> localSocket = m_x2InterfaceSockets[params.sourceCellId]->m_localCtrlPlaneSocket;
487 Ipv4Address remoteIpAddr = m_x2InterfaceSockets[params.sourceCellId]->m_remoteIpAddr;
488
489 NS_LOG_LOGIC("localSocket = " << localSocket);
490 NS_LOG_LOGIC("remoteIpAddr = " << remoteIpAddr);
491
492 NS_LOG_INFO("Send X2 message: HANDOVER REQUEST ACK");
493
494 // Build the X2 message
496 x2HoAckHeader.SetOldGnbUeX2apId(params.oldGnbUeX2apId);
497 x2HoAckHeader.SetNewGnbUeX2apId(params.newGnbUeX2apId);
498 x2HoAckHeader.SetAdmittedBearers(params.admittedBearers);
499 x2HoAckHeader.SetNotAdmittedBearers(params.notAdmittedBearers);
500
501 NrEpcX2Header x2Header;
502 x2Header.SetMessageType(NrEpcX2Header::SuccessfulOutcome);
503 x2Header.SetProcedureCode(NrEpcX2Header::HandoverPreparation);
504 x2Header.SetLengthOfIes(x2HoAckHeader.GetLengthOfIes());
505 x2Header.SetNumberOfIes(x2HoAckHeader.GetNumberOfIes());
506
507 NS_LOG_INFO("X2 header: " << x2Header);
508 NS_LOG_INFO("X2 HandoverAck header: " << x2HoAckHeader);
509 NS_LOG_INFO("RRC context: " << params.rrcContext);
510
511 // Build the X2 packet
512 Ptr<Packet> packet = (params.rrcContext) ? (params.rrcContext) : (Create<Packet>());
513 packet->AddHeader(x2HoAckHeader);
514 packet->AddHeader(x2Header);
515 NS_LOG_INFO("packetLen = " << packet->GetSize());
516
517 // Send the X2 message through the socket
518 localSocket->SendTo(packet, 0, InetSocketAddress(remoteIpAddr, m_x2cUdpPort));
519}
520
521void
524{
525 NS_LOG_FUNCTION(this);
526
527 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
528 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
529 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
530 NS_LOG_LOGIC("cause = " << params.cause);
531 NS_LOG_LOGIC("criticalityDiagnostics = " << params.criticalityDiagnostics);
532
533 NS_ASSERT_MSG(m_x2InterfaceSockets.find(params.sourceCellId) != m_x2InterfaceSockets.end(),
534 "Socket infos not defined for sourceCellId = " << params.sourceCellId);
535
536 Ptr<Socket> localSocket = m_x2InterfaceSockets[params.sourceCellId]->m_localCtrlPlaneSocket;
537 Ipv4Address remoteIpAddr = m_x2InterfaceSockets[params.sourceCellId]->m_remoteIpAddr;
538
539 NS_LOG_LOGIC("localSocket = " << localSocket);
540 NS_LOG_LOGIC("remoteIpAddr = " << remoteIpAddr);
541
542 NS_LOG_INFO("Send X2 message: HANDOVER PREPARATION FAILURE");
543
544 // Build the X2 message
546 x2HoPrepFailHeader.SetOldGnbUeX2apId(params.oldGnbUeX2apId);
547 x2HoPrepFailHeader.SetCause(params.cause);
548 x2HoPrepFailHeader.SetCriticalityDiagnostics(params.criticalityDiagnostics);
549
550 NrEpcX2Header x2Header;
551 x2Header.SetMessageType(NrEpcX2Header::UnsuccessfulOutcome);
552 x2Header.SetProcedureCode(NrEpcX2Header::HandoverPreparation);
553 x2Header.SetLengthOfIes(x2HoPrepFailHeader.GetLengthOfIes());
554 x2Header.SetNumberOfIes(x2HoPrepFailHeader.GetNumberOfIes());
555
556 NS_LOG_INFO("X2 header: " << x2Header);
557 NS_LOG_INFO("X2 HandoverPrepFail header: " << x2HoPrepFailHeader);
558
559 // Build the X2 packet
560 Ptr<Packet> packet = Create<Packet>();
561 packet->AddHeader(x2HoPrepFailHeader);
562 packet->AddHeader(x2Header);
563 NS_LOG_INFO("packetLen = " << packet->GetSize());
564
565 // Send the X2 message through the socket
566 localSocket->SendTo(packet, 0, InetSocketAddress(remoteIpAddr, m_x2cUdpPort));
567}
568
569void
571{
572 NS_LOG_FUNCTION(this);
573
574 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
575 NS_LOG_LOGIC("newGnbUeX2apId = " << params.newGnbUeX2apId);
576 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
577 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
578 NS_LOG_LOGIC("erabsList size = " << params.erabsSubjectToStatusTransferList.size());
579
580 NS_ASSERT_MSG(m_x2InterfaceSockets.find(params.targetCellId) != m_x2InterfaceSockets.end(),
581 "Socket infos not defined for targetCellId = " << params.targetCellId);
582
583 Ptr<Socket> localSocket = m_x2InterfaceSockets[params.targetCellId]->m_localCtrlPlaneSocket;
584 Ipv4Address remoteIpAddr = m_x2InterfaceSockets[params.targetCellId]->m_remoteIpAddr;
585
586 NS_LOG_LOGIC("localSocket = " << localSocket);
587 NS_LOG_LOGIC("remoteIpAddr = " << remoteIpAddr);
588
589 NS_LOG_INFO("Send X2 message: SN STATUS TRANSFER");
590
591 // Build the X2 message
592 NrEpcX2SnStatusTransferHeader x2SnStatusXferHeader;
593 x2SnStatusXferHeader.SetOldGnbUeX2apId(params.oldGnbUeX2apId);
594 x2SnStatusXferHeader.SetNewGnbUeX2apId(params.newGnbUeX2apId);
595 x2SnStatusXferHeader.SetErabsSubjectToStatusTransferList(
597
598 NrEpcX2Header x2Header;
599 x2Header.SetMessageType(NrEpcX2Header::InitiatingMessage);
600 x2Header.SetProcedureCode(NrEpcX2Header::SnStatusTransfer);
601 x2Header.SetLengthOfIes(x2SnStatusXferHeader.GetLengthOfIes());
602 x2Header.SetNumberOfIes(x2SnStatusXferHeader.GetNumberOfIes());
603
604 NS_LOG_INFO("X2 header: " << x2Header);
605 NS_LOG_INFO("X2 SnStatusTransfer header: " << x2SnStatusXferHeader);
606
607 // Build the X2 packet
608 Ptr<Packet> packet = Create<Packet>();
609 packet->AddHeader(x2SnStatusXferHeader);
610 packet->AddHeader(x2Header);
611 NS_LOG_INFO("packetLen = " << packet->GetSize());
612
613 // Send the X2 message through the socket
614 localSocket->SendTo(packet, 0, InetSocketAddress(remoteIpAddr, m_x2cUdpPort));
615}
616
617void
619{
620 NS_LOG_FUNCTION(this);
621
622 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
623 NS_LOG_LOGIC("newGnbUeX2apId = " << params.newGnbUeX2apId);
624 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
625
626 NS_ASSERT_MSG(m_x2InterfaceSockets.find(params.sourceCellId) != m_x2InterfaceSockets.end(),
627 "Socket infos not defined for sourceCellId = " << params.sourceCellId);
628
629 Ptr<Socket> localSocket = m_x2InterfaceSockets[params.sourceCellId]->m_localCtrlPlaneSocket;
630 Ipv4Address remoteIpAddr = m_x2InterfaceSockets[params.sourceCellId]->m_remoteIpAddr;
631
632 NS_LOG_LOGIC("localSocket = " << localSocket);
633 NS_LOG_LOGIC("remoteIpAddr = " << remoteIpAddr);
634
635 NS_LOG_INFO("Send X2 message: UE CONTEXT RELEASE");
636
637 // Build the X2 message
638 NrEpcX2UeContextReleaseHeader x2UeCtxReleaseHeader;
639 x2UeCtxReleaseHeader.SetOldGnbUeX2apId(params.oldGnbUeX2apId);
640 x2UeCtxReleaseHeader.SetNewGnbUeX2apId(params.newGnbUeX2apId);
641
642 NrEpcX2Header x2Header;
643 x2Header.SetMessageType(NrEpcX2Header::InitiatingMessage);
644 x2Header.SetProcedureCode(NrEpcX2Header::UeContextRelease);
645 x2Header.SetLengthOfIes(x2UeCtxReleaseHeader.GetLengthOfIes());
646 x2Header.SetNumberOfIes(x2UeCtxReleaseHeader.GetNumberOfIes());
647
648 NS_LOG_INFO("X2 header: " << x2Header);
649 NS_LOG_INFO("X2 UeContextRelease header: " << x2UeCtxReleaseHeader);
650
651 // Build the X2 packet
652 Ptr<Packet> packet = Create<Packet>();
653 packet->AddHeader(x2UeCtxReleaseHeader);
654 packet->AddHeader(x2Header);
655 NS_LOG_INFO("packetLen = " << packet->GetSize());
656
657 // Send the X2 message through the socket
658 localSocket->SendTo(packet, 0, InetSocketAddress(remoteIpAddr, m_x2cUdpPort));
659}
660
661void
663{
664 NS_LOG_FUNCTION(this);
665
666 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
667 NS_LOG_LOGIC("cellInformationList size = " << params.cellInformationList.size());
668
669 NS_ASSERT_MSG(m_x2InterfaceSockets.find(params.targetCellId) != m_x2InterfaceSockets.end(),
670 "Missing infos for targetCellId = " << params.targetCellId);
671 Ptr<NrX2IfaceInfo> socketInfo = m_x2InterfaceSockets[params.targetCellId];
672 Ptr<Socket> sourceSocket = socketInfo->m_localCtrlPlaneSocket;
673 Ipv4Address targetIpAddr = socketInfo->m_remoteIpAddr;
674
675 NS_LOG_LOGIC("sourceSocket = " << sourceSocket);
676 NS_LOG_LOGIC("targetIpAddr = " << targetIpAddr);
677
678 NS_LOG_INFO("Send X2 message: LOAD INFORMATION");
679
680 // Build the X2 message
681 NrEpcX2LoadInformationHeader x2LoadInfoHeader;
682 x2LoadInfoHeader.SetCellInformationList(params.cellInformationList);
683
684 NrEpcX2Header x2Header;
685 x2Header.SetMessageType(NrEpcX2Header::InitiatingMessage);
686 x2Header.SetProcedureCode(NrEpcX2Header::LoadIndication);
687 x2Header.SetLengthOfIes(x2LoadInfoHeader.GetLengthOfIes());
688 x2Header.SetNumberOfIes(x2LoadInfoHeader.GetNumberOfIes());
689
690 NS_LOG_INFO("X2 header: " << x2Header);
691 NS_LOG_INFO("X2 LoadInformation header: " << x2LoadInfoHeader);
692
693 // Build the X2 packet
694 Ptr<Packet> packet = Create<Packet>();
695 packet->AddHeader(x2LoadInfoHeader);
696 packet->AddHeader(x2Header);
697 NS_LOG_INFO("packetLen = " << packet->GetSize());
698
699 // Send the X2 message through the socket
700 sourceSocket->SendTo(packet, 0, InetSocketAddress(targetIpAddr, m_x2cUdpPort));
701}
702
703void
705{
706 NS_LOG_FUNCTION(this);
707
708 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
709 NS_LOG_LOGIC("gnb1MeasurementId = " << params.gnb1MeasurementId);
710 NS_LOG_LOGIC("gnb2MeasurementId = " << params.gnb2MeasurementId);
711 NS_LOG_LOGIC("cellMeasurementResultList size = " << params.cellMeasurementResultList.size());
712
713 NS_ASSERT_MSG(m_x2InterfaceSockets.find(params.targetCellId) != m_x2InterfaceSockets.end(),
714 "Missing infos for targetCellId = " << params.targetCellId);
715 Ptr<NrX2IfaceInfo> socketInfo = m_x2InterfaceSockets[params.targetCellId];
716 Ptr<Socket> sourceSocket = socketInfo->m_localCtrlPlaneSocket;
717 Ipv4Address targetIpAddr = socketInfo->m_remoteIpAddr;
718
719 NS_LOG_LOGIC("sourceSocket = " << sourceSocket);
720 NS_LOG_LOGIC("targetIpAddr = " << targetIpAddr);
721
722 NS_LOG_INFO("Send X2 message: RESOURCE STATUS UPDATE");
723
724 // Build the X2 message
725 NrEpcX2ResourceStatusUpdateHeader x2ResourceStatUpdHeader;
726 x2ResourceStatUpdHeader.SetGnb1MeasurementId(params.gnb1MeasurementId);
727 x2ResourceStatUpdHeader.SetGnb2MeasurementId(params.gnb2MeasurementId);
728 x2ResourceStatUpdHeader.SetCellMeasurementResultList(params.cellMeasurementResultList);
729
730 NrEpcX2Header x2Header;
731 x2Header.SetMessageType(NrEpcX2Header::InitiatingMessage);
732 x2Header.SetProcedureCode(NrEpcX2Header::ResourceStatusReporting);
733 x2Header.SetLengthOfIes(x2ResourceStatUpdHeader.GetLengthOfIes());
734 x2Header.SetNumberOfIes(x2ResourceStatUpdHeader.GetNumberOfIes());
735
736 NS_LOG_INFO("X2 header: " << x2Header);
737 NS_LOG_INFO("X2 ResourceStatusUpdate header: " << x2ResourceStatUpdHeader);
738
739 // Build the X2 packet
740 Ptr<Packet> packet = Create<Packet>();
741 packet->AddHeader(x2ResourceStatUpdHeader);
742 packet->AddHeader(x2Header);
743 NS_LOG_INFO("packetLen = " << packet->GetSize());
744
745 // Send the X2 message through the socket
746 sourceSocket->SendTo(packet, 0, InetSocketAddress(targetIpAddr, m_x2cUdpPort));
747}
748
749void
751{
752 NS_LOG_FUNCTION(this);
753
754 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
755 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
756 NS_LOG_LOGIC("gtpTeid = " << params.gtpTeid);
757
758 NS_ASSERT_MSG(m_x2InterfaceSockets.find(params.targetCellId) != m_x2InterfaceSockets.end(),
759 "Missing infos for targetCellId = " << params.targetCellId);
760 Ptr<NrX2IfaceInfo> socketInfo = m_x2InterfaceSockets[params.targetCellId];
761 Ptr<Socket> sourceSocket = socketInfo->m_localUserPlaneSocket;
762 Ipv4Address targetIpAddr = socketInfo->m_remoteIpAddr;
763
764 NS_LOG_LOGIC("sourceSocket = " << sourceSocket);
765 NS_LOG_LOGIC("targetIpAddr = " << targetIpAddr);
766
767 NrGtpuHeader gtpu;
768 gtpu.SetTeid(params.gtpTeid);
769 gtpu.SetLength(params.ueData->GetSize() + gtpu.GetSerializedSize() -
770 8);
771 NS_LOG_INFO("GTP-U header: " << gtpu);
772
773 Ptr<Packet> packet = params.ueData;
774 packet->AddHeader(gtpu);
775
776 NS_LOG_INFO("Forward UE DATA through X2 interface");
777 sourceSocket->SendTo(packet, 0, InetSocketAddress(targetIpAddr, m_x2uUdpPort));
778}
779
780void
782{
783 NS_LOG_FUNCTION(this);
784
785 NS_LOG_LOGIC("oldGnbUeX2apId = " << params.oldGnbUeX2apId);
786 NS_LOG_LOGIC("newGnbUeX2apId = " << params.newGnbUeX2apId);
787 NS_LOG_LOGIC("sourceCellId = " << params.sourceCellId);
788 NS_LOG_LOGIC("targetCellId = " << params.targetCellId);
789
790 NS_ASSERT_MSG(m_x2InterfaceSockets.find(params.targetCellId) != m_x2InterfaceSockets.end(),
791 "Socket infos not defined for targetCellId = " << params.targetCellId);
792
793 Ptr<Socket> localSocket = m_x2InterfaceSockets[params.targetCellId]->m_localCtrlPlaneSocket;
794 Ipv4Address remoteIpAddr = m_x2InterfaceSockets[params.targetCellId]->m_remoteIpAddr;
795
796 NS_LOG_LOGIC("localSocket = " << localSocket);
797 NS_LOG_LOGIC("remoteIpAddr = " << remoteIpAddr);
798
799 NS_LOG_INFO("Send X2 message: HANDOVER CANCEL");
800
801 // Build the X2 message
802 NrEpcX2HandoverCancelHeader x2HandoverCancelHeader;
803 x2HandoverCancelHeader.SetOldGnbUeX2apId(params.oldGnbUeX2apId);
804 x2HandoverCancelHeader.SetNewGnbUeX2apId(params.newGnbUeX2apId);
805 x2HandoverCancelHeader.SetCause(params.cause);
806
807 NrEpcX2Header x2Header;
808 x2Header.SetMessageType(NrEpcX2Header::SuccessfulOutcome);
809 x2Header.SetProcedureCode(NrEpcX2Header::HandoverCancel);
810 x2Header.SetLengthOfIes(x2HandoverCancelHeader.GetLengthOfIes());
811 x2Header.SetNumberOfIes(x2HandoverCancelHeader.GetNumberOfIes());
812
813 NS_LOG_INFO("X2 header: " << x2Header);
814 NS_LOG_INFO("X2 UeContextRelease header: " << x2HandoverCancelHeader);
815
816 // Build the X2 packet
817 Ptr<Packet> packet = Create<Packet>();
818 packet->AddHeader(x2HandoverCancelHeader);
819 packet->AddHeader(x2Header);
820 NS_LOG_INFO("packetLen = " << packet->GetSize());
821
822 // Send the X2 message through the socket
823 localSocket->SendTo(packet, 0, InetSocketAddress(remoteIpAddr, m_x2cUdpPort));
824}
825
826} // namespace ns3
uint32_t GetLengthOfIes() const
Get length of IEs function.
void SetNewGnbUeX2apId(uint16_t x2apId)
Set new gNB UE X2 AP ID function.
uint32_t GetNumberOfIes() const
Get number of IEs function.
void SetOldGnbUeX2apId(uint16_t x2apId)
Set old gNB UE X2 AP ID function.
uint16_t GetNewGnbUeX2apId() const
Get new gNB UE X2 AP ID function.
void SetCause(uint16_t cause)
Set cause function.
uint16_t GetCause() const
Get cause function.
uint16_t GetOldGnbUeX2apId() const
Get old gNB UE X2 AP ID function.
void SetCriticalityDiagnostics(uint16_t criticalityDiagnostics)
std::vector< NrEpcX2Sap::ErabAdmittedItem > GetAdmittedBearers() const
void SetNotAdmittedBearers(std::vector< NrEpcX2Sap::ErabNotAdmittedItem > bearers)
void SetAdmittedBearers(std::vector< NrEpcX2Sap::ErabAdmittedItem > bearers)
std::vector< NrEpcX2Sap::ErabNotAdmittedItem > GetNotAdmittedBearers() const
void SetTargetCellId(uint16_t targetCellId)
void SetUeAggregateMaxBitRateDownlink(uint64_t bitRate)
void SetOldGnbUeX2apId(uint16_t x2apId)
void SetMmeUeS1apId(uint32_t mmeUeS1apId)
void SetBearers(std::vector< NrEpcX2Sap::ErabToBeSetupItem > bearers)
void SetUeAggregateMaxBitRateUplink(uint64_t bitRate)
uint64_t GetUeAggregateMaxBitRateDownlink() const
std::vector< NrEpcX2Sap::ErabToBeSetupItem > GetBearers() const
uint8_t GetProcedureCode() const
void SetLengthOfIes(uint32_t lengthOfIes)
void SetProcedureCode(uint8_t procedureCode)
void SetNumberOfIes(uint32_t numberOfIes)
uint8_t GetMessageType() const
void SetMessageType(uint8_t messageType)
virtual void DoSendResourceStatusUpdate(NrEpcX2SapProvider::ResourceStatusUpdateParams params)
Definition nr-epc-x2.cc:704
NrEpcX2SapProvider * m_x2SapProvider
X2 SAP provider.
Definition nr-epc-x2.h:198
void AddX2Interface(uint16_t gnb1CellId, Ipv4Address gnb1X2Address, std::vector< uint16_t > gnb2CellIds, Ipv4Address gnb2X2Address)
Definition nr-epc-x2.cc:118
virtual void DoSendUeContextRelease(NrEpcX2SapProvider::UeContextReleaseParams params)
Definition nr-epc-x2.cc:618
virtual void DoSendLoadInformation(NrEpcX2SapProvider::LoadInformationParams params)
Definition nr-epc-x2.cc:662
void RecvFromX2uSocket(Ptr< Socket > socket)
Definition nr-epc-x2.cc:394
~NrEpcX2() override
Definition nr-epc-x2.cc:81
NrEpcX2SapProvider * GetEpcX2SapProvider()
Definition nr-epc-x2.cc:111
friend class NrEpcX2SpecificEpcX2SapProvider< NrEpcX2 >
allow NrEpcX2SpecificEpcX2SapProvider<NrEpcX2> class friend access
Definition nr-epc-x2.h:88
virtual void DoSendUeData(NrEpcX2SapProvider::UeDataParams params)
Definition nr-epc-x2.cc:750
virtual void DoSendHandoverRequestAck(NrEpcX2SapProvider::HandoverRequestAckParams params)
Definition nr-epc-x2.cc:474
void SetEpcX2SapUser(NrEpcX2SapUser *s)
Definition nr-epc-x2.cc:104
virtual void DoSendHandoverPreparationFailure(NrEpcX2SapProvider::HandoverPreparationFailureParams params)
Definition nr-epc-x2.cc:522
virtual void DoSendHandoverCancel(NrEpcX2SapProvider::HandoverCancelParams params)
Send Handover Cancel function.
Definition nr-epc-x2.cc:781
virtual void DoSendSnStatusTransfer(NrEpcX2SapProvider::SnStatusTransferParams params)
Definition nr-epc-x2.cc:570
virtual void DoSendHandoverRequest(NrEpcX2SapProvider::HandoverRequestParams params)
Definition nr-epc-x2.cc:424
void RecvFromX2cSocket(Ptr< Socket > socket)
Definition nr-epc-x2.cc:167
static TypeId GetTypeId()
Get the type ID.
Definition nr-epc-x2.cc:97
NrEpcX2SapUser * m_x2SapUser
X2 SAP user.
Definition nr-epc-x2.h:197
std::vector< NrEpcX2Sap::CellInformationItem > GetCellInformationList() const
void SetCellInformationList(std::vector< NrEpcX2Sap::CellInformationItem > cellInformationList)
void SetGnb2MeasurementId(uint16_t gnb2MeasurementId)
void SetCellMeasurementResultList(std::vector< NrEpcX2Sap::CellMeasurementResultItem > cellMeasurementResultList)
std::vector< NrEpcX2Sap::CellMeasurementResultItem > GetCellMeasurementResultList() const
void SetGnb1MeasurementId(uint16_t gnb1MeasurementId)
virtual void RecvUeData(UeDataParams params)=0
virtual void RecvUeContextRelease(UeContextReleaseParams params)=0
virtual void RecvResourceStatusUpdate(ResourceStatusUpdateParams params)=0
virtual void RecvHandoverCancel(HandoverCancelParams params)=0
virtual void RecvHandoverRequestAck(HandoverRequestAckParams params)=0
virtual void RecvLoadInformation(LoadInformationParams params)=0
virtual void RecvSnStatusTransfer(SnStatusTransferParams params)=0
virtual void RecvHandoverRequest(HandoverRequestParams params)=0
virtual void RecvHandoverPreparationFailure(HandoverPreparationFailureParams params)=0
std::vector< NrEpcX2Sap::ErabsSubjectToStatusTransferItem > GetErabsSubjectToStatusTransferList() const
void SetErabsSubjectToStatusTransferList(std::vector< NrEpcX2Sap::ErabsSubjectToStatusTransferItem > erabs)
void SetLength(uint16_t length)
void SetTeid(uint32_t teid)
uint32_t GetTeid() const
NrX2CellInfo(std::vector< uint16_t > localCellIds, std::vector< uint16_t > remoteCellIds)
Definition nr-epc-x2.cc:49
std::vector< uint16_t > m_remoteCellIds
remote cell IDs
Definition nr-epc-x2.h:77
std::vector< uint16_t > m_localCellIds
local cell IDs
Definition nr-epc-x2.h:76
NrX2CellInfo & operator=(const NrX2CellInfo &value)
Definition nr-epc-x2.cc:60
NrX2IfaceInfo & operator=(const NrX2IfaceInfo &value)
Definition nr-epc-x2.cc:38
Ipv4Address m_remoteIpAddr
remote IP address
Definition nr-epc-x2.h:48
Ptr< Socket > m_localCtrlPlaneSocket
local control plane socket
Definition nr-epc-x2.h:49
Ptr< Socket > m_localUserPlaneSocket
local user plane socket
Definition nr-epc-x2.h:50
NrX2IfaceInfo(Ipv4Address remoteIpAddr, Ptr< Socket > localCtrlPlaneSocket, Ptr< Socket > localUserPlaneSocket)
Definition nr-epc-x2.cc:22
Parameters of the HANDOVER CANCEL message.
uint16_t oldGnbUeX2apId
old gNB UE X2 AP ID
uint16_t newGnbUeX2apId
new gNB UE X2 AP ID
Parameters of the HANDOVER PREPARATION FAILURE message.
uint16_t criticalityDiagnostics
criticality diagnostics
Parameters of the HANDOVER REQUEST ACKNOWLEDGE message.
std::vector< ErabNotAdmittedItem > notAdmittedBearers
not admitted bearers
uint16_t newGnbUeX2apId
new gNB UE X2 AP ID
uint16_t oldGnbUeX2apId
old gNB UE X2 AP ID
std::vector< ErabAdmittedItem > admittedBearers
admitted bearers
Parameters of the HANDOVER REQUEST message.
uint64_t ueAggregateMaxBitRateDownlink
UE aggregate max bit rate downlink.
uint32_t mmeUeS1apId
MME UE S1 AP ID.
std::vector< ErabToBeSetupItem > bearers
bearers
Ptr< Packet > rrcContext
RRC context.
uint64_t ueAggregateMaxBitRateUplink
UE aggregate max bit rate uplink.
uint16_t oldGnbUeX2apId
old gNB UE X2 AP ID
Parameters of the LOAD INFORMATION message.
std::vector< CellInformationItem > cellInformationList
cell information list
Parameters of the RESOURCE STATUS UPDATE message.
std::vector< CellMeasurementResultItem > cellMeasurementResultList
cell measurement result list
uint16_t gnb1MeasurementId
gNB1 measurement ID
uint16_t gnb2MeasurementId
gNB2 measurement ID
Parameters of the SN STATUS TRANSFER message.
std::vector< ErabsSubjectToStatusTransferItem > erabsSubjectToStatusTransferList
ERABs subject to status transfer list.
uint16_t oldGnbUeX2apId
old gNB UE X2 AP ID
uint16_t newGnbUeX2apId
new gNB UE X2 AP ID
Parameters of the UE CONTEXT RELEASE message.
uint16_t oldGnbUeX2apId
old gNB UE X2 AP ID
uint16_t newGnbUeX2apId
new gNB UE X2 AP ID
Parameters of the UE DATA primitive.
uint16_t targetCellId
target cell ID
uint16_t sourceCellId
source cell ID
Ptr< Packet > ueData
UE data.