A Discrete-Event Network Simulator
API
epc-sgw-application.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2017-2018 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: Manuel Requena <manuel.requena@cttc.es>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/epc-gtpu-header.h"
23 #include "ns3/epc-sgw-application.h"
24 
25 namespace ns3 {
26 
27 NS_LOG_COMPONENT_DEFINE ("EpcSgwApplication");
28 
29 NS_OBJECT_ENSURE_REGISTERED (EpcSgwApplication);
30 
32  const Ptr<Socket> s5uSocket, const Ptr<Socket> s5cSocket)
33  : m_s5Addr (s5Addr),
34  m_s5uSocket (s5uSocket),
35  m_s5cSocket (s5cSocket),
36  m_s1uSocket (s1uSocket),
37  m_gtpuUdpPort (2152), // fixed by the standard
38  m_gtpcUdpPort (2123), // fixed by the standard
39  m_teidCount (0)
40 {
41  NS_LOG_FUNCTION (this << s1uSocket << s5Addr << s5uSocket << s5cSocket);
45 }
46 
48 {
49  NS_LOG_FUNCTION (this);
50 }
51 
52 void
54 {
55  NS_LOG_FUNCTION (this);
57  m_s1uSocket = 0;
59  m_s5uSocket = 0;
61  m_s5cSocket = 0;
62 }
63 
64 TypeId
66 {
67  static TypeId tid = TypeId ("ns3::EpcSgwApplication")
68  .SetParent<Object> ()
69  .SetGroupName("Lte");
70  return tid;
71 }
72 
73 
74 void
76 {
77  NS_LOG_FUNCTION (this << mmeS11Addr << s11Socket);
78  m_mmeS11Addr = mmeS11Addr;
79  m_s11Socket = s11Socket;
81 }
82 
83 void
85 {
86  NS_LOG_FUNCTION (this << pgwAddr);
87  m_pgwAddr = pgwAddr;
88 }
89 
90 void
91 EpcSgwApplication::AddEnb (uint16_t cellId, Ipv4Address enbAddr, Ipv4Address sgwAddr)
92 {
93  NS_LOG_FUNCTION (this << cellId << enbAddr << sgwAddr);
94  EnbInfo enbInfo;
95  enbInfo.enbAddr = enbAddr;
96  enbInfo.sgwAddr = sgwAddr;
97  m_enbInfoByCellId[cellId] = enbInfo;
98 }
99 
100 
101 void
103 {
104  NS_LOG_FUNCTION (this << socket);
105  NS_ASSERT (socket == m_s11Socket);
106  Ptr<Packet> packet = socket->Recv ();
107  GtpcHeader header;
108  packet->PeekHeader (header);
109  uint16_t msgType = header.GetMessageType ();
110 
111  switch (msgType)
112  {
115  break;
116 
118  DoRecvModifyBearerRequest (packet);
119  break;
120 
122  DoRecvDeleteBearerCommand (packet);
123  break;
124 
127  break;
128 
129  default:
130  NS_FATAL_ERROR ("GTP-C message not supported");
131  break;
132  }
133 }
134 
135 
136 void
138 {
139  NS_LOG_FUNCTION (this << socket);
140  NS_ASSERT (socket == m_s5uSocket);
141  Ptr<Packet> packet = socket->Recv ();
142  GtpuHeader gtpu;
143  packet->RemoveHeader (gtpu);
144  uint32_t teid = gtpu.GetTeid ();
145 
146  Ipv4Address enbAddr = m_enbByTeidMap[teid];
147  NS_LOG_DEBUG ("eNB " << enbAddr << " TEID " << teid);
148  SendToS1uSocket (packet, enbAddr, teid);
149 }
150 
151 void
153 {
154  NS_LOG_FUNCTION (this << socket);
155  NS_ASSERT (socket == m_s5cSocket);
156  Ptr<Packet> packet = socket->Recv ();
157  GtpcHeader header;
158  packet->PeekHeader (header);
159  uint16_t msgType = header.GetMessageType ();
160 
161  switch (msgType)
162  {
165  break;
166 
169  break;
170 
172  DoRecvDeleteBearerRequest (packet);
173  break;
174 
175  default:
176  NS_FATAL_ERROR ("GTP-C message not supported");
177  break;
178  }
179 }
180 
181 void
183 {
184  NS_LOG_FUNCTION (this << socket);
185  NS_ASSERT (socket == m_s1uSocket);
186  Ptr<Packet> packet = socket->Recv ();
187  GtpuHeader gtpu;
188  packet->RemoveHeader (gtpu);
189  uint32_t teid = gtpu.GetTeid ();
190 
191  SendToS5uSocket (packet, m_pgwAddr, teid);
192 }
193 
194 void
196 {
197  NS_LOG_FUNCTION (this << packet << enbAddr << teid);
198 
199  GtpuHeader gtpu;
200  gtpu.SetTeid (teid);
201  // From 3GPP TS 29.281 v10.0.0 Section 5.1
202  // Length of the payload + the non obligatory GTP-U header
203  gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8);
204  packet->AddHeader (gtpu);
205  m_s1uSocket->SendTo (packet, 0, InetSocketAddress (enbAddr, m_gtpuUdpPort));
206 }
207 
208 void
210 {
211  NS_LOG_FUNCTION (this << packet << pgwAddr << teid);
212 
213  GtpuHeader gtpu;
214  gtpu.SetTeid (teid);
215  // From 3GPP TS 29.281 v10.0.0 Section 5.1
216  // Length of the payload + the non obligatory GTP-U header
217  gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8);
218  packet->AddHeader (gtpu);
219  m_s5uSocket->SendTo (packet, 0, InetSocketAddress (pgwAddr, m_gtpuUdpPort));
220 }
221 
222 
224 // Process messages from the MME
226 
227 void
229 {
230  NS_LOG_FUNCTION (this);
231 
233  packet->RemoveHeader (msg);
234  uint64_t imsi = msg.GetImsi ();
235  uint16_t cellId = msg.GetUliEcgi ();
236  NS_LOG_DEBUG ("cellId " << cellId << " IMSI " << imsi);
237 
238  std::map<uint16_t, EnbInfo>::iterator enbit = m_enbInfoByCellId.find (cellId);
239  NS_ASSERT_MSG (enbit != m_enbInfoByCellId.end (), "unknown CellId " << cellId);
240  Ipv4Address enbAddr = enbit->second.enbAddr;
241  NS_LOG_DEBUG ("eNB " << enbAddr);
242 
243  GtpcHeader::Fteid_t mmeS11Fteid = msg.GetSenderCpFteid ();
245  "wrong interface type");
246 
248  msgOut.SetImsi (imsi);
249  msgOut.SetUliEcgi (cellId);
250 
251  GtpcHeader::Fteid_t sgwS5cFteid;
253  sgwS5cFteid.teid = imsi;
254  m_mmeS11FteidBySgwS5cTeid[sgwS5cFteid.teid] = mmeS11Fteid;
255  sgwS5cFteid.addr = m_s5Addr;
256  msgOut.SetSenderCpFteid (sgwS5cFteid); // S5 SGW GTP-C TEID
257 
258  std::list<GtpcCreateSessionRequestMessage::BearerContextToBeCreated> bearerContexts =
260  NS_LOG_DEBUG ("BearerContextToBeCreated size = " << bearerContexts.size ());
261  std::list<GtpcCreateSessionRequestMessage::BearerContextToBeCreated> bearerContextsOut;
262  for (auto &bearerContext : bearerContexts)
263  {
264  // simple sanity check. If you ever need more than 4M teids
265  // throughout your simulation, you'll need to implement a smarter teid
266  // management algorithm.
267  NS_ABORT_IF (m_teidCount == 0xFFFFFFFF);
268  uint32_t teid = ++m_teidCount;
269 
270  NS_LOG_DEBUG (" TEID " << teid);
271  m_enbByTeidMap[teid] = enbAddr;
272 
275  bearerContextOut.sgwS5uFteid.teid = teid; // S5U SGW FTEID
276  bearerContextOut.sgwS5uFteid.addr = enbit->second.sgwAddr;
277  bearerContextOut.epsBearerId = bearerContext.epsBearerId;
278  bearerContextOut.bearerLevelQos = bearerContext.bearerLevelQos;
279  bearerContextOut.tft = bearerContext.tft;
280  bearerContextsOut.push_back (bearerContextOut);
281  }
282 
283  msgOut.SetBearerContextsToBeCreated (bearerContextsOut);
284 
285  msgOut.SetTeid (0);
286  msgOut.ComputeMessageLength ();
287 
288  Ptr<Packet> packetOut = Create <Packet> ();
289  packetOut->AddHeader (msgOut);
290  NS_LOG_DEBUG ("Send CreateSessionRequest to PGW " << m_pgwAddr);
292 }
293 
294 void
296 {
297  NS_LOG_FUNCTION (this);
298 
300  packet->RemoveHeader (msg);
301  uint64_t imsi = msg.GetImsi ();
302  uint16_t cellId = msg.GetUliEcgi ();
303  NS_LOG_DEBUG ("cellId " << cellId << " IMSI " << imsi);
304 
305  std::map<uint16_t, EnbInfo>::iterator enbit = m_enbInfoByCellId.find (cellId);
306  NS_ASSERT_MSG (enbit != m_enbInfoByCellId.end (), "unknown CellId " << cellId);
307  Ipv4Address enbAddr = enbit->second.enbAddr;
308  NS_LOG_DEBUG ("eNB " << enbAddr);
309 
311  msgOut.SetImsi (imsi);
312  msgOut.SetUliEcgi (cellId);
313 
314  std::list<GtpcModifyBearerRequestMessage::BearerContextToBeModified> bearerContextsOut;
315  std::list<GtpcModifyBearerRequestMessage::BearerContextToBeModified> bearerContexts
317  NS_LOG_DEBUG ("BearerContextsToBeModified size = " << bearerContexts.size ());
318  for (auto &bearerContext : bearerContexts)
319  {
320  NS_ASSERT_MSG (bearerContext.fteid.interfaceType == GtpcHeader::S1U_ENB_GTPU,
321  "Wrong FTEID in ModifyBearerRequest msg");
322  uint32_t teid = bearerContext.fteid.teid;
323  Ipv4Address enbAddr = bearerContext.fteid.addr;
324  NS_LOG_DEBUG ("bearerId " << (uint16_t)bearerContext.epsBearerId <<
325  " TEID " << teid);
326  std::map<uint32_t, Ipv4Address>::iterator addrit = m_enbByTeidMap.find (teid);
327  NS_ASSERT_MSG (addrit != m_enbByTeidMap.end (), "unknown TEID " << teid);
328  addrit->second = enbAddr;
330  bearerContextOut.epsBearerId = bearerContext.epsBearerId;
331  bearerContextOut.fteid.interfaceType = GtpcHeader::S5_SGW_GTPU;
332  bearerContextOut.fteid.addr = m_s5Addr;
333  bearerContextOut.fteid.teid = bearerContext.fteid.teid;
334 
335  bearerContextsOut.push_back (bearerContextOut);
336  }
337 
338  msgOut.SetTeid (imsi);
339  msgOut.ComputeMessageLength ();
340 
341  Ptr<Packet> packetOut = Create <Packet> ();
342  packetOut->AddHeader (msgOut);
343  NS_LOG_DEBUG ("Send ModifyBearerRequest to PGW " << m_pgwAddr);
345 }
346 
347 void
349 {
350  NS_LOG_FUNCTION (this);
351 
353  packet->RemoveHeader (msg);
354 
355  std::list<GtpcDeleteBearerCommandMessage::BearerContext> bearerContextsOut;
356  for (auto &bearerContext : msg.GetBearerContexts ())
357  {
358  NS_LOG_DEBUG ("ebid " << (uint16_t) bearerContext.m_epsBearerId);
360  bearerContextOut.m_epsBearerId = bearerContext.m_epsBearerId;
361  bearerContextsOut.push_back (bearerContextOut);
362  }
363 
365  msgOut.SetBearerContexts (bearerContextsOut);
366  msgOut.SetTeid (msg.GetTeid ());
367  msgOut.ComputeMessageLength ();
368 
369  Ptr<Packet> packetOut = Create <Packet> ();
370  packetOut->AddHeader (msgOut);
371  NS_LOG_DEBUG ("Send DeleteBearerCommand to PGW " << m_pgwAddr);
373 }
374 
375 void
377 {
378  NS_LOG_FUNCTION (this);
379 
381  packet->RemoveHeader (msg);
383  msgOut.SetEpsBearerIds (msg.GetEpsBearerIds ());
384  msgOut.SetTeid (msg.GetTeid ());
385  msgOut.ComputeMessageLength ();
386 
387  Ptr<Packet> packetOut = Create <Packet> ();
388  packetOut->AddHeader (msgOut);
389  NS_LOG_DEBUG ("Send DeleteBearerResponse to PGW " << m_pgwAddr);
391 }
392 
393 
395 // Process messages received from the PGW
397 
398 void
400 {
401  NS_LOG_FUNCTION (this);
402 
404  packet->RemoveHeader (msg);
405 
406  GtpcHeader::Fteid_t pgwS5cFteid = msg.GetSenderCpFteid ();
408  "wrong interface type");
409 
412 
413  uint32_t teid = msg.GetTeid ();
415 
416  std::list<GtpcCreateSessionResponseMessage::BearerContextCreated> bearerContexts =
418  NS_LOG_DEBUG ("BearerContextsCreated size = " << bearerContexts.size ());
419  std::list<GtpcCreateSessionResponseMessage::BearerContextCreated> bearerContextsOut;
420  for (auto &bearerContext : bearerContexts)
421  {
423  bearerContextOut.fteid.interfaceType = GtpcHeader::S5_SGW_GTPU;
424  bearerContextOut.fteid.teid = bearerContext.fteid.teid;
425  bearerContextOut.fteid.addr = m_s5Addr;
426  bearerContextOut.epsBearerId = bearerContext.epsBearerId;
427  bearerContextOut.bearerLevelQos = bearerContext.bearerLevelQos;
428  bearerContextOut.tft = bearerContext.tft;
429  bearerContextsOut.push_back (bearerContext);
430  }
431  msgOut.SetBearerContextsCreated (bearerContextsOut);
432 
433  msgOut.SetTeid (mmeS11Fteid.teid);
434  msgOut.ComputeMessageLength ();
435 
436  Ptr<Packet> packetOut = Create <Packet> ();
437  packetOut->AddHeader (msgOut);
438  NS_LOG_DEBUG ("Send CreateSessionResponse to MME " << mmeS11Fteid.addr);
439  m_s11Socket->SendTo (packetOut, 0, InetSocketAddress (mmeS11Fteid.addr, m_gtpcUdpPort));
440 }
441 
442 void
444 {
445  NS_LOG_FUNCTION (this);
446 
448  packet->RemoveHeader (msg);
449 
452  msgOut.SetTeid (msg.GetTeid ());
453  msgOut.ComputeMessageLength ();
454 
455  Ptr<Packet> packetOut = Create <Packet> ();
456  packetOut->AddHeader (msgOut);
457  NS_LOG_DEBUG ("Send ModifyBearerResponse to MME " << m_mmeS11Addr);
459 }
460 
461 void
463 {
464  NS_LOG_FUNCTION (this);
465 
467  packet->RemoveHeader (msg);
468 
470  msgOut.SetEpsBearerIds (msg.GetEpsBearerIds ());
471  msgOut.SetTeid (msg.GetTeid ());
472  msgOut.ComputeMessageLength ();
473 
474  Ptr<Packet> packetOut = Create <Packet> ();
475  packetOut->AddHeader (msgOut);
476  NS_LOG_DEBUG ("Send DeleteBearerRequest to MME " << m_mmeS11Addr);
478 }
479 
480 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
Ptr< Socket > m_s5cSocket
UDP socket to send/receive GTP-C packets to/from the S5 interface.
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 "...
std::list< BearerContextToBeModified > GetBearerContextsToBeModified() const
void AddMme(Ipv4Address mmeS11Addr, Ptr< Socket > s11Socket)
Let the SGW be aware of an MME.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
void RecvFromS1uSocket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the S1-U socket.
void SetBearerContextsToBeCreated(std::list< BearerContextToBeCreated > bearerContexts)
std::list< BearerContextToBeCreated > GetBearerContextsToBeCreated() const
uint32_t m_teidCount
TEID count.
void SetLength(uint16_t length)
Set the length in octets of the payload.
#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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:204
Ptr< Socket > m_s5uSocket
UDP socket to send/receive GTP-U packets to/from the S5 interface.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
virtual uint32_t GetSerializedSize(void) const
Callback< R > MakeNullCallback(void)
Definition: callback.h:1635
static TypeId GetTypeId(void)
Get the type ID.
void ComputeMessageLength(void)
std::map< uint32_t, Ipv4Address > m_enbByTeidMap
Map for eNB address by TEID.
void DoRecvModifyBearerResponse(Ptr< Packet > packet)
Process GTP-C Modify Bearer Response message.
std::list< BearerContext > GetBearerContexts() const
void DoRecvDeleteBearerRequest(Ptr< Packet > packet)
Process GTP-C Delete Bearer Request message.
void SetSenderCpFteid(GtpcHeader::Fteid_t fteid)
Ptr< Socket > m_s11Socket
UDP socket to send/receive control messages to/from the S11 interface.
uint32_t GetTeid() const
Get a tunnel endpoint identificator (TEID)
void SetEpsBearerIds(std::list< uint8_t > epsBearerIds)
std::list< BearerContextCreated > GetBearerContextsCreated() const
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
void SendToS5uSocket(Ptr< Packet > packet, Ipv4Address pgwAddr, uint32_t teid)
Send a data packet to the PGW via the S5 interface.
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:128
InterfaceType_t interfaceType
virtual void DoDispose()
Destructor implementation.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetBearerContexts(std::list< BearerContext > bearerContexts)
Ipv4Address m_s5Addr
SGW address in the S5 interface.
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
void AddPgw(Ipv4Address pgwAddr)
Let the SGW be aware of a PGW.
Ipv4Address sgwAddr
SGW address.
GtpcHeader::Fteid_t GetSenderCpFteid() const
uint16_t m_gtpcUdpPort
UDP port to be used for GTP-C.
Ptr< Socket > m_s1uSocket
UDP socket to send/receive GTP-U packets to/from the S1-U interface.
Ipv4Address m_pgwAddr
PGW address in the S5 interface.
void DoRecvCreateSessionRequest(Ptr< Packet > packet)
Process GTP-C Create Session Request message.
void AddEnb(uint16_t cellId, Ipv4Address enbAddr, Ipv4Address sgwAddr)
Let the SGW be aware of a new eNB.
uint8_t GetMessageType() const
Get message type.
void DoRecvModifyBearerRequest(Ptr< Packet > packet)
Process GTP-C Modify Bearer Request message.
Ptr< EpcTft > tft
Bearer traffic flow template.
std::map< uint32_t, GtpcHeader::Fteid_t > m_mmeS11FteidBySgwS5cTeid
MME S11 FTEID by SGW S5C TEID.
void DoRecvDeleteBearerResponse(Ptr< Packet > packet)
Process GTP-C Delete Bearer Response message.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:77
void DoRecvCreateSessionResponse(Ptr< Packet > packet)
Process GTP-C Create Session Response message.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
void SetTeid(uint32_t teid)
Set TEID function.
void SetTeid(uint32_t teid)
Set TEID.
void SendToS1uSocket(Ptr< Packet > packet, Ipv4Address enbS1uAddress, uint32_t teid)
Send a data packet to an eNB via the S1-U interface.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:272
void RecvFromS5uSocket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the S5-U socket.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
Ipv4Address m_mmeS11Addr
MME address in the S11 interface.
void DoRecvDeleteBearerCommand(Ptr< Packet > packet)
Process GTP-C Delete Bearer Command message.
A base class which provides memory management and object aggregation.
Definition: object.h:87
virtual ~EpcSgwApplication(void)
Destructor.
void RecvFromS5cSocket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the S5-C socket.
Header of the GTPv2-C protocol.
void SetBearerContextsCreated(std::list< BearerContextCreated > bearerContexts)
uint32_t GetTeid() const
Get TEID.
std::list< uint8_t > GetEpsBearerIds() const
std::list< uint8_t > GetEpsBearerIds() const
a unique identifier for an interface.
Definition: type-id.h:58
void RecvFromS11Socket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the S11 socket.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
GtpcHeader::Fteid_t GetSenderCpFteid() const
EpcSgwApplication(const Ptr< Socket > s1uSocket, Ipv4Address s5Addr, const Ptr< Socket > s5uSocket, const Ptr< Socket > s5cSocket)
Constructor that binds callback methods of sockets.
std::map< uint16_t, EnbInfo > m_enbInfoByCellId
Map for eNB info by cell ID.
void SetEpsBearerIds(std::list< uint8_t > epsBearerIds)
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint16_t m_gtpuUdpPort
UDP port to be used for GTP-U.
Implementation of the GPRS Tunnelling Protocol header according to GTPv1-U Release 10 as per 3Gpp TS ...