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, Ptr<Socket> s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId)
91  : m_lteSocket (lteSocket),
92  m_lteSocket6 (lteSocket6),
93  m_s1uSocket (s1uSocket),
94  m_enbS1uAddress (enbS1uAddress),
95  m_sgwS1uAddress (sgwS1uAddress),
96  m_gtpuUdpPort (2152), // fixed by the standard
97  m_s1SapUser (0),
98  m_s1apSapMme (0),
99  m_cellId (cellId)
100 {
101  NS_LOG_FUNCTION (this << lteSocket << s1uSocket << sgwS1uAddress);
107 }
108 
109 
111 {
112  NS_LOG_FUNCTION (this);
113 }
114 
115 
116 void
118 {
119  m_s1SapUser = s;
120 }
121 
122 
125 {
126  return m_s1SapProvider;
127 }
128 
129 void
131 {
132  m_s1apSapMme = s;
133 }
134 
135 
138 {
139  return m_s1apSapEnb;
140 }
141 
142 void
143 EpcEnbApplication::DoInitialUeMessage (uint64_t imsi, uint16_t rnti)
144 {
145  NS_LOG_FUNCTION (this);
146  // side effect: create entry if not exist
147  m_imsiRntiMap[imsi] = rnti;
148  m_s1apSapMme->InitialUeMessage (imsi, rnti, imsi, m_cellId);
149 }
150 
151 void
153 {
154  NS_LOG_FUNCTION (this);
155  uint16_t enbUeS1Id = params.rnti;
156  uint64_t mmeUeS1Id = params.mmeUeS1Id;
157  uint64_t imsi = mmeUeS1Id;
158  // side effect: create entry if not exist
159  m_imsiRntiMap[imsi] = params.rnti;
160 
161  uint16_t gci = params.cellId;
162  std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList;
163  for (std::list<EpcEnbS1SapProvider::BearerToBeSwitched>::iterator bit = params.bearersToBeSwitched.begin ();
164  bit != params.bearersToBeSwitched.end ();
165  ++bit)
166  {
167  EpsFlowId_t flowId;
168  flowId.m_rnti = params.rnti;
169  flowId.m_bid = bit->epsBearerId;
170  uint32_t teid = bit->teid;
171 
172  EpsFlowId_t rbid (params.rnti, bit->epsBearerId);
173  // side effect: create entries if not exist
174  m_rbidTeidMap[params.rnti][bit->epsBearerId] = teid;
175  m_teidRbidMap[teid] = rbid;
176 
178  erab.erabId = bit->epsBearerId;
180  erab.enbTeid = bit->teid;
181 
182  erabToBeSwitchedInDownlinkList.push_back (erab);
183  }
184  m_s1apSapMme->PathSwitchRequest (enbUeS1Id, mmeUeS1Id, gci, erabToBeSwitchedInDownlinkList);
185 }
186 
187 void
189 {
190  NS_LOG_FUNCTION (this << rnti);
191  std::map<uint16_t, std::map<uint8_t, uint32_t> >::iterator rntiIt = m_rbidTeidMap.find (rnti);
192  if (rntiIt != m_rbidTeidMap.end ())
193  {
194  for (std::map<uint8_t, uint32_t>::iterator bidIt = rntiIt->second.begin ();
195  bidIt != rntiIt->second.end ();
196  ++bidIt)
197  {
198  uint32_t teid = bidIt->second;
199  m_teidRbidMap.erase (teid);
200  }
201  m_rbidTeidMap.erase (rntiIt);
202  }
203 }
204 
205 void
206 EpcEnbApplication::DoInitialContextSetupRequest (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList)
207 {
208  NS_LOG_FUNCTION (this);
209 
210  for (std::list<EpcS1apSapEnb::ErabToBeSetupItem>::iterator erabIt = erabToBeSetupList.begin ();
211  erabIt != erabToBeSetupList.end ();
212  ++erabIt)
213  {
214  // request the RRC to setup a radio bearer
215 
216  uint64_t imsi = mmeUeS1Id;
217  std::map<uint64_t, uint16_t>::iterator imsiIt = m_imsiRntiMap.find (imsi);
218  NS_ASSERT_MSG (imsiIt != m_imsiRntiMap.end (), "unknown IMSI");
219  uint16_t rnti = imsiIt->second;
220 
222  params.rnti = rnti;
223  params.bearer = erabIt->erabLevelQosParameters;
224  params.bearerId = erabIt->erabId;
225  params.gtpTeid = erabIt->sgwTeid;
227 
228  EpsFlowId_t rbid (rnti, erabIt->erabId);
229  // side effect: create entries if not exist
230  m_rbidTeidMap[rnti][erabIt->erabId] = params.gtpTeid;
231  m_teidRbidMap[params.gtpTeid] = rbid;
232 
233  }
234 }
235 
236 void
237 EpcEnbApplication::DoPathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList)
238 {
239  NS_LOG_FUNCTION (this);
240 
241  uint64_t imsi = mmeUeS1Id;
242  std::map<uint64_t, uint16_t>::iterator imsiIt = m_imsiRntiMap.find (imsi);
243  NS_ASSERT_MSG (imsiIt != m_imsiRntiMap.end (), "unknown IMSI");
244  uint16_t rnti = imsiIt->second;
246  params.rnti = rnti;
248 }
249 
250 void
252 {
253  NS_LOG_FUNCTION (this);
254  if(m_lteSocket6)
255  {
256  NS_ASSERT (socket == m_lteSocket || socket == m_lteSocket6);
257  }
258  else
259  {
260  NS_ASSERT (socket == m_lteSocket);
261  }
262  Ptr<Packet> packet = socket->Recv ();
263 
264  EpsBearerTag tag;
265  bool found = packet->RemovePacketTag (tag);
266  NS_ASSERT (found);
267  uint16_t rnti = tag.GetRnti ();
268  uint8_t bid = tag.GetBid ();
269  NS_LOG_LOGIC ("received packet with RNTI=" << (uint32_t) rnti << ", BID=" << (uint32_t) bid);
270  std::map<uint16_t, std::map<uint8_t, uint32_t> >::iterator rntiIt = m_rbidTeidMap.find (rnti);
271  if (rntiIt == m_rbidTeidMap.end ())
272  {
273  NS_LOG_WARN ("UE context not found, discarding packet");
274  }
275  else
276  {
277  std::map<uint8_t, uint32_t>::iterator bidIt = rntiIt->second.find (bid);
278  NS_ASSERT (bidIt != rntiIt->second.end ());
279  uint32_t teid = bidIt->second;
280  m_rxLteSocketPktTrace (packet->Copy ());
281  SendToS1uSocket (packet, teid);
282  }
283 }
284 
285 void
287 {
288  NS_LOG_FUNCTION (this << socket);
289  NS_ASSERT (socket == m_s1uSocket);
290  Ptr<Packet> packet = socket->Recv ();
291  GtpuHeader gtpu;
292  packet->RemoveHeader (gtpu);
293  uint32_t teid = gtpu.GetTeid ();
294  std::map<uint32_t, EpsFlowId_t>::iterator it = m_teidRbidMap.find (teid);
295  NS_ASSERT (it != m_teidRbidMap.end ());
296 
297  m_rxS1uSocketPktTrace (packet->Copy ());
298  SendToLteSocket (packet, it->second.m_rnti, it->second.m_bid);
299 }
300 
301 void
302 EpcEnbApplication::SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t bid)
303 {
304  NS_LOG_FUNCTION (this << packet << rnti << (uint16_t) bid << packet->GetSize ());
305  EpsBearerTag tag (rnti, bid);
306  packet->AddPacketTag (tag);
307  uint8_t ipType;
308 
309  packet->CopyData (&ipType, 1);
310  ipType = (ipType>>4) & 0x0f;
311 
312  int sentBytes;
313  if (ipType == 0x04)
314  {
315  sentBytes = m_lteSocket->Send (packet);
316  }
317  else if (ipType == 0x06)
318  {
319  sentBytes = m_lteSocket6->Send (packet);
320  }
321  else
322  {
323  NS_ABORT_MSG ("EpcEnbApplication::SendToLteSocket - Unknown IP type...");
324  }
325 
326  NS_ASSERT (sentBytes > 0);
327 }
328 
329 
330 void
332 {
333  NS_LOG_FUNCTION (this << packet << teid << packet->GetSize ());
334  GtpuHeader gtpu;
335  gtpu.SetTeid (teid);
336  // From 3GPP TS 29.281 v10.0.0 Section 5.1
337  // Length of the payload + the non obligatory GTP-U header
338  gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8);
339  packet->AddHeader (gtpu);
340  uint32_t flags = 0;
342 }
343 
344 void
345 EpcEnbApplication::DoReleaseIndication (uint64_t imsi, uint16_t rnti, uint8_t bearerId)
346 {
347  NS_LOG_FUNCTION (this << bearerId );
348  std::list<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication;
350  erab.erabId = bearerId;
351  erabToBeReleaseIndication.push_back (erab);
352  //From 3GPP TS 23401-950 Section 5.4.4.2, enB sends EPS bearer Identity in Bearer Release Indication message to MME
353  m_s1apSapMme->ErabReleaseIndication (imsi, rnti, erabToBeReleaseIndication);
354 }
355 
356 } // 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:831
virtual void DataRadioBearerSetupRequest(DataRadioBearerSetupRequestParameters params)=0
request the setup of a DataRadioBearer
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
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:202
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 ...
EpsBearer bearer
the characteristics of the bearer to be set up
Ptr< Socket > m_lteSocket
raw packet socket to send and receive the packets to and from the LTE radio interface ...
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:153
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.
EpcEnbApplication(Ptr< Socket > lteSocket, Ptr< Socket > lteSocket6, Ptr< Socket > s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId)
Constructor.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
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
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
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
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:852
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:262
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:859
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:135
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
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
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.
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.