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
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...
virtual ~EpcEnbApplication(void)
Destructor.
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 DoUeContextRelease(uint16_t rnti)
UE Context Release function.
Ipv4Address m_sgwS1uAddress
address of the SGW which terminates all S1-U tunnels
void DoDispose(void)
Destructor implementation.
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.
static TypeId GetTypeId(void)
Get the type ID.
void SetS1apSapMme(EpcS1apSapMme *s)
Set the MME side of the S1-AP SAP.
EpcEnbS1SapProvider * GetS1SapProvider()
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.
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:144
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:54
virtual void InitialUeMessage(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t stmsi, uint16_t ecgi)=0
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 ...
uint16_t GetRnti(void) const
Get RNTI function.
uint8_t GetBid(void) const
Get Bearer Id 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.
virtual uint32_t GetSerializedSize(void) const
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:41
A base class which provides memory management and object aggregation.
Definition: object.h:88
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
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:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
#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
#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
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#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:265
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
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.
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.h:158
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:176
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:1648
uint8_t m_bid
Bid, the EPS Bearer IDentifier.
PathSwitchRequestParameters structure.
std::list< BearerToBeSwitched > bearersToBeSwitched
list of bearers to be switched
uint32_t mmeUeS1Id
mmeUeS1Id in practice, we use the IMSI
Parameters passed to DataRadioBearerSetupRequest ()
EpsBearer bearer
the characteristics of the bearer to be setup
uint16_t rnti
the RNTI identifying the UE for which the DataRadioBearer is to be created
uint32_t gtpTeid
S1-bearer GTP tunnel endpoint identifier, see 36.423 9.2.1.
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:73