A Discrete-Event Network Simulator
API
epc-enb-application.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 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: Jaume Nin <jnin@cttc.cat>
19  * Nicola Baldo <nbaldo@cttc.cat>
20  */
21 
22 
23 #include "epc-enb-application.h"
24 #include "ns3/log.h"
25 #include "ns3/mac48-address.h"
26 #include "ns3/ipv4.h"
27 #include "ns3/inet-socket-address.h"
28 #include "ns3/uinteger.h"
29 
30 #include "epc-gtpu-header.h"
31 #include "eps-bearer-tag.h"
32 
33 
34 namespace ns3 {
35 
36 NS_LOG_COMPONENT_DEFINE ("EpcEnbApplication");
37 
39 {
40 }
41 
42 EpcEnbApplication::EpsFlowId_t::EpsFlowId_t (const uint16_t a, const uint8_t b)
43  : m_rnti (a),
44  m_bid (b)
45 {
46 }
47 
48 bool
50 {
51  return ( (a.m_rnti == b.m_rnti) && (a.m_bid == b.m_bid) );
52 }
53 
54 bool
56 {
57  return ( (a.m_rnti < b.m_rnti) || ( (a.m_rnti == b.m_rnti) && (a.m_bid < b.m_bid) ) );
58 }
59 
60 
61 TypeId
63 {
64  static TypeId tid = TypeId ("ns3::EpcEnbApplication")
65  .SetParent<Object> ()
66  .SetGroupName("Lte")
67  .AddTraceSource ("RxFromEnb",
68  "Receive data packets from LTE Enb Net Device",
70  "ns3::EpcEnbApplication::RxTracedCallback")
71  .AddTraceSource ("RxFromS1u",
72  "Receive data packets from S1-U Net Device",
74  "ns3::EpcEnbApplication::RxTracedCallback")
75  ;
76  return tid;
77 }
78 
79 void
81 {
82  NS_LOG_FUNCTION (this);
83  m_lteSocket = 0;
84  m_lteSocket6 = 0;
85  m_s1uSocket = 0;
86  delete m_s1SapProvider;
87  delete m_s1apSapEnb;
88 }
89 
90 EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> lteSocket6, uint16_t cellId)
91  : m_lteSocket (lteSocket),
92  m_lteSocket6 (lteSocket6),
93  m_gtpuUdpPort (2152), // fixed by the standard
94  m_s1SapUser (0),
95  m_s1apSapMme (0),
96  m_cellId (cellId)
97 {
98  NS_LOG_FUNCTION (this << lteSocket << lteSocket6 << cellId);
99 
104 }
105 
106 
107 void
109 {
110  NS_LOG_FUNCTION (this << s1uSocket << enbAddress << sgwAddress);
111 
112  m_s1uSocket = s1uSocket;
114  m_enbS1uAddress = enbAddress;
115  m_sgwS1uAddress = sgwAddress;
116 }
117 
118 
120 {
121  NS_LOG_FUNCTION (this);
122 }
123 
124 
125 void
127 {
128  m_s1SapUser = s;
129 }
130 
131 
134 {
135  return m_s1SapProvider;
136 }
137 
138 void
140 {
141  m_s1apSapMme = s;
142 }
143 
144 
147 {
148  return m_s1apSapEnb;
149 }
150 
151 void
152 EpcEnbApplication::DoInitialUeMessage (uint64_t imsi, uint16_t rnti)
153 {
154  NS_LOG_FUNCTION (this);
155  // side effect: create entry if not exist
156  m_imsiRntiMap[imsi] = rnti;
157  m_s1apSapMme->InitialUeMessage (imsi, rnti, imsi, m_cellId);
158 }
159 
160 void
162 {
163  NS_LOG_FUNCTION (this);
164  uint16_t enbUeS1Id = params.rnti;
165  uint64_t mmeUeS1Id = params.mmeUeS1Id;
166  uint64_t imsi = mmeUeS1Id;
167  // side effect: create entry if not exist
168  m_imsiRntiMap[imsi] = params.rnti;
169 
170  uint16_t gci = params.cellId;
171  std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList;
172  for (std::list<EpcEnbS1SapProvider::BearerToBeSwitched>::iterator bit = params.bearersToBeSwitched.begin ();
173  bit != params.bearersToBeSwitched.end ();
174  ++bit)
175  {
176  EpsFlowId_t flowId;
177  flowId.m_rnti = params.rnti;
178  flowId.m_bid = bit->epsBearerId;
179  uint32_t teid = bit->teid;
180 
181  EpsFlowId_t rbid (params.rnti, bit->epsBearerId);
182  // side effect: create entries if not exist
183  m_rbidTeidMap[params.rnti][bit->epsBearerId] = teid;
184  m_teidRbidMap[teid] = rbid;
185 
187  erab.erabId = bit->epsBearerId;
189  erab.enbTeid = bit->teid;
190 
191  erabToBeSwitchedInDownlinkList.push_back (erab);
192  }
193  m_s1apSapMme->PathSwitchRequest (enbUeS1Id, mmeUeS1Id, gci, erabToBeSwitchedInDownlinkList);
194 }
195 
196 void
198 {
199  NS_LOG_FUNCTION (this << rnti);
200  std::map<uint16_t, std::map<uint8_t, uint32_t> >::iterator rntiIt = m_rbidTeidMap.find (rnti);
201  if (rntiIt != m_rbidTeidMap.end ())
202  {
203  for (std::map<uint8_t, uint32_t>::iterator bidIt = rntiIt->second.begin ();
204  bidIt != rntiIt->second.end ();
205  ++bidIt)
206  {
207  uint32_t teid = bidIt->second;
208  m_teidRbidMap.erase (teid);
209  NS_LOG_INFO ("TEID: " << teid << " erased");
210  }
211  m_rbidTeidMap.erase (rntiIt);
212  NS_LOG_INFO ("RNTI: " << rntiIt->first << " erased");
213  }
214 }
215 
216 void
217 EpcEnbApplication::DoInitialContextSetupRequest (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList)
218 {
219  NS_LOG_FUNCTION (this);
220 
221  uint64_t imsi = mmeUeS1Id;
222  std::map<uint64_t, uint16_t>::iterator imsiIt = m_imsiRntiMap.find (imsi);
223  NS_ASSERT_MSG (imsiIt != m_imsiRntiMap.end (), "unknown IMSI");
224  uint16_t rnti = imsiIt->second;
225 
226  for (std::list<EpcS1apSapEnb::ErabToBeSetupItem>::iterator erabIt = erabToBeSetupList.begin ();
227  erabIt != erabToBeSetupList.end ();
228  ++erabIt)
229  {
230  // request the RRC to setup a radio bearer
232  params.rnti = rnti;
233  params.bearer = erabIt->erabLevelQosParameters;
234  params.bearerId = erabIt->erabId;
235  params.gtpTeid = erabIt->sgwTeid;
237 
238  EpsFlowId_t rbid (rnti, erabIt->erabId);
239  // side effect: create entries if not exist
240  m_rbidTeidMap[rnti][erabIt->erabId] = params.gtpTeid;
241  m_teidRbidMap[params.gtpTeid] = rbid;
242  }
243 
244  // Send Initial Context Setup Request to RRC
246  params.rnti = rnti;
248 }
249 
250 void
251 EpcEnbApplication::DoPathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList)
252 {
253  NS_LOG_FUNCTION (this);
254 
255  uint64_t imsi = mmeUeS1Id;
256  std::map<uint64_t, uint16_t>::iterator imsiIt = m_imsiRntiMap.find (imsi);
257  NS_ASSERT_MSG (imsiIt != m_imsiRntiMap.end (), "unknown IMSI");
258  uint16_t rnti = imsiIt->second;
260  params.rnti = rnti;
262 }
263 
264 void
266 {
267  NS_LOG_FUNCTION (this);
268  if(m_lteSocket6)
269  {
270  NS_ASSERT (socket == m_lteSocket || socket == m_lteSocket6);
271  }
272  else
273  {
274  NS_ASSERT (socket == m_lteSocket);
275  }
276  Ptr<Packet> packet = socket->Recv ();
277 
278  EpsBearerTag tag;
279  bool found = packet->RemovePacketTag (tag);
280  NS_ASSERT (found);
281  uint16_t rnti = tag.GetRnti ();
282  uint8_t bid = tag.GetBid ();
283  NS_LOG_LOGIC ("received packet with RNTI=" << (uint32_t) rnti << ", BID=" << (uint32_t) bid);
284  std::map<uint16_t, std::map<uint8_t, uint32_t> >::iterator rntiIt = m_rbidTeidMap.find (rnti);
285  if (rntiIt == m_rbidTeidMap.end ())
286  {
287  NS_LOG_WARN ("UE context not found, discarding packet");
288  }
289  else
290  {
291  std::map<uint8_t, uint32_t>::iterator bidIt = rntiIt->second.find (bid);
292  NS_ASSERT (bidIt != rntiIt->second.end ());
293  uint32_t teid = bidIt->second;
294  m_rxLteSocketPktTrace (packet->Copy ());
295  SendToS1uSocket (packet, teid);
296  }
297 }
298 
299 void
301 {
302  NS_LOG_FUNCTION (this << socket);
303  NS_ASSERT (socket == m_s1uSocket);
304  Ptr<Packet> packet = socket->Recv ();
305  GtpuHeader gtpu;
306  packet->RemoveHeader (gtpu);
307  uint32_t teid = gtpu.GetTeid ();
308  std::map<uint32_t, EpsFlowId_t>::iterator it = m_teidRbidMap.find (teid);
309  if (it == m_teidRbidMap.end ())
310  {
311  NS_LOG_WARN ("UE context at cell id " << m_cellId << " not found, discarding packet");
312  }
313  else
314  {
315  m_rxS1uSocketPktTrace (packet->Copy ());
316  SendToLteSocket (packet, it->second.m_rnti, it->second.m_bid);
317  }
318 }
319 
320 void
321 EpcEnbApplication::SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t bid)
322 {
323  NS_LOG_FUNCTION (this << packet << rnti << (uint16_t) bid << packet->GetSize ());
324  EpsBearerTag tag (rnti, bid);
325  packet->AddPacketTag (tag);
326  uint8_t ipType;
327 
328  packet->CopyData (&ipType, 1);
329  ipType = (ipType>>4) & 0x0f;
330 
331  int sentBytes;
332  if (ipType == 0x04)
333  {
334  sentBytes = m_lteSocket->Send (packet);
335  }
336  else if (ipType == 0x06)
337  {
338  sentBytes = m_lteSocket6->Send (packet);
339  }
340  else
341  {
342  NS_ABORT_MSG ("EpcEnbApplication::SendToLteSocket - Unknown IP type...");
343  }
344 
345  NS_ASSERT (sentBytes > 0);
346 }
347 
348 
349 void
351 {
352  NS_LOG_FUNCTION (this << packet << teid << packet->GetSize ());
353  GtpuHeader gtpu;
354  gtpu.SetTeid (teid);
355  // From 3GPP TS 29.281 v10.0.0 Section 5.1
356  // Length of the payload + the non obligatory GTP-U header
357  gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8);
358  packet->AddHeader (gtpu);
359  uint32_t flags = 0;
361 }
362 
363 void
364 EpcEnbApplication::DoReleaseIndication (uint64_t imsi, uint16_t rnti, uint8_t bearerId)
365 {
366  NS_LOG_FUNCTION (this << bearerId );
367  std::list<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication;
369  erab.erabId = bearerId;
370  erabToBeReleaseIndication.push_back (erab);
371  //From 3GPP TS 23401-950 Section 5.4.4.2, enB sends EPS bearer Identity in Bearer Release Indication message to MME
372  m_s1apSapMme->ErabReleaseIndication (imsi, rnti, erabToBeReleaseIndication);
373 }
374 
375 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
Parameters passed to DataRadioBearerSetupRequest ()
This class implements the Service Access Point (SAP) between the LteEnbRrc and the EpcEnbApplication...
E-RAB Release Indication Item IEs, 3GPP TS 36.413 version 9.8.0 section 9.1.3.7.
Definition: epc-s1ap-sap.h:72
an Inet address class
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
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:53
uint32_t mmeUeS1Id
mmeUeS1Id in practice, we use the IMSI
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
This class implements the Service Access Point (SAP) between the LteEnbRrc and the EpcEnbApplication...
void DoPathSwitchRequest(EpcEnbS1SapProvider::PathSwitchRequestParameters params)
Path switch request function.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
virtual void DataRadioBearerSetupRequest(DataRadioBearerSetupRequestParameters params)=0
request the setup of a DataRadioBearer
Ipv4Address m_enbS1uAddress
address of the eNB for S1-U communications
uint16_t rnti
the RNTI identifying the UE for which the DataRadioBearer is to be created
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
void DoDispose(void)
Destructor implementation.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Ipv4Address m_sgwS1uAddress
address of the SGW which terminates all S1-U tunnels
std::list< BearerToBeSwitched > bearersToBeSwitched
list of bearers to be switched
Tag used to define the RNTI and EPS bearer ID for packets interchanged between the EpcEnbApplication ...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
EpsBearer bearer
the characteristics of the bearer to be setup
Ptr< Socket > m_lteSocket
raw packet socket to send and receive the packets to and from the LTE radio interface ...
EpcEnbApplication(Ptr< Socket > lteSocket, Ptr< Socket > lteSocket6, uint16_t cellId)
Constructor.
virtual void ErabReleaseIndication(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< ErabToBeReleasedIndication > erabToBeReleaseIndication)=0
As per 3GPP TS 23.401 Release 9 V9.5.0 Figure 5.4.4.2-1 eNB sends indication of Bearer Release to MME...
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.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
EpcS1apSapEnb * GetS1apSapEnb()
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:160
void SendToS1uSocket(Ptr< Packet > packet, uint32_t teid)
Send a packet to the SGW via the S1-U interface.
TracedCallback< Ptr< Packet > > m_rxLteSocketPktTrace
Callback to trace RX (reception) data packets from LTE Socket.
void SetS1SapUser(EpcEnbS1SapUser *s)
Set the S1 SAP User.
uint32_t GetTeid() const
Get a tunnel endpoint identificator (TEID)
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:141
uint16_t m_gtpuUdpPort
UDP port to be used for GTP.
EpcS1apSapMme * m_s1apSapMme
MME side of the S1-AP SAP.
void DoInitialUeMessage(uint64_t imsi, uint16_t rnti)
Initial UE message function.
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.
uint32_t gtpTeid
S1-bearer GTP tunnel endpoint identifier, see 36.423 9.2.1.
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:128
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
PathSwitchRequestParameters structure.
virtual ~EpcEnbApplication(void)
Destructor.
void RecvFromLteSocket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the LTE socket.
uint8_t GetBid(void) const
Get Bearer Id function.
void DoInitialContextSetupRequest(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< EpcS1apSapEnb::ErabToBeSetupItem > erabToBeSetupList)
Initial Context Setup Request.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TypeId GetTypeId(void)
Get the type ID.
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
Template for the implementation of the EpcEnbS1SapProvider as a member of an owner class of type C to...
EpcEnbS1SapProvider * GetS1SapProvider()
PathSwitchRequestAcknowledgeParameters structure.
void RecvFromS1uSocket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the S1-U socket.
EpcEnbS1SapUser * m_s1SapUser
User for the S1 SAP.
void DoUeContextRelease(uint16_t rnti)
UE Context Release function.
std::map< uint32_t, EpsFlowId_t > m_teidRbidMap
map telling for each S1-U TEID the corresponding RNTI,BID
#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:88
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
void SetTeid(uint32_t teid)
Set TEID function.
virtual void PathSwitchRequestAcknowledge(PathSwitchRequestAcknowledgeParameters params)=0
request a path switch acknowledge
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:863
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:870
Parameters passed to InitialContextSetupRequest ()
void DoPathSwitchRequestAcknowledge(uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list< EpcS1apSapEnb::ErabSwitchedInUplinkItem > erabToBeSwitchedInUplinkList)
Path Switch Request Acknowledge.
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.h:142
TracedCallback< Ptr< Packet > > m_rxS1uSocketPktTrace
Callback to trace RX (reception) data packets from S1-U Socket.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
virtual void InitialUeMessage(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t stmsi, uint16_t ecgi)=0
Ptr< Socket > m_lteSocket6
raw packet socket to send and receive the packets to and from the LTE radio interface ...
A base class which provides memory management and object aggregation.
Definition: object.h:87
EpcS1apSapEnb * m_s1apSapEnb
ENB side of the S1-AP SAP.
void SetS1apSapMme(EpcS1apSapMme *s)
Set the MME side of the S1-AP SAP.
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
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...
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
virtual void InitialContextSetupRequest(InitialContextSetupRequestParameters params)=0
Initial context setup request.
void AddS1Interface(Ptr< Socket > s1uSocket, Ipv4Address enbAddress, Ipv4Address sgwAddress)
Add a S1-U interface to the eNB.
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
std::map< uint64_t, uint16_t > m_imsiRntiMap
UE context info.
Ptr< Socket > m_s1uSocket
UDP socket to send and receive GTP-U the packets to and from the S1-U interface.
uint16_t GetRnti(void) const
Get RNTI function.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
uint8_t m_bid
Bid, the EPS Bearer IDentifier.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
Template for the implementation of the EpcS1apSapEnb as a member of an owner class of type C to which...
Definition: epc-s1ap-sap.h:298
Implementation of the GPRS Tunnelling Protocol header according to GTPv1-U Release 10 as per 3Gpp TS ...
EpcEnbS1SapProvider * m_s1SapProvider
Provider for the S1 SAP.