A Discrete-Event Network Simulator
API
epc-mme-application.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2018 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: Manuel Requena <manuel.requena@cttc.es>
18  */
19 
20 #include "epc-mme-application.h"
21 
22 #include "epc-gtpc-header.h"
23 
24 #include "ns3/log.h"
25 
26 #include <map>
27 
28 namespace ns3
29 {
30 
31 NS_LOG_COMPONENT_DEFINE("EpcMmeApplication");
32 
33 NS_OBJECT_ENSURE_REGISTERED(EpcMmeApplication);
34 
36  : m_gtpcUdpPort(2123) // fixed by the standard
37 {
38  NS_LOG_FUNCTION(this);
40 }
41 
43 {
44  NS_LOG_FUNCTION(this);
45 }
46 
47 void
49 {
50  NS_LOG_FUNCTION(this);
51  delete m_s1apSapMme;
52 }
53 
54 TypeId
56 {
57  static TypeId tid = TypeId("ns3::EpcMmeApplication")
58  .SetParent<Object>()
59  .SetGroupName("Lte")
60  .AddConstructor<EpcMmeApplication>();
61  return tid;
62 }
63 
66 {
67  return m_s1apSapMme;
68 }
69 
70 void
71 EpcMmeApplication::AddSgw(Ipv4Address sgwS11Addr, Ipv4Address mmeS11Addr, Ptr<Socket> mmeS11Socket)
72 {
73  NS_LOG_FUNCTION(this << sgwS11Addr << mmeS11Addr << mmeS11Socket);
74  m_sgwS11Addr = sgwS11Addr;
75  m_mmeS11Addr = mmeS11Addr;
76  m_s11Socket = mmeS11Socket;
78 }
79 
80 void
81 EpcMmeApplication::AddEnb(uint16_t gci, Ipv4Address enbS1uAddr, EpcS1apSapEnb* enbS1apSap)
82 {
83  NS_LOG_FUNCTION(this << gci << enbS1uAddr << enbS1apSap);
84  Ptr<EnbInfo> enbInfo = Create<EnbInfo>();
85  enbInfo->gci = gci;
86  enbInfo->s1uAddr = enbS1uAddr;
87  enbInfo->s1apSapEnb = enbS1apSap;
88  m_enbInfoMap[gci] = enbInfo;
89 }
90 
91 void
93 {
94  NS_LOG_FUNCTION(this << imsi);
95  Ptr<UeInfo> ueInfo = Create<UeInfo>();
96  ueInfo->imsi = imsi;
97  ueInfo->mmeUeS1Id = imsi;
98  ueInfo->bearerCounter = 0;
99  m_ueInfoMap[imsi] = ueInfo;
100 }
101 
102 uint8_t
104 {
105  NS_LOG_FUNCTION(this << imsi);
106  auto it = m_ueInfoMap.find(imsi);
107  NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
108  NS_ASSERT_MSG(it->second->bearerCounter < 11,
109  "too many bearers already! " << it->second->bearerCounter);
110  BearerInfo bearerInfo;
111  bearerInfo.bearerId = ++(it->second->bearerCounter);
112  bearerInfo.tft = tft;
113  bearerInfo.bearer = bearer;
114  it->second->bearersToBeActivated.push_back(bearerInfo);
115  return bearerInfo.bearerId;
116 }
117 
118 // S1-AP SAP MME forwarded methods
119 
120 void
122  uint16_t enbUeS1Id,
123  uint64_t imsi,
124  uint16_t gci)
125 {
126  NS_LOG_FUNCTION(this << mmeUeS1Id << enbUeS1Id << imsi << gci);
127  auto it = m_ueInfoMap.find(imsi);
128  NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
129  it->second->cellId = gci;
130 
132  msg.SetImsi(imsi);
133  msg.SetUliEcgi(gci);
134 
135  GtpcHeader::Fteid_t mmeS11Fteid;
137  mmeS11Fteid.teid = imsi;
138  mmeS11Fteid.addr = m_mmeS11Addr;
139  msg.SetSenderCpFteid(mmeS11Fteid); // S11 MME GTP-C F-TEID
140 
141  std::list<GtpcCreateSessionRequestMessage::BearerContextToBeCreated> bearerContexts;
142  for (auto bit = it->second->bearersToBeActivated.begin();
143  bit != it->second->bearersToBeActivated.end();
144  ++bit)
145  {
147  bearerContext.epsBearerId = bit->bearerId;
148  bearerContext.tft = bit->tft;
149  bearerContext.bearerLevelQos = bit->bearer;
150  bearerContexts.push_back(bearerContext);
151  }
152  NS_LOG_DEBUG("BearerContextToBeCreated size = " << bearerContexts.size());
153  msg.SetBearerContextsToBeCreated(bearerContexts);
154 
155  msg.SetTeid(0);
156  msg.ComputeMessageLength();
157 
158  Ptr<Packet> packet = Create<Packet>();
159  packet->AddHeader(msg);
160  NS_LOG_DEBUG("Send CreateSessionRequest to SGW " << m_sgwS11Addr);
162 }
163 
164 void
166  uint64_t mmeUeS1Id,
167  uint16_t enbUeS1Id,
168  std::list<EpcS1apSapMme::ErabSetupItem> erabSetupList)
169 {
170  NS_LOG_FUNCTION(this << mmeUeS1Id << enbUeS1Id);
171  NS_FATAL_ERROR("unimplemented");
172 }
173 
174 void
176  uint64_t enbUeS1Id,
177  uint64_t mmeUeS1Id,
178  uint16_t gci,
179  std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList)
180 {
181  NS_LOG_FUNCTION(this << mmeUeS1Id << enbUeS1Id << gci);
182  uint64_t imsi = mmeUeS1Id;
183  auto it = m_ueInfoMap.find(imsi);
184  NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
185  NS_LOG_INFO("IMSI " << imsi << " old eNB: " << it->second->cellId << ", new eNB: " << gci);
186  it->second->cellId = gci;
187  it->second->enbUeS1Id = enbUeS1Id;
188 
190  msg.SetImsi(imsi);
191  msg.SetUliEcgi(gci);
192 
193  std::list<GtpcModifyBearerRequestMessage::BearerContextToBeModified> bearerContexts;
194  for (auto& erab : erabToBeSwitchedInDownlinkList)
195  {
196  NS_LOG_DEBUG("erabId " << erab.erabId << " eNB " << erab.enbTransportLayerAddress
197  << " TEID " << erab.enbTeid);
198 
200  bearerContext.epsBearerId = erab.erabId;
202  bearerContext.fteid.addr = erab.enbTransportLayerAddress;
203  bearerContext.fteid.teid = erab.enbTeid;
204  bearerContexts.push_back(bearerContext);
205  }
206  msg.SetBearerContextsToBeModified(bearerContexts);
207  msg.SetTeid(imsi);
208  msg.ComputeMessageLength();
209 
210  Ptr<Packet> packet = Create<Packet>();
211  packet->AddHeader(msg);
212  NS_LOG_DEBUG("Send ModifyBearerRequest to SGW " << m_sgwS11Addr);
214 }
215 
216 void
218  uint64_t mmeUeS1Id,
219  uint16_t enbUeS1Id,
220  std::list<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication)
221 {
222  NS_LOG_FUNCTION(this << mmeUeS1Id << enbUeS1Id);
223  uint64_t imsi = mmeUeS1Id;
224  auto it = m_ueInfoMap.find(imsi);
225  NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
226 
228  std::list<GtpcDeleteBearerCommandMessage::BearerContext> bearerContexts;
229  for (auto& erab : erabToBeReleaseIndication)
230  {
231  NS_LOG_DEBUG("erabId " << (uint16_t)erab.erabId);
233  bearerContext.m_epsBearerId = erab.erabId;
234  bearerContexts.push_back(bearerContext);
235  }
236  msg.SetBearerContexts(bearerContexts);
237  msg.SetTeid(imsi);
238  msg.ComputeMessageLength();
239 
240  Ptr<Packet> packet = Create<Packet>();
241  packet->AddHeader(msg);
242  NS_LOG_DEBUG("Send DeleteBearerCommand to SGW " << m_sgwS11Addr);
244 }
245 
246 void
247 EpcMmeApplication::RemoveBearer(Ptr<UeInfo> ueInfo, uint8_t epsBearerId)
248 {
249  NS_LOG_FUNCTION(this << epsBearerId);
250  auto bit = ueInfo->bearersToBeActivated.begin();
251  while (bit != ueInfo->bearersToBeActivated.end())
252  {
253  if (bit->bearerId == epsBearerId)
254  {
255  ueInfo->bearersToBeActivated.erase(bit);
256  ueInfo->bearerCounter = ueInfo->bearerCounter - 1;
257  break;
258  }
259  ++bit;
260  }
261 }
262 
263 void
265 {
266  NS_LOG_FUNCTION(this << socket);
267  NS_ASSERT(socket == m_s11Socket);
268  Ptr<Packet> packet = socket->Recv();
269  GtpcHeader header;
270  packet->PeekHeader(header);
271  uint16_t msgType = header.GetMessageType();
272 
273  switch (msgType)
274  {
276  DoRecvCreateSessionResponse(header, packet);
277  break;
278 
280  DoRecvModifyBearerResponse(header, packet);
281  break;
282 
284  DoRecvDeleteBearerRequest(header, packet);
285  break;
286 
287  default:
288  NS_FATAL_ERROR("GTP-C message not supported");
289  break;
290  }
291 }
292 
293 void
295 {
296  NS_LOG_FUNCTION(this << header);
297  uint64_t imsi = header.GetTeid();
298  NS_LOG_DEBUG("TEID/IMSI " << imsi);
299  auto it = m_ueInfoMap.find(imsi);
300  NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
301  uint16_t cellId = it->second->cellId;
302  uint16_t enbUeS1Id = it->second->enbUeS1Id;
303  uint64_t mmeUeS1Id = it->second->mmeUeS1Id;
304  NS_LOG_DEBUG("cellId " << cellId << " mmeUeS1Id " << mmeUeS1Id << " enbUeS1Id " << enbUeS1Id);
305  auto jt = m_enbInfoMap.find(cellId);
306  NS_ASSERT_MSG(jt != m_enbInfoMap.end(), "could not find any eNB with CellId " << cellId);
307 
309  packet->RemoveHeader(msg);
310 
311  std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList;
312  std::list<GtpcCreateSessionResponseMessage::BearerContextCreated> bearerContexts =
314  NS_LOG_DEBUG("BearerContextsCreated size = " << bearerContexts.size());
315  for (auto& bearerContext : bearerContexts)
316  {
318  erab.erabId = bearerContext.epsBearerId;
319  erab.erabLevelQosParameters = bearerContext.bearerLevelQos;
320  erab.transportLayerAddress = bearerContext.fteid.addr; // SGW S1U address
321  erab.sgwTeid = bearerContext.fteid.teid;
322  NS_LOG_DEBUG("SGW " << erab.transportLayerAddress << " TEID " << erab.sgwTeid);
323  erabToBeSetupList.push_back(erab);
324  }
325 
326  NS_LOG_DEBUG("Send InitialContextSetupRequest to eNB " << jt->second->s1apSapEnb);
327  jt->second->s1apSapEnb->InitialContextSetupRequest(mmeUeS1Id, enbUeS1Id, erabToBeSetupList);
328 }
329 
330 void
332 {
333  NS_LOG_FUNCTION(this << header);
335  packet->RemoveHeader(msg);
337 
338  uint64_t imsi = header.GetTeid();
339  NS_LOG_DEBUG("TEID/IMSI " << imsi);
340  auto it = m_ueInfoMap.find(imsi);
341  NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
342  uint16_t cellId = it->second->cellId;
343  uint16_t enbUeS1Id = it->second->enbUeS1Id;
344  uint64_t mmeUeS1Id = it->second->mmeUeS1Id;
345  NS_LOG_DEBUG("cellId " << cellId << " mmeUeS1Id " << mmeUeS1Id << " enbUeS1Id " << enbUeS1Id);
346  std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem>
347  erabToBeSwitchedInUplinkList; // unused for now
348  auto jt = m_enbInfoMap.find(cellId);
349  NS_ASSERT_MSG(jt != m_enbInfoMap.end(), "could not find any eNB with CellId " << cellId);
350 
351  NS_LOG_DEBUG("Send PathSwitchRequestAcknowledge to eNB " << jt->second->s1apSapEnb);
352  jt->second->s1apSapEnb->PathSwitchRequestAcknowledge(enbUeS1Id,
353  mmeUeS1Id,
354  cellId,
355  erabToBeSwitchedInUplinkList);
356 }
357 
358 void
360 {
361  NS_LOG_FUNCTION(this << header);
362  uint64_t imsi = header.GetTeid();
363  NS_LOG_DEBUG("TEID/IMSI " << imsi);
364  auto it = m_ueInfoMap.find(imsi);
365  NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
366 
368  packet->RemoveHeader(msg);
369 
371 
372  std::list<uint8_t> epsBearerIds;
373  for (auto& ebid : msg.GetEpsBearerIds())
374  {
375  epsBearerIds.push_back(ebid);
376  /*
377  * This condition is added to not remove bearer info at MME
378  * when UE gets disconnected since the bearers are only added
379  * at beginning of simulation at MME and if it is removed the
380  * bearers cannot be activated again unless scheduled for
381  * addition of the bearer during simulation
382  *
383  */
384  if (it->second->cellId == 0)
385  {
386  RemoveBearer(it->second,
387  ebid); // schedules function to erase, context of de-activated bearer
388  }
389  }
390  msgOut.SetEpsBearerIds(epsBearerIds);
391  msgOut.SetTeid(imsi);
392  msgOut.ComputeMessageLength();
393 
394  Ptr<Packet> packetOut = Create<Packet>();
395  packetOut->AddHeader(msgOut);
396  NS_LOG_DEBUG("Send DeleteBearerResponse to SGW " << m_sgwS11Addr);
398 }
399 
400 } // namespace ns3
This application implements the Mobility Management Entity (MME) according to the 3GPP TS 23....
void AddUe(uint64_t imsi)
Add a new UE to the MME.
void DoPathSwitchRequest(uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list< EpcS1apSapMme::ErabSwitchedInDownlinkItem > erabToBeSwitchedInDownlinkList)
Process the S1 Path Switch Request received from an eNB.
void AddEnb(uint16_t ecgi, Ipv4Address enbS1UAddr, EpcS1apSapEnb *enbS1apSap)
Add a new eNB to the MME.
std::map< uint64_t, Ptr< UeInfo > > m_ueInfoMap
UeInfo stored by IMSI.
void AddSgw(Ipv4Address sgwS11Addr, Ipv4Address mmeS11Addr, Ptr< Socket > mmeS11Socket)
Add a new SGW to the MME.
Ptr< Socket > m_s11Socket
Socket to send/receive messages in the S11 interface.
friend class MemberEpcS1apSapMme< EpcMmeApplication >
allow MemberEpcS1apSapMme<EpcMme> class friend access
EpcS1apSapMme * m_s1apSapMme
EpcS1apSapMme.
Ipv4Address m_mmeS11Addr
IPv4 address of the MME S11 interface.
Ipv4Address m_sgwS11Addr
IPv4 address of the SGW S11 interface.
~EpcMmeApplication() override
Destructor.
void DoInitialContextSetupResponse(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< EpcS1apSapMme::ErabSetupItem > erabSetupList)
Process the S1 Initial Context Setup Response received from an eNB.
void DoInitialUeMessage(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi)
Process the S1 Initial UE Message received from an eNB.
static TypeId GetTypeId()
Get the type ID.
void DoErabReleaseIndication(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< EpcS1apSapMme::ErabToBeReleasedIndication > erabToBeReleaseIndication)
Process ERAB Release Indication received from an eNB.
void DoRecvCreateSessionResponse(GtpcHeader &header, Ptr< Packet > packet)
Process GTP-C Create Session Response message.
void DoRecvDeleteBearerRequest(GtpcHeader &header, Ptr< Packet > packet)
Process GTP-C Delete Bearer Request message.
void DoRecvModifyBearerResponse(GtpcHeader &header, Ptr< Packet > packet)
Process GTP-C Modify Bearer Response message.
std::map< uint16_t, Ptr< EnbInfo > > m_enbInfoMap
EnbInfo stored by EGCI.
void RemoveBearer(Ptr< UeInfo > ueInfo, uint8_t epsBearerId)
This Function erases all contexts of bearer from MME side.
uint8_t AddBearer(uint64_t imsi, Ptr< EpcTft > tft, EpsBearer bearer)
Add an EPS bearer to the list of bearers to be activated for this UE.
uint16_t m_gtpcUdpPort
UDP port for GTP-C protocol. Fixed by the standard to port 2123.
void DoDispose() override
Destructor implementation.
EpcS1apSapMme * GetS1apSapMme()
void RecvFromS11Socket(Ptr< Socket > socket)
Reads the S11 messages from a socket.
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:53
This class contains the specification of EPS Bearers.
Definition: eps-bearer.h:91
GTP-C Create Session Request Message.
void SetUliEcgi(uint32_t uliEcgi)
Set the UliEcgi.
void SetBearerContextsToBeCreated(std::list< BearerContextToBeCreated > bearerContexts)
Set the Bearer Contexts.
void SetImsi(uint64_t imsi)
Set the IMSI.
void SetSenderCpFteid(GtpcHeader::Fteid_t fteid)
Set the Sender CpFteid.
GTP-C Create Session Response Message.
std::list< BearerContextCreated > GetBearerContextsCreated() const
Get the Container of Bearer Contexts.
GTP-C Delete Bearer Command Message.
void SetBearerContexts(std::list< BearerContext > bearerContexts)
Set the Bearer contexts.
GTP-C Delete Bearer Request Message.
std::list< uint8_t > GetEpsBearerIds() const
Get the Bearers IDs.
GTP-C Delete Bearer Response Message.
void SetEpsBearerIds(std::list< uint8_t > epsBearerIds)
Set the Bearers IDs.
Header of the GTPv2-C protocol.
uint8_t GetMessageType() const
Get message type.
void ComputeMessageLength()
Compute the message length according to the message type.
void SetTeid(uint32_t teid)
Set TEID.
uint32_t GetTeid() const
Get TEID.
GTP-C Modify Bearer Request Message.
void SetBearerContextsToBeModified(std::list< BearerContextToBeModified > bearerContexts)
Set the Bearer Contexts.
void SetUliEcgi(uint32_t uliEcgi)
Set the UliEcgi.
void SetImsi(uint64_t imsi)
Set the IMSI.
GTP-C Modify Bearer Response Message.
Cause_t GetCause() const
Get the Cause.
an Inet address class
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
A base class which provides memory management and object aggregation.
Definition: object.h:89
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 PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
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:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
#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_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
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:704
Hold info on an EPS bearer to be activated.
EpsBearer bearer
bearer QOS characteristics
Ptr< EpcTft > tft
traffic flow template
ErabToBeSetupItem structure.
Definition: epc-s1ap-sap.h:148
EpsBearer erabLevelQosParameters
Level QOS parameters.
Definition: epc-s1ap-sap.h:150
Ipv4Address transportLayerAddress
transport layer address
Definition: epc-s1ap-sap.h:151
Ipv4Address addr
IPv4 address.
InterfaceType_t interfaceType
Interface type.