A Discrete-Event Network Simulator
API
epc-tft-classifier.cc
Go to the documentation of this file.
1/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2011 CTTC
4 * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation;
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Authors:
20 * Nicola Baldo <nbaldo@cttc.es> (the EpcTftClassifier class)
21 * Giuseppe Piro <g.piro@poliba.it> (part of the code in EpcTftClassifier::Classify ()
22 * which comes from RrcEntity::Classify of the GSoC 2010 LTE module)
23 *
24 */
25
26#include "epc-tft-classifier.h"
27#include "epc-tft.h"
28#include "ns3/log.h"
29#include "ns3/packet.h"
30#include "ns3/ipv4-header.h"
31#include "ns3/ipv6-header.h"
32#include "ns3/udp-header.h"
33#include "ns3/tcp-header.h"
34#include "ns3/ipv4-l3-protocol.h"
35#include "ns3/icmpv4-l4-protocol.h"
36#include "ns3/udp-l4-protocol.h"
37#include "ns3/tcp-l4-protocol.h"
38#include "ns3/ipv6-l3-protocol.h"
39#include "ns3/icmpv6-l4-protocol.h"
40
41namespace ns3 {
42
43NS_LOG_COMPONENT_DEFINE ("EpcTftClassifier");
44
46{
47 NS_LOG_FUNCTION (this);
48}
49
50void
52{
53 NS_LOG_FUNCTION (this << tft << id);
54 m_tftMap[id] = tft;
55
56 // simple sanity check: there shouldn't be more than 16 bearers (hence TFTs) per UE
57 NS_ASSERT (m_tftMap.size () <= 16);
58}
59
60void
62{
63 NS_LOG_FUNCTION (this << id);
64 m_tftMap.erase (id);
65}
66
68EpcTftClassifier::Classify (Ptr<Packet> p, EpcTft::Direction direction, uint16_t protocolNumber)
69{
70 NS_LOG_FUNCTION (this << p << p->GetSize () << direction);
71
72 Ptr<Packet> pCopy = p->Copy ();
73
74 Ipv4Address localAddressIpv4;
75 Ipv4Address remoteAddressIpv4;
76
77 Ipv6Address localAddressIpv6;
78 Ipv6Address remoteAddressIpv6;
79
80 uint8_t protocol;
81 uint8_t tos;
82
83 uint16_t localPort = 0;
84 uint16_t remotePort = 0;
85
86 if (protocolNumber == Ipv4L3Protocol::PROT_NUMBER)
87 {
88 Ipv4Header ipv4Header;
89 pCopy->RemoveHeader (ipv4Header);
90
91 if (direction == EpcTft::UPLINK)
92 {
93 localAddressIpv4 = ipv4Header.GetSource ();
94 remoteAddressIpv4 = ipv4Header.GetDestination ();
95 }
96 else
97 {
98 NS_ASSERT (direction == EpcTft::DOWNLINK);
99 remoteAddressIpv4 = ipv4Header.GetSource ();
100 localAddressIpv4 = ipv4Header.GetDestination ();
101 }
102 NS_LOG_INFO ("local address: " << localAddressIpv4 << " remote address: " << remoteAddressIpv4);
103
104 uint16_t payloadSize = ipv4Header.GetPayloadSize ();
105 uint16_t fragmentOffset = ipv4Header.GetFragmentOffset ();
106 bool isLastFragment = ipv4Header.IsLastFragment ();
107
108 // NS_LOG_DEBUG ("PayloadSize = " << payloadSize);
109 // NS_LOG_DEBUG ("fragmentOffset " << fragmentOffset << " isLastFragment " << isLastFragment);
110
111 protocol = ipv4Header.GetProtocol ();
112 tos = ipv4Header.GetTos ();
113
114 // Port info only can be get if it is the first fragment and
115 // there is enough data in the payload
116 // We keep the port info for fragmented packets,
117 // i.e. it is the first one but it is not the last one
118 if (fragmentOffset == 0)
119 {
120 if (protocol == UdpL4Protocol::PROT_NUMBER && payloadSize >= 8)
121 {
122 UdpHeader udpHeader;
123 pCopy->RemoveHeader (udpHeader);
124 if (direction == EpcTft::UPLINK)
125 {
126 localPort = udpHeader.GetSourcePort ();
127 remotePort = udpHeader.GetDestinationPort ();
128 }
129 else
130 {
131 remotePort = udpHeader.GetSourcePort ();
132 localPort = udpHeader.GetDestinationPort ();
133 }
134 if (!isLastFragment)
135 {
136 std::tuple<uint32_t, uint32_t, uint8_t, uint16_t> fragmentKey =
137 std::make_tuple (ipv4Header.GetSource ().Get (),
138 ipv4Header.GetDestination ().Get (),
139 protocol,
140 ipv4Header.GetIdentification ());
141
142 m_classifiedIpv4Fragments[fragmentKey] = std::make_pair (localPort, remotePort);
143 }
144 }
145 else if (protocol == TcpL4Protocol::PROT_NUMBER && payloadSize >= 20)
146 {
147 TcpHeader tcpHeader;
148 pCopy->RemoveHeader (tcpHeader);
149 if (direction == EpcTft::UPLINK)
150 {
151 localPort = tcpHeader.GetSourcePort ();
152 remotePort = tcpHeader.GetDestinationPort ();
153 }
154 else
155 {
156 remotePort = tcpHeader.GetSourcePort ();
157 localPort = tcpHeader.GetDestinationPort ();
158 }
159
160 if (!isLastFragment)
161 {
162 std::tuple<uint32_t, uint32_t, uint8_t, uint16_t> fragmentKey =
163 std::make_tuple (ipv4Header.GetSource ().Get (),
164 ipv4Header.GetDestination ().Get (),
165 protocol,
166 ipv4Header.GetIdentification ());
167
168 m_classifiedIpv4Fragments[fragmentKey] = std::make_pair (localPort, remotePort);
169 }
170 }
171
172 // else
173 // First fragment but not enough data for port info or not UDP/TCP protocol.
174 // Nothing can be done, i.e. we cannot get port info from packet.
175 }
176 else
177 {
178 // Not first fragment, so port info is not available but
179 // port info should already be known (if there is not fragment reordering)
180 std::tuple<uint32_t, uint32_t, uint8_t, uint16_t> fragmentKey =
181 std::make_tuple (ipv4Header.GetSource ().Get (),
182 ipv4Header.GetDestination ().Get (),
183 protocol,
184 ipv4Header.GetIdentification ());
185
186 std::map< std::tuple<uint32_t, uint32_t, uint8_t, uint16_t>,
187 std::pair<uint32_t, uint32_t> >::iterator it =
188 m_classifiedIpv4Fragments.find (fragmentKey);
189
190 if (it != m_classifiedIpv4Fragments.end ())
191 {
192 localPort = it->second.first;
193 remotePort = it->second.second;
194
195 if (isLastFragment)
196 {
197 m_classifiedIpv4Fragments.erase (fragmentKey);
198 }
199 }
200 }
201 }
202 else if (protocolNumber == Ipv6L3Protocol::PROT_NUMBER)
203 {
204 Ipv6Header ipv6Header;
205 pCopy->RemoveHeader (ipv6Header);
206
207 if (direction == EpcTft::UPLINK)
208 {
209 localAddressIpv6 = ipv6Header.GetSource ();
210 remoteAddressIpv6 = ipv6Header.GetDestination ();
211 }
212 else
213 {
214 NS_ASSERT (direction == EpcTft::DOWNLINK);
215 remoteAddressIpv6 = ipv6Header.GetSource ();
216 localAddressIpv6 = ipv6Header.GetDestination ();
217 }
218 NS_LOG_INFO ("local address: " << localAddressIpv6 << " remote address: " << remoteAddressIpv6);
219
220 protocol = ipv6Header.GetNextHeader ();
221 tos = ipv6Header.GetTrafficClass ();
222
223 if (protocol == UdpL4Protocol::PROT_NUMBER)
224 {
225 UdpHeader udpHeader;
226 pCopy->RemoveHeader (udpHeader);
227
228 if (direction == EpcTft::UPLINK)
229 {
230 localPort = udpHeader.GetSourcePort ();
231 remotePort = udpHeader.GetDestinationPort ();
232 }
233 else
234 {
235 remotePort = udpHeader.GetSourcePort ();
236 localPort = udpHeader.GetDestinationPort ();
237 }
238 }
239 else if (protocol == TcpL4Protocol::PROT_NUMBER)
240 {
241 TcpHeader tcpHeader;
242 pCopy->RemoveHeader (tcpHeader);
243 if (direction == EpcTft::UPLINK)
244 {
245 localPort = tcpHeader.GetSourcePort ();
246 remotePort = tcpHeader.GetDestinationPort ();
247 }
248 else
249 {
250 remotePort = tcpHeader.GetSourcePort ();
251 localPort = tcpHeader.GetDestinationPort ();
252 }
253 }
254 }
255 else
256 {
257 NS_ABORT_MSG ("EpcTftClassifier::Classify - Unknown IP type...");
258 }
259
260
261 if (protocolNumber == Ipv4L3Protocol::PROT_NUMBER)
262 {
263 NS_LOG_INFO ("Classifying packet:"
264 << " localAddr=" << localAddressIpv4
265 << " remoteAddr=" << remoteAddressIpv4
266 << " localPort=" << localPort
267 << " remotePort=" << remotePort
268 << " tos=0x" << (uint16_t) tos );
269
270 // now it is possible to classify the packet!
271 // we use a reverse iterator since filter priority is not implemented properly.
272 // This way, since the default bearer is expected to be added first, it will be evaluated last.
273 std::map <uint32_t, Ptr<EpcTft> >::const_reverse_iterator it;
274 NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ());
275
276 for (it = m_tftMap.rbegin (); it != m_tftMap.rend (); ++it)
277 {
278 NS_LOG_LOGIC ("TFT id: " << it->first );
279 NS_LOG_LOGIC (" Ptr<EpcTft>: " << it->second);
280 Ptr<EpcTft> tft = it->second;
281 if (tft->Matches (direction, remoteAddressIpv4, localAddressIpv4, remotePort, localPort, tos))
282 {
283 NS_LOG_LOGIC ("matches with TFT ID = " << it->first);
284 return it->first; // the id of the matching TFT
285 }
286 }
287 }
288 else if (protocolNumber == Ipv6L3Protocol::PROT_NUMBER)
289 {
290 NS_LOG_INFO ("Classifying packet:"
291 << " localAddr=" << localAddressIpv6
292 << " remoteAddr=" << remoteAddressIpv6
293 << " localPort=" << localPort
294 << " remotePort=" << remotePort
295 << " tos=0x" << (uint16_t) tos );
296
297 // now it is possible to classify the packet!
298 // we use a reverse iterator since filter priority is not implemented properly.
299 // This way, since the default bearer is expected to be added first, it will be evaluated last.
300 std::map <uint32_t, Ptr<EpcTft> >::const_reverse_iterator it;
301 NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ());
302
303 for (it = m_tftMap.rbegin (); it != m_tftMap.rend (); ++it)
304 {
305 NS_LOG_LOGIC ("TFT id: " << it->first );
306 NS_LOG_LOGIC (" Ptr<EpcTft>: " << it->second);
307 Ptr<EpcTft> tft = it->second;
308 if (tft->Matches (direction, remoteAddressIpv6, localAddressIpv6, remotePort, localPort, tos))
309 {
310 NS_LOG_LOGIC ("matches with TFT ID = " << it->first);
311 return it->first; // the id of the matching TFT
312 }
313 }
314 }
315 NS_LOG_LOGIC ("no match");
316 return 0; // no match
317}
318
319
320} // namespace ns3
uint32_t Classify(Ptr< Packet > p, EpcTft::Direction direction, uint16_t protocolNumber)
classify an IP packet
void Add(Ptr< EpcTft > tft, uint32_t id)
add a TFT to the Classifier
std::map< uint32_t, Ptr< EpcTft > > m_tftMap
TFT map.
void Delete(uint32_t id)
delete an existing TFT from the classifier
std::map< std::tuple< uint32_t, uint32_t, uint8_t, uint16_t >, std::pair< uint32_t, uint32_t > > m_classifiedIpv4Fragments
Map with already classified IPv4 Fragments An entry is added when the port info is available,...
Direction
Indicates the direction of the traffic that is to be classified.
Definition: epc-tft.h:57
@ DOWNLINK
Definition: epc-tft.h:57
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
uint32_t Get(void) const
Get the host-order 32-bit IP address.
Packet header for IPv4.
Definition: ipv4-header.h:34
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
uint8_t GetTos(void) const
Definition: ipv4-header.cc:194
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:272
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
static const uint16_t PROT_NUMBER
Protocol number (0x0800)
Describes an IPv6 address.
Definition: ipv6-address.h:50
Packet header for IPv6.
Definition: ipv6-header.h:36
Ipv6Address GetSource(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:105
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
uint8_t GetTrafficClass(void) const
Get the "Traffic class" field.
Definition: ipv6-header.cc:50
Ipv6Address GetDestination(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:125
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
Header for the Transmission Control Protocol.
Definition: tcp-header.h:45
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
static const uint8_t PROT_NUMBER
protocol number (0x6)
Packet header for UDP packets.
Definition: udp-header.h:40
uint16_t GetSourcePort(void) const
Definition: udp-header.cc:65
uint16_t GetDestinationPort(void) const
Definition: udp-header.cc:70
static const uint8_t PROT_NUMBER
protocol number (0x11)
#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_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#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:281
Every class exported by the ns3 library is enclosed in the ns3 namespace.