A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Groups
Pages
epc-sgw-pgw-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-sgw-pgw-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/epc-gtpu-header.h"
29
#include "ns3/abort.h"
30
31
namespace
ns3 {
32
33
NS_LOG_COMPONENT_DEFINE
(
"EpcSgwPgwApplication"
);
34
35
37
// UeInfo
39
40
41
EpcSgwPgwApplication::UeInfo::UeInfo
()
42
{
43
NS_LOG_FUNCTION
(
this
);
44
}
45
46
void
47
EpcSgwPgwApplication::UeInfo::AddBearer
(
Ptr<EpcTft>
tft, uint8_t bearerId, uint32_t teid)
48
{
49
NS_LOG_FUNCTION
(
this
<< tft << teid);
50
m_teidByBearerIdMap[bearerId] = teid;
51
return
m_tftClassifier.Add (tft, teid);
52
}
53
54
uint32_t
55
EpcSgwPgwApplication::UeInfo::Classify
(
Ptr<Packet>
p)
56
{
57
NS_LOG_FUNCTION
(
this
<< p);
58
// we hardcode DOWNLINK direction since the PGW is espected to
59
// classify only downlink packets (uplink packets will go to the
60
// internet without any classification).
61
return
m_tftClassifier.Classify (p,
EpcTft::DOWNLINK
);
62
}
63
64
Ipv4Address
65
EpcSgwPgwApplication::UeInfo::GetEnbAddr
()
66
{
67
return
m_enbAddr;
68
}
69
70
void
71
EpcSgwPgwApplication::UeInfo::SetEnbAddr
(
Ipv4Address
enbAddr)
72
{
73
m_enbAddr = enbAddr;
74
}
75
76
Ipv4Address
77
EpcSgwPgwApplication::UeInfo::GetUeAddr
()
78
{
79
return
m_ueAddr;
80
}
81
82
void
83
EpcSgwPgwApplication::UeInfo::SetUeAddr
(
Ipv4Address
ueAddr)
84
{
85
m_ueAddr = ueAddr;
86
}
87
89
// EpcSgwPgwApplication
91
92
93
TypeId
94
EpcSgwPgwApplication::GetTypeId
(
void
)
95
{
96
static
TypeId
tid =
TypeId
(
"ns3::EpcSgwPgwApplication"
)
97
.
SetParent
<
Object
> ();
98
return
tid;
99
}
100
101
void
102
EpcSgwPgwApplication::DoDispose
()
103
{
104
NS_LOG_FUNCTION
(
this
);
105
m_s1uSocket
->
SetRecvCallback
(
MakeNullCallback
<
void
,
Ptr<Socket>
> ());
106
m_s1uSocket
= 0;
107
delete
(
m_s11SapSgw
);
108
}
109
110
111
112
EpcSgwPgwApplication::EpcSgwPgwApplication
(
const
Ptr<VirtualNetDevice>
tunDevice,
const
Ptr<Socket>
s1uSocket)
113
:
m_s1uSocket
(s1uSocket),
114
m_tunDevice
(tunDevice),
115
m_gtpuUdpPort
(2152),
// fixed by the standard
116
m_teidCount
(0),
117
m_s11SapMme
(0)
118
{
119
NS_LOG_FUNCTION
(
this
<< tunDevice << s1uSocket);
120
m_s1uSocket
->
SetRecvCallback
(
MakeCallback
(&
EpcSgwPgwApplication::RecvFromS1uSocket
,
this
));
121
m_s11SapSgw
=
new
MemberEpcS11SapSgw<EpcSgwPgwApplication>
(
this
);
122
}
123
124
125
EpcSgwPgwApplication::~EpcSgwPgwApplication
()
126
{
127
NS_LOG_FUNCTION
(
this
);
128
}
129
130
131
bool
132
EpcSgwPgwApplication::RecvFromTunDevice
(
Ptr<Packet>
packet,
const
Address
& source,
const
Address
& dest, uint16_t protocolNumber)
133
{
134
NS_LOG_FUNCTION
(
this
<< source << dest << packet << packet->
GetSize
());
135
136
// get IP address of UE
137
Ptr<Packet>
pCopy = packet->
Copy
();
138
Ipv4Header
ipv4Header;
139
pCopy->RemoveHeader (ipv4Header);
140
Ipv4Address
ueAddr = ipv4Header.
GetDestination
();
141
NS_LOG_LOGIC
(
"packet addressed to UE "
<< ueAddr);
142
143
// find corresponding UeInfo address
144
std::map<Ipv4Address, Ptr<UeInfo> >::iterator it =
m_ueInfoByAddrMap
.find (ueAddr);
145
if
(it ==
m_ueInfoByAddrMap
.end ())
146
{
147
NS_LOG_WARN
(
"unknown UE address "
<< ueAddr) ;
148
}
149
else
150
{
151
Ipv4Address
enbAddr = it->second->GetEnbAddr ();
152
uint32_t teid = it->second->Classify (packet);
153
if
(teid == 0)
154
{
155
NS_LOG_WARN
(
"no matching bearer for this packet"
);
156
}
157
else
158
{
159
SendToS1uSocket
(packet, enbAddr, teid);
160
}
161
}
162
// there is no reason why we should notify the TUN
163
// VirtualNetDevice that he failed to send the packet: if we receive
164
// any bogus packet, it will just be silently discarded.
165
const
bool
succeeded =
true
;
166
return
succeeded;
167
}
168
169
void
170
EpcSgwPgwApplication::RecvFromS1uSocket
(
Ptr<Socket>
socket)
171
{
172
NS_LOG_FUNCTION
(
this
<< socket);
173
NS_ASSERT
(socket ==
m_s1uSocket
);
174
Ptr<Packet>
packet = socket->
Recv
();
175
GtpuHeader
gtpu;
176
packet->
RemoveHeader
(gtpu);
177
uint32_t teid = gtpu.
GetTeid
();
178
179
// workaround for bug 231 https://www.nsnam.org/bugzilla/show_bug.cgi?id=231
180
SocketAddressTag
tag;
181
packet->
RemovePacketTag
(tag);
182
183
SendToTunDevice
(packet, teid);
184
}
185
186
void
187
EpcSgwPgwApplication::SendToTunDevice
(
Ptr<Packet>
packet, uint32_t teid)
188
{
189
NS_LOG_FUNCTION
(
this
<< packet << teid);
190
NS_LOG_LOGIC
(
" packet size: "
<< packet->
GetSize
() <<
" bytes"
);
191
m_tunDevice
->
Receive
(packet, 0x0800,
m_tunDevice
->
GetAddress
(),
m_tunDevice
->
GetAddress
(),
NetDevice::PACKET_HOST
);
192
}
193
194
void
195
EpcSgwPgwApplication::SendToS1uSocket
(
Ptr<Packet>
packet,
Ipv4Address
enbAddr, uint32_t teid)
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
uint32_t flags = 0;
206
m_s1uSocket
->
SendTo
(packet, flags,
InetSocketAddress
(enbAddr,
m_gtpuUdpPort
));
207
}
208
209
210
void
211
EpcSgwPgwApplication::SetS11SapMme
(
EpcS11SapMme
* s)
212
{
213
m_s11SapMme
= s;
214
}
215
216
EpcS11SapSgw
*
217
EpcSgwPgwApplication::GetS11SapSgw
()
218
{
219
return
m_s11SapSgw
;
220
}
221
222
void
223
EpcSgwPgwApplication::AddEnb
(uint16_t cellId,
Ipv4Address
enbAddr,
Ipv4Address
sgwAddr)
224
{
225
NS_LOG_FUNCTION
(
this
<< cellId << enbAddr << sgwAddr);
226
EnbInfo
enbInfo;
227
enbInfo.
enbAddr
= enbAddr;
228
enbInfo.
sgwAddr
= sgwAddr;
229
m_enbInfoByCellId
[cellId] = enbInfo;
230
}
231
232
void
233
EpcSgwPgwApplication::AddUe
(uint64_t imsi)
234
{
235
NS_LOG_FUNCTION
(
this
<< imsi);
236
Ptr<UeInfo>
ueInfo = Create<UeInfo> ();
237
m_ueInfoByImsiMap
[imsi] = ueInfo;
238
}
239
240
void
241
EpcSgwPgwApplication::SetUeAddress
(uint64_t imsi,
Ipv4Address
ueAddr)
242
{
243
NS_LOG_FUNCTION
(
this
<< imsi << ueAddr);
244
std::map<uint64_t, Ptr<UeInfo> >::iterator ueit =
m_ueInfoByImsiMap
.find (imsi);
245
NS_ASSERT_MSG
(ueit !=
m_ueInfoByImsiMap
.end (),
"unknown IMSI "
<< imsi);
246
m_ueInfoByAddrMap
[ueAddr] = ueit->second;
247
ueit->second->SetUeAddr (ueAddr);
248
}
249
250
void
251
EpcSgwPgwApplication::DoCreateSessionRequest
(
EpcS11SapSgw::CreateSessionRequestMessage
req)
252
{
253
NS_LOG_FUNCTION
(
this
<< req.
imsi
);
254
std::map<uint64_t, Ptr<UeInfo> >::iterator ueit =
m_ueInfoByImsiMap
.find (req.
imsi
);
255
NS_ASSERT_MSG
(ueit !=
m_ueInfoByImsiMap
.end (),
"unknown IMSI "
<< req.
imsi
);
256
uint16_t cellId = req.
uli
.gci;
257
std::map<uint16_t, EnbInfo>::iterator enbit =
m_enbInfoByCellId
.find (cellId);
258
NS_ASSERT_MSG
(enbit !=
m_enbInfoByCellId
.end (),
"unknown CellId "
<< cellId);
259
Ipv4Address
enbAddr = enbit->second.enbAddr;
260
ueit->second->SetEnbAddr (enbAddr);
261
262
EpcS11SapMme::CreateSessionResponseMessage
res;
263
res.teid = req.
imsi
;
// trick to avoid the need for allocating TEIDs on the S11 interface
264
265
for
(std::list<EpcS11SapSgw::BearerContextToBeCreated>::iterator bit = req.
bearerContextsToBeCreated
.begin ();
266
bit != req.
bearerContextsToBeCreated
.end ();
267
++bit)
268
{
269
// simple sanity check. If you ever need more than 4M teids
270
// throughout your simulation, you'll need to implement a smarter teid
271
// management algorithm.
272
NS_ABORT_IF
(
m_teidCount
== 0xFFFFFFFF);
273
uint32_t teid = ++
m_teidCount
;
274
ueit->second->AddBearer (bit->tft, bit->epsBearerId, teid);
275
276
EpcS11SapMme::BearerContextCreated
bearerContext;
277
bearerContext.
sgwFteid
.
teid
= teid;
278
bearerContext.
sgwFteid
.
address
= enbit->second.sgwAddr;
279
bearerContext.
epsBearerId
= bit->epsBearerId;
280
bearerContext.
bearerLevelQos
= bit->bearerLevelQos;
281
bearerContext.
tft
= bit->tft;
282
res.
bearerContextsCreated
.push_back (bearerContext);
283
}
284
m_s11SapMme
->
CreateSessionResponse
(res);
285
286
}
287
288
void
289
EpcSgwPgwApplication::DoModifyBearerRequest
(
EpcS11SapSgw::ModifyBearerRequestMessage
req)
290
{
291
NS_LOG_FUNCTION
(
this
<< req.
teid
);
292
uint64_t imsi = req.
teid
;
// trick to avoid the need for allocating TEIDs on the S11 interface
293
std::map<uint64_t, Ptr<UeInfo> >::iterator ueit =
m_ueInfoByImsiMap
.find (imsi);
294
NS_ASSERT_MSG
(ueit !=
m_ueInfoByImsiMap
.end (),
"unknown IMSI "
<< imsi);
295
uint16_t cellId = req.
uli
.
gci
;
296
std::map<uint16_t, EnbInfo>::iterator enbit =
m_enbInfoByCellId
.find (cellId);
297
NS_ASSERT_MSG
(enbit !=
m_enbInfoByCellId
.end (),
"unknown CellId "
<< cellId);
298
Ipv4Address
enbAddr = enbit->second.enbAddr;
299
ueit->second->SetEnbAddr (enbAddr);
300
// no actual bearer modification: for now we just support the minimum needed for path switch request (handover)
301
EpcS11SapMme::ModifyBearerResponseMessage
res;
302
res.teid = imsi;
// trick to avoid the need for allocating TEIDs on the S11 interface
303
res.
cause
=
EpcS11SapMme::ModifyBearerResponseMessage::REQUEST_ACCEPTED
;
304
m_s11SapMme
->
ModifyBearerResponse
(res);
305
}
306
307
};
// namespace ns3
src
lte
model
epc-sgw-pgw-application.cc
Generated on Tue May 14 2013 11:08:24 for ns-3 by
1.8.1.2