A Discrete-Event Network Simulator
API
 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 
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 
42 {
43  NS_LOG_FUNCTION (this);
44 }
45 
46 void
48 {
49  NS_LOG_FUNCTION (this << tft << teid);
50  return m_tftClassifier.Add (tft, teid);
51 }
52 
53 uint32_t
55 {
56  NS_LOG_FUNCTION (this << p);
57  // we hardcode DOWNLINK direction since the PGW is espected to
58  // classify only downlink packets (uplink packets will go to the
59  // internet without any classification).
60  return m_tftClassifier.Classify (p, EpcTft::DOWNLINK);
61 }
62 
65 {
66  return m_enbAddr;
67 }
68 
69 void
71 {
72  m_enbAddr = enbAddr;
73 }
74 
76 // EpcSgwPgwApplication
78 
79 
80 TypeId
82 {
83  static TypeId tid = TypeId ("ns3::EpcSgwPgwApplication")
84  .SetParent<Object> ();
85  return tid;
86 }
87 
88 void
90 {
92  m_s1uSocket = 0;
93 }
94 
95 
96 
98  : m_s1uSocket (s1uSocket),
99  m_tunDevice (tunDevice),
100  m_gtpuUdpPort (2152), // fixed by the standard
101  m_teidCount (0)
102 {
103  NS_LOG_FUNCTION (this << tunDevice << s1uSocket);
105 }
106 
107 
109 {
111 }
112 
113 
114 uint32_t
116 {
117  NS_LOG_FUNCTION (this << ueAddr << enbAddr << tft);
118 
119  // simple sanity check. If you ever need more than 4M teids
120  // throughout your simulation, you'll need to implement a smarter teid
121  // management algorithm.
122  NS_ABORT_IF (m_teidCount == 0xFFFFFFFF);
123  uint32_t teid = ++m_teidCount;
124 
125  std::map<Ipv4Address, UeInfo>::iterator it = m_ueInfoMap.find (ueAddr);
126  if (it == m_ueInfoMap.end ())
127  {
128  // UE unknown, creating new entry
129  std::pair<std::map<Ipv4Address, UeInfo>::iterator, bool> ret;
130  ret = m_ueInfoMap.insert (std::pair <Ipv4Address, UeInfo> (ueAddr, UeInfo ()));
131  it = ret.first;
132  it->second.SetEnbAddr (enbAddr);
133  }
134 
135  it->second.AddBearer (tft, teid);
136  return teid;
137 }
138 
139 bool
140 EpcSgwPgwApplication::RecvFromTunDevice (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
141 {
142  NS_LOG_FUNCTION (this << source << dest << packet << packet->GetSize ());
143 
144  // get IP address of UE
145  Ptr<Packet> pCopy = packet->Copy ();
146  Ipv4Header ipv4Header;
147  pCopy->RemoveHeader (ipv4Header);
148  Ipv4Address ueAddr = ipv4Header.GetDestination ();
149  NS_LOG_LOGIC ("packet addressed to UE " << ueAddr);
150 
151  // find corresponding UeInfo address
152  std::map<Ipv4Address, UeInfo>::iterator it = m_ueInfoMap.find (ueAddr);
153  if (it == m_ueInfoMap.end ())
154  {
155  NS_LOG_WARN ("unknown UE address " << ueAddr) ;
156  }
157  else
158  {
159  Ipv4Address enbAddr = it->second.GetEnbAddr ();
160  uint32_t teid = it->second.Classify (packet);
161  if (teid == 0)
162  {
163  NS_LOG_WARN ("no matching bearer for this packet");
164  }
165  else
166  {
167  SendToS1uSocket (packet, enbAddr, teid);
168  }
169  }
170  // there is no reason why we should notify the TUN
171  // VirtualNetDevice that he failed to send the packet: if we receive
172  // any bogus packet, it will just be silently discarded.
173  const bool succeeded = true;
174  return succeeded;
175 }
176 
177 void
179 {
180  NS_LOG_FUNCTION (this << socket);
181  NS_ASSERT (socket == m_s1uSocket);
182  Ptr<Packet> packet = socket->Recv ();
183  GtpuHeader gtpu;
184  packet->RemoveHeader (gtpu);
185  uint32_t teid = gtpu.GetTeid ();
186 
187  // workaround for bug 231 https://www.nsnam.org/bugzilla/show_bug.cgi?id=231
188  SocketAddressTag tag;
189  packet->RemovePacketTag (tag);
190 
191  SendToTunDevice (packet, teid);
192 }
193 
194 void
196 {
197  NS_LOG_FUNCTION (this << packet << teid);
198  NS_LOG_LOGIC (" packet size: " << packet->GetSize () << " bytes");
200 }
201 
202 void
204 {
205  NS_LOG_FUNCTION (this << packet << enbAddr << teid);
206 
207  GtpuHeader gtpu;
208  gtpu.SetTeid (teid);
209  // From 3GPP TS 29.281 v10.0.0 Section 5.1
210  // Length of the payload + the non obligatory GTP-U header
211  gtpu.SetLength (packet->GetSize () + gtpu.GetSerializedSize () - 8);
212  packet->AddHeader (gtpu);
213  uint32_t flags = 0;
214  m_s1uSocket->SendTo (packet, flags, InetSocketAddress(enbAddr, m_gtpuUdpPort));
215 }
216 
217 }; // namespace ns3