A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
epc-x2.cc
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Manuel Requena <manuel.requena@cttc.es>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/inet-socket-address.h"
23 #include "ns3/packet.h"
24 #include "ns3/node.h"
25 #include "ns3/epc-gtpu-header.h"
26 
27 #include "ns3/epc-x2-header.h"
28 #include "ns3/epc-x2.h"
29 
30 NS_LOG_COMPONENT_DEFINE ("EpcX2");
31 
32 namespace ns3 {
33 
34 
35 X2IfaceInfo::X2IfaceInfo (Ipv4Address remoteIpAddr, Ptr<Socket> localCtrlPlaneSocket, Ptr<Socket> localUserPlaneSocket)
36 {
37  m_remoteIpAddr = remoteIpAddr;
38  m_localCtrlPlaneSocket = localCtrlPlaneSocket;
39  m_localUserPlaneSocket = localUserPlaneSocket;
40 }
41 
42 X2IfaceInfo::~X2IfaceInfo (void)
43 {
44  m_localCtrlPlaneSocket = 0;
45  m_localUserPlaneSocket = 0;
46 }
47 
48 X2IfaceInfo&
49 X2IfaceInfo::operator= (const X2IfaceInfo& value)
50 {
51  NS_LOG_FUNCTION (this);
52  m_remoteIpAddr = value.m_remoteIpAddr;
53  m_localCtrlPlaneSocket = value.m_localCtrlPlaneSocket;
54  m_localUserPlaneSocket = value.m_localUserPlaneSocket;
55  return *this;
56 }
57 
59 
60 X2CellInfo::X2CellInfo (uint16_t localCellId, uint16_t remoteCellId)
61 {
62  m_localCellId = localCellId;
63  m_remoteCellId = remoteCellId;
64 }
65 
66 X2CellInfo::~X2CellInfo (void)
67 {
68  m_localCellId = 0;
69  m_remoteCellId = 0;
70 }
71 
72 X2CellInfo&
73 X2CellInfo::operator= (const X2CellInfo& value)
74 {
75  NS_LOG_FUNCTION (this);
76  m_localCellId = value.m_localCellId;
77  m_remoteCellId = value.m_remoteCellId;
78  return *this;
79 }
80 
82 
83 NS_OBJECT_ENSURE_REGISTERED (EpcX2);
84 
86  : m_x2cUdpPort (4444),
87  m_x2uUdpPort (2152)
88 {
89  NS_LOG_FUNCTION (this);
90 
91  m_x2SapProvider = new EpcX2SpecificEpcX2SapProvider<EpcX2> (this);
92 }
93 
95 {
96  NS_LOG_FUNCTION (this);
97 }
98 
99 void
101 {
102  NS_LOG_FUNCTION (this);
103 
104  m_x2InterfaceSockets.clear ();
105  m_x2InterfaceCellIds.clear ();
106  delete m_x2SapProvider;
107 }
108 
109 TypeId
110 EpcX2::GetTypeId (void)
111 {
112  static TypeId tid = TypeId ("ns3::EpcX2")
113  .SetParent<Object> ();
114  return tid;
115 }
116 
117 void
119 {
120  NS_LOG_FUNCTION (this << s);
121  m_x2SapUser = s;
122 }
123 
126 {
127  NS_LOG_FUNCTION (this);
128  return m_x2SapProvider;
129 }
130 
131 
132 void
133 EpcX2::AddX2Interface (uint16_t localCellId, Ipv4Address localX2Address, uint16_t remoteCellId, Ipv4Address remoteX2Address)
134 {
135  NS_LOG_FUNCTION (this << localCellId << localX2Address << remoteCellId << remoteX2Address);
136 
137  int retval;
138 
139  // Get local eNB where this X2 entity belongs to
140  Ptr<Node> localEnb = GetObject<Node> ();
141 
142  // Create X2-C socket for the local eNB
143  Ptr<Socket> localX2cSocket = Socket::CreateSocket (localEnb, TypeId::LookupByName ("ns3::UdpSocketFactory"));
144  retval = localX2cSocket->Bind (InetSocketAddress (localX2Address, m_x2cUdpPort));
145  NS_ASSERT (retval == 0);
146  localX2cSocket->SetRecvCallback (MakeCallback (&EpcX2::RecvFromX2cSocket, this));
147 
148  // Create X2-U socket for the local eNB
149  Ptr<Socket> localX2uSocket = Socket::CreateSocket (localEnb, TypeId::LookupByName ("ns3::UdpSocketFactory"));
150  retval = localX2uSocket->Bind (InetSocketAddress (localX2Address, m_x2uUdpPort));
151  NS_ASSERT (retval == 0);
152  localX2uSocket->SetRecvCallback (MakeCallback (&EpcX2::RecvFromX2uSocket, this));
153 
154 
155  NS_ASSERT_MSG (m_x2InterfaceSockets.find (remoteCellId) == m_x2InterfaceSockets.end (),
156  "Mapping for remoteCellId = " << remoteCellId << " is already known");
157  m_x2InterfaceSockets [remoteCellId] = Create<X2IfaceInfo> (remoteX2Address, localX2cSocket, localX2uSocket);
158 
159  NS_ASSERT_MSG (m_x2InterfaceCellIds.find (localX2cSocket) == m_x2InterfaceCellIds.end (),
160  "Mapping for control plane localSocket = " << localX2cSocket << " is already known");
161  m_x2InterfaceCellIds [localX2cSocket] = Create<X2CellInfo> (localCellId, remoteCellId);
162 
163  NS_ASSERT_MSG (m_x2InterfaceCellIds.find (localX2uSocket) == m_x2InterfaceCellIds.end (),
164  "Mapping for data plane localSocket = " << localX2uSocket << " is already known");
165  m_x2InterfaceCellIds [localX2uSocket] = Create<X2CellInfo> (localCellId, remoteCellId);
166 }
167 
168 
169 void
171 {
172  NS_LOG_FUNCTION (this << socket);
173 
174  NS_LOG_LOGIC ("Recv X2 message: from Socket");
175  Ptr<Packet> packet = socket->Recv ();
176  NS_LOG_LOGIC ("packetLen = " << packet->GetSize ());
177 
179  "Missing infos of local and remote CellId");
180  Ptr<X2CellInfo> cellsInfo = m_x2InterfaceCellIds [socket];
181 
182  EpcX2Header x2Header;
183  packet->RemoveHeader (x2Header);
184 
185  NS_LOG_LOGIC ("X2 header: " << x2Header);
186 
187  uint8_t messageType = x2Header.GetMessageType ();
188  uint8_t procedureCode = x2Header.GetProcedureCode ();
189 
190  if (procedureCode == EpcX2Header::HandoverPreparation)
191  {
192  if (messageType == EpcX2Header::InitiatingMessage)
193  {
194  NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST");
195 
196  EpcX2HandoverRequestHeader x2HoReqHeader;
197  packet->RemoveHeader (x2HoReqHeader);
198 
199  NS_LOG_INFO ("X2 HandoverRequest header: " << x2HoReqHeader);
200 
202  params.oldEnbUeX2apId = x2HoReqHeader.GetOldEnbUeX2apId ();
203  params.cause = x2HoReqHeader.GetCause ();
204  params.sourceCellId = cellsInfo->m_remoteCellId;
205  params.targetCellId = x2HoReqHeader.GetTargetCellId ();
206  params.mmeUeS1apId = x2HoReqHeader.GetMmeUeS1apId ();
207  params.ueAggregateMaxBitRateDownlink = x2HoReqHeader.GetUeAggregateMaxBitRateDownlink ();
208  params.ueAggregateMaxBitRateUplink = x2HoReqHeader.GetUeAggregateMaxBitRateUplink ();
209  params.bearers = x2HoReqHeader.GetBearers ();
210  params.rrcContext = packet;
211 
212  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
213  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
214  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
215  NS_LOG_LOGIC ("mmeUeS1apId = " << params.mmeUeS1apId);
216  NS_LOG_LOGIC ("cellsInfo->m_localCellId = " << cellsInfo->m_localCellId);
217  NS_ASSERT_MSG (params.targetCellId == cellsInfo->m_localCellId,
218  "TargetCellId mismatches with localCellId");
219 
220  m_x2SapUser->RecvHandoverRequest (params);
221  }
222  else if (messageType == EpcX2Header::SuccessfulOutcome)
223  {
224  NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST ACK");
225 
226  EpcX2HandoverRequestAckHeader x2HoReqAckHeader;
227  packet->RemoveHeader (x2HoReqAckHeader);
228 
229  NS_LOG_INFO ("X2 HandoverRequestAck header: " << x2HoReqAckHeader);
230 
232  params.oldEnbUeX2apId = x2HoReqAckHeader.GetOldEnbUeX2apId ();
233  params.newEnbUeX2apId = x2HoReqAckHeader.GetNewEnbUeX2apId ();
234  params.sourceCellId = cellsInfo->m_localCellId;
235  params.targetCellId = cellsInfo->m_remoteCellId;
236  params.admittedBearers = x2HoReqAckHeader.GetAdmittedBearers ();
237  params.notAdmittedBearers = x2HoReqAckHeader.GetNotAdmittedBearers ();
238  params.rrcContext = packet;
239 
240  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
241  NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
242  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
243  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
244 
245  m_x2SapUser->RecvHandoverRequestAck (params);
246  }
247  else // messageType == EpcX2Header::UnsuccessfulOutcome
248  {
249  NS_LOG_LOGIC ("Recv X2 message: HANDOVER PREPARATION FAILURE");
250 
251  EpcX2HandoverPreparationFailureHeader x2HoPrepFailHeader;
252  packet->RemoveHeader (x2HoPrepFailHeader);
253 
254  NS_LOG_INFO ("X2 HandoverPreparationFailure header: " << x2HoPrepFailHeader);
255 
257  params.oldEnbUeX2apId = x2HoPrepFailHeader.GetOldEnbUeX2apId ();
258  params.sourceCellId = cellsInfo->m_localCellId;
259  params.targetCellId = cellsInfo->m_remoteCellId;
260  params.cause = x2HoPrepFailHeader.GetCause ();
261  params.criticalityDiagnostics = x2HoPrepFailHeader.GetCriticalityDiagnostics ();
262 
263  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
264  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
265  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
266  NS_LOG_LOGIC ("cause = " << params.cause);
267  NS_LOG_LOGIC ("criticalityDiagnostics = " << params.criticalityDiagnostics);
268 
269  m_x2SapUser->RecvHandoverPreparationFailure (params);
270  }
271  }
272  else if (procedureCode == EpcX2Header::LoadIndication)
273  {
274  if (messageType == EpcX2Header::InitiatingMessage)
275  {
276  NS_LOG_LOGIC ("Recv X2 message: LOAD INFORMATION");
277 
278  EpcX2LoadInformationHeader x2LoadInfoHeader;
279  packet->RemoveHeader (x2LoadInfoHeader);
280 
281  NS_LOG_INFO ("X2 LoadInformation header: " << x2LoadInfoHeader);
282 
284  params.cellInformationList = x2LoadInfoHeader.GetCellInformationList ();
285 
286  NS_LOG_LOGIC ("cellInformationList size = " << params.cellInformationList.size ());
287 
288  m_x2SapUser->RecvLoadInformation (params);
289  }
290  }
291  else if (procedureCode == EpcX2Header::SnStatusTransfer)
292  {
293  if (messageType == EpcX2Header::InitiatingMessage)
294  {
295  NS_LOG_LOGIC ("Recv X2 message: SN STATUS TRANSFER");
296 
297  EpcX2SnStatusTransferHeader x2SnStatusXferHeader;
298  packet->RemoveHeader (x2SnStatusXferHeader);
299 
300  NS_LOG_INFO ("X2 SnStatusTransfer header: " << x2SnStatusXferHeader);
301 
303  params.oldEnbUeX2apId = x2SnStatusXferHeader.GetOldEnbUeX2apId ();
304  params.newEnbUeX2apId = x2SnStatusXferHeader.GetNewEnbUeX2apId ();
305  params.sourceCellId = cellsInfo->m_remoteCellId;
306  params.targetCellId = cellsInfo->m_localCellId;
307  params.erabsSubjectToStatusTransferList = x2SnStatusXferHeader.GetErabsSubjectToStatusTransferList ();
308 
309  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
310  NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
311  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
312  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
313  NS_LOG_LOGIC ("erabsList size = " << params.erabsSubjectToStatusTransferList.size ());
314 
315  m_x2SapUser->RecvSnStatusTransfer (params);
316  }
317  }
318  else if (procedureCode == EpcX2Header::UeContextRelease)
319  {
320  if (messageType == EpcX2Header::InitiatingMessage)
321  {
322  NS_LOG_LOGIC ("Recv X2 message: UE CONTEXT RELEASE");
323 
324  EpcX2UeContextReleaseHeader x2UeCtxReleaseHeader;
325  packet->RemoveHeader (x2UeCtxReleaseHeader);
326 
327  NS_LOG_INFO ("X2 UeContextRelease header: " << x2UeCtxReleaseHeader);
328 
330  params.oldEnbUeX2apId = x2UeCtxReleaseHeader.GetOldEnbUeX2apId ();
331  params.newEnbUeX2apId = x2UeCtxReleaseHeader.GetNewEnbUeX2apId ();
332 
333  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
334  NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
335 
336  m_x2SapUser->RecvUeContextRelease (params);
337  }
338  }
339  else if (procedureCode == EpcX2Header::ResourceStatusReporting)
340  {
341  if (messageType == EpcX2Header::InitiatingMessage)
342  {
343  NS_LOG_LOGIC ("Recv X2 message: RESOURCE STATUS UPDATE");
344 
345  EpcX2ResourceStatusUpdateHeader x2ResStatUpdHeader;
346  packet->RemoveHeader (x2ResStatUpdHeader);
347 
348  NS_LOG_INFO ("X2 ResourceStatusUpdate header: " << x2ResStatUpdHeader);
349 
351  params.enb1MeasurementId = x2ResStatUpdHeader.GetEnb1MeasurementId ();
352  params.enb2MeasurementId = x2ResStatUpdHeader.GetEnb2MeasurementId ();
353  params.cellMeasurementResultList = x2ResStatUpdHeader.GetCellMeasurementResultList ();
354 
355  NS_LOG_LOGIC ("enb1MeasurementId = " << params.enb1MeasurementId);
356  NS_LOG_LOGIC ("enb2MeasurementId = " << params.enb2MeasurementId);
357  NS_LOG_LOGIC ("cellMeasurementResultList size = " << params.cellMeasurementResultList.size ());
358 
359  m_x2SapUser->RecvResourceStatusUpdate (params);
360  }
361  }
362  else
363  {
364  NS_ASSERT_MSG (false, "ProcedureCode NOT SUPPORTED!!!");
365  }
366 }
367 
368 
369 void
371 {
372  NS_LOG_FUNCTION (this << socket);
373 
374  NS_LOG_LOGIC ("Recv UE DATA through X2-U interface from Socket");
375  Ptr<Packet> packet = socket->Recv ();
376  NS_LOG_LOGIC ("packetLen = " << packet->GetSize ());
377 
379  "Missing infos of local and remote CellId");
380  Ptr<X2CellInfo> cellsInfo = m_x2InterfaceCellIds [socket];
381 
382  GtpuHeader gtpu;
383  packet->RemoveHeader (gtpu);
384 
385  NS_LOG_LOGIC ("GTP-U header: " << gtpu);
386 
388  params.sourceCellId = cellsInfo->m_remoteCellId;
389  params.targetCellId = cellsInfo->m_localCellId;
390  params.gtpTeid = gtpu.GetTeid ();
391  params.ueData = packet;
392 
393  m_x2SapUser->RecvUeData (params);
394 }
395 
396 
397 //
398 // Implementation of the X2 SAP Provider
399 //
400 void
401 EpcX2::DoSendHandoverRequest (EpcX2SapProvider::HandoverRequestParams params)
402 {
403  NS_LOG_FUNCTION (this);
404 
405  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
406  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
407  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
408  NS_LOG_LOGIC ("mmeUeS1apId = " << params.mmeUeS1apId);
409 
410  NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.targetCellId) != m_x2InterfaceSockets.end (),
411  "Missing infos for targetCellId = " << params.targetCellId);
412  Ptr<X2IfaceInfo> socketInfo = m_x2InterfaceSockets [params.targetCellId];
413  Ptr<Socket> sourceSocket = socketInfo->m_localCtrlPlaneSocket;
414  Ipv4Address targetIpAddr = socketInfo->m_remoteIpAddr;
415 
416  NS_LOG_LOGIC ("sourceSocket = " << sourceSocket);
417  NS_LOG_LOGIC ("targetIpAddr = " << targetIpAddr);
418 
419  NS_LOG_INFO ("Send X2 message: HANDOVER REQUEST");
420 
421  // Build the X2 message
422  EpcX2HandoverRequestHeader x2HoReqHeader;
423  x2HoReqHeader.SetOldEnbUeX2apId (params.oldEnbUeX2apId);
424  x2HoReqHeader.SetCause (params.cause);
425  x2HoReqHeader.SetTargetCellId (params.targetCellId);
426  x2HoReqHeader.SetMmeUeS1apId (params.mmeUeS1apId);
427  x2HoReqHeader.SetUeAggregateMaxBitRateDownlink (params.ueAggregateMaxBitRateDownlink);
428  x2HoReqHeader.SetUeAggregateMaxBitRateUplink (params.ueAggregateMaxBitRateUplink);
429  x2HoReqHeader.SetBearers (params.bearers);
430 
431  EpcX2Header x2Header;
432  x2Header.SetMessageType (EpcX2Header::InitiatingMessage);
433  x2Header.SetProcedureCode (EpcX2Header::HandoverPreparation);
434  x2Header.SetLengthOfIes (x2HoReqHeader.GetLengthOfIes ());
435  x2Header.SetNumberOfIes (x2HoReqHeader.GetNumberOfIes ());
436 
437  NS_LOG_INFO ("X2 header: " << x2Header);
438  NS_LOG_INFO ("X2 HandoverRequest header: " << x2HoReqHeader);
439 
440  // Build the X2 packet
441  Ptr<Packet> packet = (params.rrcContext != 0) ? (params.rrcContext) : (Create <Packet> ());
442  packet->AddHeader (x2HoReqHeader);
443  packet->AddHeader (x2Header);
444  NS_LOG_INFO ("packetLen = " << packet->GetSize ());
445 
446  // Send the X2 message through the socket
447  sourceSocket->SendTo (packet, 0, InetSocketAddress (targetIpAddr, m_x2cUdpPort));
448 }
449 
450 
451 void
452 EpcX2::DoSendHandoverRequestAck (EpcX2SapProvider::HandoverRequestAckParams params)
453 {
454  NS_LOG_FUNCTION (this);
455 
456  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
457  NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
458  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
459  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
460 
461  NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.sourceCellId) != m_x2InterfaceSockets.end (),
462  "Socket infos not defined for sourceCellId = " << params.sourceCellId);
463 
464  Ptr<Socket> localSocket = m_x2InterfaceSockets [params.sourceCellId]->m_localCtrlPlaneSocket;
465  Ipv4Address remoteIpAddr = m_x2InterfaceSockets [params.sourceCellId]->m_remoteIpAddr;
466 
467  NS_LOG_LOGIC ("localSocket = " << localSocket);
468  NS_LOG_LOGIC ("remoteIpAddr = " << remoteIpAddr);
469 
470  NS_LOG_INFO ("Send X2 message: HANDOVER REQUEST ACK");
471 
472  // Build the X2 message
473  EpcX2HandoverRequestAckHeader x2HoAckHeader;
474  x2HoAckHeader.SetOldEnbUeX2apId (params.oldEnbUeX2apId);
475  x2HoAckHeader.SetNewEnbUeX2apId (params.newEnbUeX2apId);
476  x2HoAckHeader.SetAdmittedBearers (params.admittedBearers);
477  x2HoAckHeader.SetNotAdmittedBearers (params.notAdmittedBearers);
478 
479  EpcX2Header x2Header;
480  x2Header.SetMessageType (EpcX2Header::SuccessfulOutcome);
481  x2Header.SetProcedureCode (EpcX2Header::HandoverPreparation);
482  x2Header.SetLengthOfIes (x2HoAckHeader.GetLengthOfIes ());
483  x2Header.SetNumberOfIes (x2HoAckHeader.GetNumberOfIes ());
484 
485  NS_LOG_INFO ("X2 header: " << x2Header);
486  NS_LOG_INFO ("X2 HandoverAck header: " << x2HoAckHeader);
487  NS_LOG_INFO ("RRC context: " << params.rrcContext);
488 
489  // Build the X2 packet
490  Ptr<Packet> packet = (params.rrcContext != 0) ? (params.rrcContext) : (Create <Packet> ());
491  packet->AddHeader (x2HoAckHeader);
492  packet->AddHeader (x2Header);
493  NS_LOG_INFO ("packetLen = " << packet->GetSize ());
494 
495  // Send the X2 message through the socket
496  localSocket->SendTo (packet, 0, InetSocketAddress (remoteIpAddr, m_x2cUdpPort));
497 }
498 
499 
500 void
501 EpcX2::DoSendHandoverPreparationFailure (EpcX2SapProvider::HandoverPreparationFailureParams params)
502 {
503  NS_LOG_FUNCTION (this);
504 
505  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
506  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
507  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
508  NS_LOG_LOGIC ("cause = " << params.cause);
509  NS_LOG_LOGIC ("criticalityDiagnostics = " << params.criticalityDiagnostics);
510 
511  NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.sourceCellId) != m_x2InterfaceSockets.end (),
512  "Socket infos not defined for sourceCellId = " << params.sourceCellId);
513 
514  Ptr<Socket> localSocket = m_x2InterfaceSockets [params.sourceCellId]->m_localCtrlPlaneSocket;
515  Ipv4Address remoteIpAddr = m_x2InterfaceSockets [params.sourceCellId]->m_remoteIpAddr;
516 
517  NS_LOG_LOGIC ("localSocket = " << localSocket);
518  NS_LOG_LOGIC ("remoteIpAddr = " << remoteIpAddr);
519 
520  NS_LOG_INFO ("Send X2 message: HANDOVER PREPARATION FAILURE");
521 
522  // Build the X2 message
523  EpcX2HandoverPreparationFailureHeader x2HoPrepFailHeader;
524  x2HoPrepFailHeader.SetOldEnbUeX2apId (params.oldEnbUeX2apId);
525  x2HoPrepFailHeader.SetCause (params.cause);
526  x2HoPrepFailHeader.SetCriticalityDiagnostics (params.criticalityDiagnostics);
527 
528  EpcX2Header x2Header;
529  x2Header.SetMessageType (EpcX2Header::UnsuccessfulOutcome);
530  x2Header.SetProcedureCode (EpcX2Header::HandoverPreparation);
531  x2Header.SetLengthOfIes (x2HoPrepFailHeader.GetLengthOfIes ());
532  x2Header.SetNumberOfIes (x2HoPrepFailHeader.GetNumberOfIes ());
533 
534  NS_LOG_INFO ("X2 header: " << x2Header);
535  NS_LOG_INFO ("X2 HandoverPrepFail header: " << x2HoPrepFailHeader);
536 
537  // Build the X2 packet
538  Ptr<Packet> packet = Create <Packet> ();
539  packet->AddHeader (x2HoPrepFailHeader);
540  packet->AddHeader (x2Header);
541  NS_LOG_INFO ("packetLen = " << packet->GetSize ());
542 
543  // Send the X2 message through the socket
544  localSocket->SendTo (packet, 0, InetSocketAddress (remoteIpAddr, m_x2cUdpPort));
545 }
546 
547 
548 void
549 EpcX2::DoSendSnStatusTransfer (EpcX2SapProvider::SnStatusTransferParams params)
550 {
551  NS_LOG_FUNCTION (this);
552 
553  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
554  NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
555  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
556  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
557  NS_LOG_LOGIC ("erabsList size = " << params.erabsSubjectToStatusTransferList.size ());
558 
559  NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.targetCellId) != m_x2InterfaceSockets.end (),
560  "Socket infos not defined for targetCellId = " << params.targetCellId);
561 
562  Ptr<Socket> localSocket = m_x2InterfaceSockets [params.targetCellId]->m_localCtrlPlaneSocket;
563  Ipv4Address remoteIpAddr = m_x2InterfaceSockets [params.targetCellId]->m_remoteIpAddr;
564 
565  NS_LOG_LOGIC ("localSocket = " << localSocket);
566  NS_LOG_LOGIC ("remoteIpAddr = " << remoteIpAddr);
567 
568  NS_LOG_INFO ("Send X2 message: SN STATUS TRANSFER");
569 
570  // Build the X2 message
571  EpcX2SnStatusTransferHeader x2SnStatusXferHeader;
572  x2SnStatusXferHeader.SetOldEnbUeX2apId (params.oldEnbUeX2apId);
573  x2SnStatusXferHeader.SetNewEnbUeX2apId (params.newEnbUeX2apId);
574  x2SnStatusXferHeader.SetErabsSubjectToStatusTransferList (params.erabsSubjectToStatusTransferList);
575 
576  EpcX2Header x2Header;
577  x2Header.SetMessageType (EpcX2Header::InitiatingMessage);
578  x2Header.SetProcedureCode (EpcX2Header::SnStatusTransfer);
579  x2Header.SetLengthOfIes (x2SnStatusXferHeader.GetLengthOfIes ());
580  x2Header.SetNumberOfIes (x2SnStatusXferHeader.GetNumberOfIes ());
581 
582  NS_LOG_INFO ("X2 header: " << x2Header);
583  NS_LOG_INFO ("X2 SnStatusTransfer header: " << x2SnStatusXferHeader);
584 
585  // Build the X2 packet
586  Ptr<Packet> packet = Create <Packet> ();
587  packet->AddHeader (x2SnStatusXferHeader);
588  packet->AddHeader (x2Header);
589  NS_LOG_INFO ("packetLen = " << packet->GetSize ());
590 
591  // Send the X2 message through the socket
592  localSocket->SendTo (packet, 0, InetSocketAddress (remoteIpAddr, m_x2cUdpPort));
593 }
594 
595 
596 void
597 EpcX2::DoSendUeContextRelease (EpcX2SapProvider::UeContextReleaseParams params)
598 {
599  NS_LOG_FUNCTION (this);
600 
601  NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
602  NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
603  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
604 
605  NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.sourceCellId) != m_x2InterfaceSockets.end (),
606  "Socket infos not defined for sourceCellId = " << params.sourceCellId);
607 
608  Ptr<Socket> localSocket = m_x2InterfaceSockets [params.sourceCellId]->m_localCtrlPlaneSocket;
609  Ipv4Address remoteIpAddr = m_x2InterfaceSockets [params.sourceCellId]->m_remoteIpAddr;
610 
611  NS_LOG_LOGIC ("localSocket = " << localSocket);
612  NS_LOG_LOGIC ("remoteIpAddr = " << remoteIpAddr);
613 
614  NS_LOG_INFO ("Send X2 message: UE CONTEXT RELEASE");
615 
616  // Build the X2 message
617  EpcX2UeContextReleaseHeader x2UeCtxReleaseHeader;
618  x2UeCtxReleaseHeader.SetOldEnbUeX2apId (params.oldEnbUeX2apId);
619  x2UeCtxReleaseHeader.SetNewEnbUeX2apId (params.newEnbUeX2apId);
620 
621  EpcX2Header x2Header;
622  x2Header.SetMessageType (EpcX2Header::InitiatingMessage);
623  x2Header.SetProcedureCode (EpcX2Header::UeContextRelease);
624  x2Header.SetLengthOfIes (x2UeCtxReleaseHeader.GetLengthOfIes ());
625  x2Header.SetNumberOfIes (x2UeCtxReleaseHeader.GetNumberOfIes ());
626 
627  NS_LOG_INFO ("X2 header: " << x2Header);
628  NS_LOG_INFO ("X2 UeContextRelease header: " << x2UeCtxReleaseHeader);
629 
630  // Build the X2 packet
631  Ptr<Packet> packet = Create <Packet> ();
632  packet->AddHeader (x2UeCtxReleaseHeader);
633  packet->AddHeader (x2Header);
634  NS_LOG_INFO ("packetLen = " << packet->GetSize ());
635 
636  // Send the X2 message through the socket
637  localSocket->SendTo (packet, 0, InetSocketAddress (remoteIpAddr, m_x2cUdpPort));
638 }
639 
640 
641 void
642 EpcX2::DoSendLoadInformation (EpcX2SapProvider::LoadInformationParams params)
643 {
644  NS_LOG_FUNCTION (this);
645 
646  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
647  NS_LOG_LOGIC ("cellInformationList size = " << params.cellInformationList.size ());
648 
649  NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.targetCellId) != m_x2InterfaceSockets.end (),
650  "Missing infos for targetCellId = " << params.targetCellId);
651  Ptr<X2IfaceInfo> socketInfo = m_x2InterfaceSockets [params.targetCellId];
652  Ptr<Socket> sourceSocket = socketInfo->m_localCtrlPlaneSocket;
653  Ipv4Address targetIpAddr = socketInfo->m_remoteIpAddr;
654 
655  NS_LOG_LOGIC ("sourceSocket = " << sourceSocket);
656  NS_LOG_LOGIC ("targetIpAddr = " << targetIpAddr);
657 
658  NS_LOG_INFO ("Send X2 message: LOAD INFORMATION");
659 
660  // Build the X2 message
661  EpcX2LoadInformationHeader x2LoadInfoHeader;
662  x2LoadInfoHeader.SetCellInformationList (params.cellInformationList);
663 
664  EpcX2Header x2Header;
665  x2Header.SetMessageType (EpcX2Header::InitiatingMessage);
666  x2Header.SetProcedureCode (EpcX2Header::LoadIndication);
667  x2Header.SetLengthOfIes (x2LoadInfoHeader.GetLengthOfIes ());
668  x2Header.SetNumberOfIes (x2LoadInfoHeader.GetNumberOfIes ());
669 
670  NS_LOG_INFO ("X2 header: " << x2Header);
671  NS_LOG_INFO ("X2 LoadInformation header: " << x2LoadInfoHeader);
672 
673  // Build the X2 packet
674  Ptr<Packet> packet = Create <Packet> ();
675  packet->AddHeader (x2LoadInfoHeader);
676  packet->AddHeader (x2Header);
677  NS_LOG_INFO ("packetLen = " << packet->GetSize ());
678 
679  // Send the X2 message through the socket
680  sourceSocket->SendTo (packet, 0, InetSocketAddress (targetIpAddr, m_x2cUdpPort));
681 
682 }
683 
684 
685 void
686 EpcX2::DoSendResourceStatusUpdate (EpcX2SapProvider::ResourceStatusUpdateParams params)
687 {
688  NS_LOG_FUNCTION (this);
689 
690  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
691  NS_LOG_LOGIC ("enb1MeasurementId = " << params.enb1MeasurementId);
692  NS_LOG_LOGIC ("enb2MeasurementId = " << params.enb2MeasurementId);
693  NS_LOG_LOGIC ("cellMeasurementResultList size = " << params.cellMeasurementResultList.size ());
694 
695  NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.targetCellId) != m_x2InterfaceSockets.end (),
696  "Missing infos for targetCellId = " << params.targetCellId);
697  Ptr<X2IfaceInfo> socketInfo = m_x2InterfaceSockets [params.targetCellId];
698  Ptr<Socket> sourceSocket = socketInfo->m_localCtrlPlaneSocket;
699  Ipv4Address targetIpAddr = socketInfo->m_remoteIpAddr;
700 
701  NS_LOG_LOGIC ("sourceSocket = " << sourceSocket);
702  NS_LOG_LOGIC ("targetIpAddr = " << targetIpAddr);
703 
704  NS_LOG_INFO ("Send X2 message: RESOURCE STATUS UPDATE");
705 
706  // Build the X2 message
707  EpcX2ResourceStatusUpdateHeader x2ResourceStatUpdHeader;
708  x2ResourceStatUpdHeader.SetEnb1MeasurementId (params.enb1MeasurementId);
709  x2ResourceStatUpdHeader.SetEnb2MeasurementId (params.enb2MeasurementId);
710  x2ResourceStatUpdHeader.SetCellMeasurementResultList (params.cellMeasurementResultList);
711 
712  EpcX2Header x2Header;
713  x2Header.SetMessageType (EpcX2Header::InitiatingMessage);
714  x2Header.SetProcedureCode (EpcX2Header::ResourceStatusReporting);
715  x2Header.SetLengthOfIes (x2ResourceStatUpdHeader.GetLengthOfIes ());
716  x2Header.SetNumberOfIes (x2ResourceStatUpdHeader.GetNumberOfIes ());
717 
718  NS_LOG_INFO ("X2 header: " << x2Header);
719  NS_LOG_INFO ("X2 ResourceStatusUpdate header: " << x2ResourceStatUpdHeader);
720 
721  // Build the X2 packet
722  Ptr<Packet> packet = Create <Packet> ();
723  packet->AddHeader (x2ResourceStatUpdHeader);
724  packet->AddHeader (x2Header);
725  NS_LOG_INFO ("packetLen = " << packet->GetSize ());
726 
727  // Send the X2 message through the socket
728  sourceSocket->SendTo (packet, 0, InetSocketAddress (targetIpAddr, m_x2cUdpPort));
729 
730 }
731 
732 
733 void
734 EpcX2::DoSendUeData (EpcX2SapProvider::UeDataParams params)
735 {
736  NS_LOG_FUNCTION (this);
737 
738  NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
739  NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
740  NS_LOG_LOGIC ("gtpTeid = " << params.gtpTeid);
741 
742  NS_ASSERT_MSG (m_x2InterfaceSockets.find (params.targetCellId) != m_x2InterfaceSockets.end (),
743  "Missing infos for targetCellId = " << params.targetCellId);
744  Ptr<X2IfaceInfo> socketInfo = m_x2InterfaceSockets [params.targetCellId];
745  Ptr<Socket> sourceSocket = socketInfo->m_localUserPlaneSocket;
746  Ipv4Address targetIpAddr = socketInfo->m_remoteIpAddr;
747 
748  NS_LOG_LOGIC ("sourceSocket = " << sourceSocket);
749  NS_LOG_LOGIC ("targetIpAddr = " << targetIpAddr);
750 
751  GtpuHeader gtpu;
752  gtpu.SetTeid (params.gtpTeid);
753  gtpu.SetLength (params.ueData->GetSize () + gtpu.GetSerializedSize () - 8); // TODO This should be done in GtpuHeader
754  NS_LOG_INFO ("GTP-U header: " << gtpu);
755 
756  Ptr<Packet> packet = params.ueData;
757  packet->AddHeader (gtpu);
758 
759  NS_LOG_INFO ("Forward UE DATA through X2 interface");
760  sourceSocket->SendTo (packet, 0, InetSocketAddress (targetIpAddr, m_x2uUdpPort));
761 }
762 
763 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
virtual ~EpcX2(void)
Definition: epc-x2.cc:94
an Inet address class
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Parameters of the HANDOVER REQUEST message.
Definition: epc-x2-sap.h:225
#define NS_ASSERT(condition)
Definition: assert.h:64
virtual void RecvHandoverRequest(HandoverRequestParams params)=0
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
uint16_t m_x2cUdpPort
Definition: epc-x2.h:155
#define NS_LOG_INFO(msg)
Definition: log.h:264
void RecvFromX2uSocket(Ptr< Socket > socket)
Definition: epc-x2.cc:370
void RecvFromX2cSocket(Ptr< Socket > socket)
Definition: epc-x2.cc:170
Parameters of the HANDOVER PREPARATION FAILURE message.
Definition: epc-x2-sap.h:259
Parameters of the SN STATUS TRANSFER message.
Definition: epc-x2-sap.h:273
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:127
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
Definition: socket.cc:70
std::map< uint16_t, Ptr< X2IfaceInfo > > m_x2InterfaceSockets
Definition: epc-x2.h:144
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
Parameters of the RESOURCE STATUS UPDATE message.
Definition: epc-x2-sap.h:311
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
Parameters of the UE CONTEXT RELEASE message.
Definition: epc-x2-sap.h:287
Parameters of the HANDOVER REQUEST ACKNOWLEDGE message.
Definition: epc-x2-sap.h:243
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
EpcX2SapProvider * GetEpcX2SapProvider()
Definition: epc-x2.cc:125
void SetEpcX2SapUser(EpcX2SapUser *s)
Definition: epc-x2.cc:118
Parameters of the LOAD INFORMATION message.
Definition: epc-x2-sap.h:300
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
std::map< Ptr< Socket >, Ptr< X2CellInfo > > m_x2InterfaceCellIds
Definition: epc-x2.h:150
a base class which provides memory management and object aggregation
Definition: object.h:63
void AddX2Interface(uint16_t enb1CellId, Ipv4Address enb1X2Address, uint16_t enb2CellId, Ipv4Address enb2X2Address)
Definition: epc-x2.cc:133
virtual void DoDispose(void)
Definition: epc-x2.cc:100
Parameters of the UE DATA primitive.
Definition: epc-x2-sap.h:325
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
void AddHeader(const Header &header)
Definition: packet.cc:270
static TypeId LookupByName(std::string name)
Definition: type-id.cc:415