A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
epc-enb-application.cc
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 
38 
39 EpcEnbApplication::EpsFlowId_t::EpsFlowId_t ()
40 {
41 }
42 
43 EpcEnbApplication::EpsFlowId_t::EpsFlowId_t (const uint16_t a, const uint8_t b)
44  : m_rnti (a),
45  m_bid (b)
46 {
47 }
48 
49 bool
50 operator == (const EpcEnbApplication::EpsFlowId_t &a, const EpcEnbApplication::EpsFlowId_t &b)
51 {
52  return ( (a.m_rnti == b.m_rnti) && (a.m_bid == b.m_bid) );
53 }
54 
55 bool
56 operator < (const EpcEnbApplication::EpsFlowId_t& a, const EpcEnbApplication::EpsFlowId_t& b)
57 {
58  return ( (a.m_rnti < b.m_rnti) || ( (a.m_rnti == b.m_rnti) && (a.m_bid < b.m_bid) ) );
59 }
60 
61 
62 TypeId
63 EpcEnbApplication::GetTypeId (void)
64 {
65  static TypeId tid = TypeId ("ns3::EpcEnbApplication")
66  .SetParent<Object> ();
67  return tid;
68 }
69 
70 void
72 {
73  NS_LOG_FUNCTION (this);
74  m_lteSocket = 0;
75  m_s1uSocket = 0;
76  delete m_s1SapProvider;
77  delete m_s1apSapEnb;
78 }
79 
80 
81 EpcEnbApplication::EpcEnbApplication (Ptr<Socket> lteSocket, Ptr<Socket> s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId)
82  : m_lteSocket (lteSocket),
83  m_s1uSocket (s1uSocket),
84  m_enbS1uAddress (enbS1uAddress),
85  m_sgwS1uAddress (sgwS1uAddress),
86  m_gtpuUdpPort (2152), // fixed by the standard
87  m_s1SapUser (0),
88  m_s1apSapMme (0),
89  m_cellId (cellId)
90 {
91  NS_LOG_FUNCTION (this << lteSocket << s1uSocket << sgwS1uAddress);
96 }
97 
98 
100 {
101  NS_LOG_FUNCTION (this);
102 }
103 
104 
105 void
107 {
108  m_s1SapUser = s;
109 }
110 
111 
114 {
115  return m_s1SapProvider;
116 }
117 
118 void
120 {
121  m_s1apSapMme = s;
122 }
123 
124 
127 {
128  return m_s1apSapEnb;
129 }
130 
131 void
132 EpcEnbApplication::DoInitialUeMessage (uint64_t imsi, uint16_t rnti)
133 {
134  NS_LOG_FUNCTION (this);
135  // side effect: create entry if not exist
136  m_imsiRntiMap[imsi] = rnti;
137  m_s1apSapMme->InitialUeMessage (imsi, rnti, imsi, m_cellId);
138 }
139 
140 void
141 EpcEnbApplication::DoPathSwitchRequest (EpcEnbS1SapProvider::PathSwitchRequestParameters params)
142 {
143  NS_LOG_FUNCTION (this);
144  uint16_t enbUeS1Id = params.rnti;
145  uint64_t mmeUeS1Id = params.mmeUeS1Id;
146  uint64_t imsi = mmeUeS1Id;
147  // side effect: create entry if not exist
148  m_imsiRntiMap[imsi] = params.rnti;
149 
150  uint16_t gci = params.cellId;
151  std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList;
152  for (std::list<EpcEnbS1SapProvider::BearerToBeSwitched>::iterator bit = params.bearersToBeSwitched.begin ();
153  bit != params.bearersToBeSwitched.end ();
154  ++bit)
155  {
156  EpsFlowId_t flowId;
157  flowId.m_rnti = params.rnti;
158  flowId.m_bid = bit->epsBearerId;
159  uint32_t teid = bit->teid;
160 
161  EpsFlowId_t rbid (params.rnti, bit->epsBearerId);
162  // side effect: create entries if not exist
163  m_rbidTeidMap[params.rnti][bit->epsBearerId] = teid;
164  m_teidRbidMap[teid] = rbid;
165 
166  EpcS1apSapMme::ErabSwitchedInDownlinkItem erab;
167  erab.erabId = bit->epsBearerId;
168  erab.enbTransportLayerAddress = m_enbS1uAddress;
169  erab.enbTeid = bit->teid;
170 
171  erabToBeSwitchedInDownlinkList.push_back (erab);
172  }
173  m_s1apSapMme->PathSwitchRequest (enbUeS1Id, mmeUeS1Id, gci, erabToBeSwitchedInDownlinkList);
174 }
175 
176 void
177 EpcEnbApplication::DoUeContextRelease (uint16_t rnti)
178 {
179  NS_LOG_FUNCTION (this << rnti);
180  std::map<uint16_t, std::map<uint8_t, uint32_t> >::iterator rntiIt = m_rbidTeidMap.find (rnti);
181  if (rntiIt != m_rbidTeidMap.end ())
182  {
183  for (std::map<uint8_t, uint32_t>::iterator bidIt = rntiIt->second.begin ();
184  bidIt != rntiIt->second.end ();
185  ++bidIt)
186  {
187  uint32_t teid = bidIt->second;
188  m_teidRbidMap.erase (teid);
189  }
190  m_rbidTeidMap.erase (rntiIt);
191  }
192 }
193 
194 void
195 EpcEnbApplication::DoInitialContextSetupRequest (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList)
196 {
197  NS_LOG_FUNCTION (this);
198 
199  for (std::list<EpcS1apSapEnb::ErabToBeSetupItem>::iterator erabIt = erabToBeSetupList.begin ();
200  erabIt != erabToBeSetupList.end ();
201  ++erabIt)
202  {
203  // request the RRC to setup a radio bearer
204 
205  uint64_t imsi = mmeUeS1Id;
206  std::map<uint64_t, uint16_t>::iterator imsiIt = m_imsiRntiMap.find (imsi);
207  NS_ASSERT_MSG (imsiIt != m_imsiRntiMap.end (), "unknown IMSI");
208  uint16_t rnti = imsiIt->second;
209 
210  struct EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params;
211  params.rnti = rnti;
212  params.bearer = erabIt->erabLevelQosParameters;
213  params.bearerId = erabIt->erabId;
214  params.gtpTeid = erabIt->sgwTeid;
216 
217  EpsFlowId_t rbid (rnti, erabIt->erabId);
218  // side effect: create entries if not exist
219  m_rbidTeidMap[rnti][erabIt->erabId] = params.gtpTeid;
220  m_teidRbidMap[params.gtpTeid] = rbid;
221 
222  }
223 }
224 
225 void
226 EpcEnbApplication::DoPathSwitchRequestAcknowledge (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList)
227 {
228  NS_LOG_FUNCTION (this);
229 
230  uint64_t imsi = mmeUeS1Id;
231  std::map<uint64_t, uint16_t>::iterator imsiIt = m_imsiRntiMap.find (imsi);
232  NS_ASSERT_MSG (imsiIt != m_imsiRntiMap.end (), "unknown IMSI");
233  uint16_t rnti = imsiIt->second;
234  EpcEnbS1SapUser::PathSwitchRequestAcknowledgeParameters params;
235  params.rnti = rnti;
236  m_s1SapUser->PathSwitchRequestAcknowledge (params);
237 }
238 
239 void
241 {
242  NS_LOG_FUNCTION (this);
243  NS_ASSERT (socket == m_lteSocket);
244  Ptr<Packet> packet = socket->Recv ();
245 
246  // workaround for bug 231 https://www.nsnam.org/bugzilla/show_bug.cgi?id=231
247  SocketAddressTag satag;
248  packet->RemovePacketTag (satag);
249 
250  EpsBearerTag tag;
251  bool found = packet->RemovePacketTag (tag);
252  NS_ASSERT (found);
253  uint16_t rnti = tag.GetRnti ();
254  uint8_t bid = tag.GetBid ();
255  NS_LOG_LOGIC ("received packet with RNTI=" << (uint32_t) rnti << ", BID=" << (uint32_t) bid);
256  std::map<uint16_t, std::map<uint8_t, uint32_t> >::iterator rntiIt = m_rbidTeidMap.find (rnti);
257  if (rntiIt == m_rbidTeidMap.end ())
258  {
259  NS_LOG_WARN ("UE context not found, discarding packet");
260  }
261  else
262  {
263  std::map<uint8_t, uint32_t>::iterator bidIt = rntiIt->second.find (bid);
264  NS_ASSERT (bidIt != rntiIt->second.end ());
265  uint32_t teid = bidIt->second;
266  SendToS1uSocket (packet, teid);
267  }
268 }
269 
270 void
272 {
273  NS_LOG_FUNCTION (this << socket);
274  NS_ASSERT (socket == m_s1uSocket);
275  Ptr<Packet> packet = socket->Recv ();
276  GtpuHeader gtpu;
277  packet->RemoveHeader (gtpu);
278  uint32_t teid = gtpu.GetTeid ();
279  std::map<uint32_t, EpsFlowId_t>::iterator it = m_teidRbidMap.find (teid);
280  NS_ASSERT (it != m_teidRbidMap.end ());
281 
282  // workaround for bug 231 https://www.nsnam.org/bugzilla/show_bug.cgi?id=231
283  SocketAddressTag tag;
284  packet->RemovePacketTag (tag);
285 
286  SendToLteSocket (packet, it->second.m_rnti, it->second.m_bid);
287 }
288 
289 void
290 EpcEnbApplication::SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t bid)
291 {
292  NS_LOG_FUNCTION (this << packet << rnti << (uint16_t) bid << packet->GetSize ());
293  EpsBearerTag tag (rnti, bid);
294  packet->AddPacketTag (tag);
295  int sentBytes = m_lteSocket->Send (packet);
296  NS_ASSERT (sentBytes > 0);
297 }
298 
299 
300 void
302 {
303  NS_LOG_FUNCTION (this << packet << teid << packet->GetSize ());
304  GtpuHeader gtpu;
305  gtpu.SetTeid (teid);
306  // From 3GPP TS 29.281 v10.0.0 Section 5.1
307  // Length of the payload + the non obligatory GTP-U header
308  gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8);
309  packet->AddHeader (gtpu);
310  uint32_t flags = 0;
312 }
313 
314 
315 }; // namespace ns3
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
an Inet address class
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
EpcEnbApplication(Ptr< Socket > lteSocket, Ptr< Socket > s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress, uint16_t cellId)
virtual void DataRadioBearerSetupRequest(DataRadioBearerSetupRequestParameters params)=0
void AddPacketTag(const Tag &tag) const
Definition: packet.cc:868
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
void SendToLteSocket(Ptr< Packet > packet, uint16_t rnti, uint8_t bid)
EpcS1apSapEnb * GetS1apSapEnb()
void SendToS1uSocket(Ptr< Packet > packet, uint32_t teid)
void SetS1SapUser(EpcEnbS1SapUser *s)
This class implements a tag that carries an address of a packet across the socket interface...
Definition: socket.h:847
virtual void PathSwitchRequest(uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list< ErabSwitchedInDownlinkItem > erabToBeSwitchedInDownlinkList)=0
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:127
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
void RecvFromLteSocket(Ptr< Socket > socket)
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
EpcEnbS1SapProvider * GetS1SapProvider()
void RecvFromS1uSocket(Ptr< Socket > socket)
EpcEnbS1SapUser * m_s1SapUser
std::map< uint32_t, EpsFlowId_t > m_teidRbidMap
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
virtual void InitialUeMessage(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi)=0
#define NS_LOG_WARN(msg)
Definition: log.h:246
bool RemovePacketTag(Tag &tag)
Definition: packet.cc:874
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
void SetS1apSapMme(EpcS1apSapMme *s)
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
std::map< uint16_t, std::map< uint8_t, uint32_t > > m_rbidTeidMap
std::map< uint64_t, uint16_t > m_imsiRntiMap
void AddHeader(const Header &header)
Definition: packet.cc:270
EpcEnbS1SapProvider * m_s1SapProvider