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