A Discrete-Event Network Simulator
API
epc-enb-application.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Jaume Nin <jnin@cttc.cat>
18  * Nicola Baldo <nbaldo@cttc.cat>
19  */
20 
21 #include "epc-enb-application.h"
22 
23 #include "epc-gtpu-header.h"
24 #include "eps-bearer-tag.h"
25 
26 #include "ns3/inet-socket-address.h"
27 #include "ns3/ipv4.h"
28 #include "ns3/log.h"
29 #include "ns3/mac48-address.h"
30 #include "ns3/uinteger.h"
31 
32 namespace ns3
33 {
34 
35 NS_LOG_COMPONENT_DEFINE("EpcEnbApplication");
36 
38 {
39 }
40 
41 EpcEnbApplication::EpsFlowId_t::EpsFlowId_t(const uint16_t a, const uint8_t b)
42  : m_rnti(a),
43  m_bid(b)
44 {
45 }
46 
47 bool
49 {
50  return ((a.m_rnti == b.m_rnti) && (a.m_bid == b.m_bid));
51 }
52 
53 bool
55 {
56  return ((a.m_rnti < b.m_rnti) || ((a.m_rnti == b.m_rnti) && (a.m_bid < b.m_bid)));
57 }
58 
59 TypeId
61 {
62  static TypeId tid =
63  TypeId("ns3::EpcEnbApplication")
64  .SetParent<Object>()
65  .SetGroupName("Lte")
66  .AddTraceSource("RxFromEnb",
67  "Receive data packets from LTE Enb Net Device",
69  "ns3::EpcEnbApplication::RxTracedCallback")
70  .AddTraceSource("RxFromS1u",
71  "Receive data packets from S1-U Net Device",
73  "ns3::EpcEnbApplication::RxTracedCallback");
74  return tid;
75 }
76 
77 void
79 {
80  NS_LOG_FUNCTION(this);
81  m_lteSocket = nullptr;
82  m_lteSocket6 = nullptr;
83  m_s1uSocket = nullptr;
84  delete m_s1SapProvider;
85  delete m_s1apSapEnb;
86 }
87 
88 EpcEnbApplication::EpcEnbApplication(Ptr<Socket> lteSocket, Ptr<Socket> lteSocket6, uint16_t cellId)
89  : m_lteSocket(lteSocket),
90  m_lteSocket6(lteSocket6),
91  m_gtpuUdpPort(2152), // fixed by the standard
92  m_s1SapUser(nullptr),
93  m_s1apSapMme(nullptr),
94  m_cellId(cellId)
95 {
96  NS_LOG_FUNCTION(this << lteSocket << lteSocket6 << cellId);
97 
102 }
103 
104 void
106  Ipv4Address enbAddress,
107  Ipv4Address sgwAddress)
108 {
109  NS_LOG_FUNCTION(this << s1uSocket << enbAddress << sgwAddress);
110 
111  m_s1uSocket = s1uSocket;
113  m_enbS1uAddress = enbAddress;
114  m_sgwS1uAddress = sgwAddress;
115 }
116 
118 {
119  NS_LOG_FUNCTION(this);
120 }
121 
122 void
124 {
125  m_s1SapUser = s;
126 }
127 
130 {
131  return m_s1SapProvider;
132 }
133 
134 void
136 {
137  m_s1apSapMme = s;
138 }
139 
142 {
143  return m_s1apSapEnb;
144 }
145 
146 void
147 EpcEnbApplication::DoInitialUeMessage(uint64_t imsi, uint16_t rnti)
148 {
149  NS_LOG_FUNCTION(this);
150  // side effect: create entry if not exist
151  m_imsiRntiMap[imsi] = rnti;
152  m_s1apSapMme->InitialUeMessage(imsi, rnti, imsi, m_cellId);
153 }
154 
155 void
157 {
158  NS_LOG_FUNCTION(this);
159  uint16_t enbUeS1Id = params.rnti;
160  uint64_t mmeUeS1Id = params.mmeUeS1Id;
161  uint64_t imsi = mmeUeS1Id;
162  // side effect: create entry if not exist
163  m_imsiRntiMap[imsi] = params.rnti;
164 
165  uint16_t gci = params.cellId;
166  std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList;
167  for (std::list<EpcEnbS1SapProvider::BearerToBeSwitched>::iterator bit =
168  params.bearersToBeSwitched.begin();
169  bit != params.bearersToBeSwitched.end();
170  ++bit)
171  {
172  EpsFlowId_t flowId;
173  flowId.m_rnti = params.rnti;
174  flowId.m_bid = bit->epsBearerId;
175  uint32_t teid = bit->teid;
176 
177  EpsFlowId_t rbid(params.rnti, bit->epsBearerId);
178  // side effect: create entries if not exist
179  m_rbidTeidMap[params.rnti][bit->epsBearerId] = teid;
180  m_teidRbidMap[teid] = rbid;
181 
183  erab.erabId = bit->epsBearerId;
185  erab.enbTeid = bit->teid;
186 
187  erabToBeSwitchedInDownlinkList.push_back(erab);
188  }
189  m_s1apSapMme->PathSwitchRequest(enbUeS1Id, mmeUeS1Id, gci, erabToBeSwitchedInDownlinkList);
190 }
191 
192 void
194 {
195  NS_LOG_FUNCTION(this << rnti);
196  std::map<uint16_t, std::map<uint8_t, uint32_t>>::iterator rntiIt = m_rbidTeidMap.find(rnti);
197  if (rntiIt != m_rbidTeidMap.end())
198  {
199  for (std::map<uint8_t, uint32_t>::iterator bidIt = rntiIt->second.begin();
200  bidIt != rntiIt->second.end();
201  ++bidIt)
202  {
203  uint32_t teid = bidIt->second;
204  m_teidRbidMap.erase(teid);
205  NS_LOG_INFO("TEID: " << teid << " erased");
206  }
207  m_rbidTeidMap.erase(rntiIt);
208  NS_LOG_INFO("RNTI: " << rntiIt->first << " erased");
209  }
210 }
211 
212 void
214  uint64_t mmeUeS1Id,
215  uint16_t enbUeS1Id,
216  std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList)
217 {
218  NS_LOG_FUNCTION(this);
219 
220  uint64_t imsi = mmeUeS1Id;
221  std::map<uint64_t, uint16_t>::iterator imsiIt = m_imsiRntiMap.find(imsi);
222  NS_ASSERT_MSG(imsiIt != m_imsiRntiMap.end(), "unknown IMSI");
223  uint16_t rnti = imsiIt->second;
224 
225  for (std::list<EpcS1apSapEnb::ErabToBeSetupItem>::iterator erabIt = erabToBeSetupList.begin();
226  erabIt != erabToBeSetupList.end();
227  ++erabIt)
228  {
229  // request the RRC to setup a radio bearer
231  params.rnti = rnti;
232  params.bearer = erabIt->erabLevelQosParameters;
233  params.bearerId = erabIt->erabId;
234  params.gtpTeid = erabIt->sgwTeid;
236 
237  EpsFlowId_t rbid(rnti, erabIt->erabId);
238  // side effect: create entries if not exist
239  m_rbidTeidMap[rnti][erabIt->erabId] = params.gtpTeid;
240  m_teidRbidMap[params.gtpTeid] = rbid;
241  }
242 
243  // Send Initial Context Setup Request to RRC
245  params.rnti = rnti;
247 }
248 
249 void
251  uint64_t enbUeS1Id,
252  uint64_t mmeUeS1Id,
253  uint16_t gci,
254  std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList)
255 {
256  NS_LOG_FUNCTION(this);
257 
258  uint64_t imsi = mmeUeS1Id;
259  std::map<uint64_t, uint16_t>::iterator imsiIt = m_imsiRntiMap.find(imsi);
260  NS_ASSERT_MSG(imsiIt != m_imsiRntiMap.end(), "unknown IMSI");
261  uint16_t rnti = imsiIt->second;
263  params.rnti = rnti;
265 }
266 
267 void
269 {
270  NS_LOG_FUNCTION(this);
271  if (m_lteSocket6)
272  {
273  NS_ASSERT(socket == m_lteSocket || socket == m_lteSocket6);
274  }
275  else
276  {
277  NS_ASSERT(socket == m_lteSocket);
278  }
279  Ptr<Packet> packet = socket->Recv();
280 
281  EpsBearerTag tag;
282  bool found = packet->RemovePacketTag(tag);
283  NS_ASSERT(found);
284  uint16_t rnti = tag.GetRnti();
285  uint8_t bid = tag.GetBid();
286  NS_LOG_LOGIC("received packet with RNTI=" << (uint32_t)rnti << ", BID=" << (uint32_t)bid);
287  std::map<uint16_t, std::map<uint8_t, uint32_t>>::iterator rntiIt = m_rbidTeidMap.find(rnti);
288  if (rntiIt == m_rbidTeidMap.end())
289  {
290  NS_LOG_WARN("UE context not found, discarding packet");
291  }
292  else
293  {
294  std::map<uint8_t, uint32_t>::iterator bidIt = rntiIt->second.find(bid);
295  NS_ASSERT(bidIt != rntiIt->second.end());
296  uint32_t teid = bidIt->second;
297  m_rxLteSocketPktTrace(packet->Copy());
298  SendToS1uSocket(packet, teid);
299  }
300 }
301 
302 void
304 {
305  NS_LOG_FUNCTION(this << socket);
306  NS_ASSERT(socket == m_s1uSocket);
307  Ptr<Packet> packet = socket->Recv();
308  GtpuHeader gtpu;
309  packet->RemoveHeader(gtpu);
310  uint32_t teid = gtpu.GetTeid();
311  std::map<uint32_t, EpsFlowId_t>::iterator it = m_teidRbidMap.find(teid);
312  if (it == m_teidRbidMap.end())
313  {
314  NS_LOG_WARN("UE context at cell id " << m_cellId << " not found, discarding packet");
315  }
316  else
317  {
318  m_rxS1uSocketPktTrace(packet->Copy());
319  SendToLteSocket(packet, it->second.m_rnti, it->second.m_bid);
320  }
321 }
322 
323 void
324 EpcEnbApplication::SendToLteSocket(Ptr<Packet> packet, uint16_t rnti, uint8_t bid)
325 {
326  NS_LOG_FUNCTION(this << packet << rnti << (uint16_t)bid << packet->GetSize());
327  EpsBearerTag tag(rnti, bid);
328  packet->AddPacketTag(tag);
329  uint8_t ipType;
330 
331  packet->CopyData(&ipType, 1);
332  ipType = (ipType >> 4) & 0x0f;
333 
334  int sentBytes;
335  if (ipType == 0x04)
336  {
337  sentBytes = m_lteSocket->Send(packet);
338  }
339  else if (ipType == 0x06)
340  {
341  sentBytes = m_lteSocket6->Send(packet);
342  }
343  else
344  {
345  NS_ABORT_MSG("EpcEnbApplication::SendToLteSocket - Unknown IP type...");
346  }
347 
348  NS_ASSERT(sentBytes > 0);
349 }
350 
351 void
353 {
354  NS_LOG_FUNCTION(this << packet << teid << packet->GetSize());
355  GtpuHeader gtpu;
356  gtpu.SetTeid(teid);
357  // From 3GPP TS 29.281 v10.0.0 Section 5.1
358  // Length of the payload + the non obligatory GTP-U header
359  gtpu.SetLength(packet->GetSize() + gtpu.GetSerializedSize() - 8);
360  packet->AddHeader(gtpu);
361  uint32_t flags = 0;
363 }
364 
365 void
366 EpcEnbApplication::DoReleaseIndication(uint64_t imsi, uint16_t rnti, uint8_t bearerId)
367 {
368  NS_LOG_FUNCTION(this << bearerId);
369  std::list<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication;
371  erab.erabId = bearerId;
372  erabToBeReleaseIndication.push_back(erab);
373  // From 3GPP TS 23401-950 Section 5.4.4.2, enB sends EPS bearer Identity in Bearer Release
374  // Indication message to MME
375  m_s1apSapMme->ErabReleaseIndication(imsi, rnti, erabToBeReleaseIndication);
376 }
377 
378 } // namespace ns3
std::map< uint16_t, std::map< uint8_t, uint32_t > > m_rbidTeidMap
map of maps telling for each RNTI and BID the corresponding S1-U TEID
EpcS1apSapEnb * m_s1apSapEnb
ENB side of the S1-AP SAP.
Ipv4Address m_enbS1uAddress
address of the eNB for S1-U communications
Ptr< Socket > m_s1uSocket
UDP socket to send and receive GTP-U the packets to and from the S1-U interface.
void DoReleaseIndication(uint64_t imsi, uint16_t rnti, uint8_t bearerId)
This function accepts bearer id corresponding to a particular UE and schedules indication of bearer r...
void DoPathSwitchRequestAcknowledge(uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list< EpcS1apSapEnb::ErabSwitchedInUplinkItem > erabToBeSwitchedInUplinkList)
Path Switch Request Acknowledge.
void RecvFromLteSocket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the LTE socket.
void AddS1Interface(Ptr< Socket > s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress)
Add a S1-U interface to the eNB.
void DoInitialContextSetupRequest(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< EpcS1apSapEnb::ErabToBeSetupItem > erabToBeSetupList)
Initial Context Setup Request.
void DoDispose() override
Destructor implementation.
void DoUeContextRelease(uint16_t rnti)
UE Context Release function.
Ipv4Address m_sgwS1uAddress
address of the SGW which terminates all S1-U tunnels
Ptr< Socket > m_lteSocket
raw packet socket to send and receive the packets to and from the LTE radio interface
void SendToS1uSocket(Ptr< Packet > packet, uint32_t teid)
Send a packet to the SGW via the S1-U interface.
void SetS1apSapMme(EpcS1apSapMme *s)
Set the MME side of the S1-AP SAP.
EpcEnbS1SapProvider * GetS1SapProvider()
static TypeId GetTypeId()
Get the type ID.
void SendToLteSocket(Ptr< Packet > packet, uint16_t rnti, uint8_t bid)
Send a packet to the UE via the LTE radio interface of the eNB.
EpcS1apSapEnb * GetS1apSapEnb()
TracedCallback< Ptr< Packet > > m_rxLteSocketPktTrace
Callback to trace RX (reception) data packets from LTE Socket.
void RecvFromS1uSocket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the S1-U socket.
friend class MemberEpcEnbS1SapProvider< EpcEnbApplication >
allow MemberEpcEnbS1SapProvider<EpcEnbApplication> class friend access
std::map< uint64_t, uint16_t > m_imsiRntiMap
UE context info.
EpcEnbS1SapUser * m_s1SapUser
User for the S1 SAP.
Ptr< Socket > m_lteSocket6
raw packet socket to send and receive the packets to and from the LTE radio interface
void DoPathSwitchRequest(EpcEnbS1SapProvider::PathSwitchRequestParameters params)
Path switch request function.
uint16_t m_gtpuUdpPort
UDP port to be used for GTP.
void DoInitialUeMessage(uint64_t imsi, uint16_t rnti)
Initial UE message function.
std::map< uint32_t, EpsFlowId_t > m_teidRbidMap
map telling for each S1-U TEID the corresponding RNTI,BID
friend class MemberEpcS1apSapEnb< EpcEnbApplication >
allow MemberEpcS1apSapEnb<EpcEnbApplication> class friend access
EpcS1apSapMme * m_s1apSapMme
MME side of the S1-AP SAP.
EpcEnbApplication(Ptr< Socket > lteSocket, Ptr< Socket > lteSocket6, uint16_t cellId)
Constructor.
EpcEnbS1SapProvider * m_s1SapProvider
Provider for the S1 SAP.
void SetS1SapUser(EpcEnbS1SapUser *s)
Set the S1 SAP User.
~EpcEnbApplication() override
Destructor.
TracedCallback< Ptr< Packet > > m_rxS1uSocketPktTrace
Callback to trace RX (reception) data packets from S1-U Socket.
This class implements the Service Access Point (SAP) between the LteEnbRrc and the EpcEnbApplication.
This class implements the Service Access Point (SAP) between the LteEnbRrc and the EpcEnbApplication.
virtual void PathSwitchRequestAcknowledge(PathSwitchRequestAcknowledgeParameters params)=0
Request a path switch acknowledge.
virtual void DataRadioBearerSetupRequest(DataRadioBearerSetupRequestParameters params)=0
Request the setup of a DataRadioBearer.
virtual void InitialContextSetupRequest(InitialContextSetupRequestParameters params)=0
Initial context setup request.
eNB side of the S1-AP Service Access Point (SAP), provides the eNB methods to be called when an S1-AP...
Definition: epc-s1ap-sap.h:143
MME side of the S1-AP Service Access Point (SAP), provides the MME methods to be called when an S1-AP...
Definition: epc-s1ap-sap.h:52
virtual void InitialUeMessage(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t stmsi, uint16_t ecgi)=0
Initial UE message.
virtual void ErabReleaseIndication(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< ErabToBeReleasedIndication > erabToBeReleaseIndication)=0
As per 3GPP TS 36.413 version 9.8.0 section 8.2.3.2.2, the eNB indicates bearer release by sending an...
virtual void PathSwitchRequest(uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list< ErabSwitchedInDownlinkItem > erabToBeSwitchedInDownlinkList)=0
PATH SWITCH REQUEST message, see 3GPP TS 36.413 9.1.5.8.
Tag used to define the RNTI and EPS bearer ID for packets interchanged between the EpcEnbApplication ...
uint8_t GetBid() const
Get Bearer Id function.
uint16_t GetRnti() const
Get RNTI function.
Implementation of the GPRS Tunnelling Protocol header according to GTPv1-U Release 10 as per 3Gpp TS ...
void SetTeid(uint32_t teid)
Set TEID function.
uint32_t GetSerializedSize() const override
uint32_t GetTeid() const
Get a tunnel endpoint identificator (TEID)
void SetLength(uint16_t length)
Set the length in octets of the payload.
an Inet address class
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
A base class which provides memory management and object aggregation.
Definition: object.h:89
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:126
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.h:157
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:170
params
Fit Fluctuating Two Ray model to the 3GPP TR 38.901 using the Anderson-Darling goodness-of-fit ##.
uint8_t m_bid
Bid, the EPS Bearer IDentifier.
PathSwitchRequestParameters structure.
Parameters passed to DataRadioBearerSetupRequest ()
Parameters passed to InitialContextSetupRequest ()
PathSwitchRequestAcknowledgeParameters structure.
E-RAB Release Indication Item IEs, 3GPP TS 36.413 version 9.8.0 section 9.1.3.7.
Definition: epc-s1ap-sap.h:71