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 auto it = m_classifiedIpv4Fragments.find(fragmentKey);
191
192 if (it != m_classifiedIpv4Fragments.end())
193 {
194 localPort = it->second.first;
195 remotePort = it->second.second;
196
197 if (isLastFragment)
198 {
199 m_classifiedIpv4Fragments.erase(fragmentKey);
200 }
201 }
202 }
203 }
204 else if (protocolNumber == Ipv6L3Protocol::PROT_NUMBER)
205 {
206 Ipv6Header ipv6Header;
207 pCopy->RemoveHeader(ipv6Header);
208
209 if (direction == EpcTft::UPLINK)
210 {
211 localAddressIpv6 = ipv6Header.GetSource();
212 remoteAddressIpv6 = ipv6Header.GetDestination();
213 }
214 else
215 {
216 NS_ASSERT(direction == EpcTft::DOWNLINK);
217 remoteAddressIpv6 = ipv6Header.GetSource();
218 localAddressIpv6 = ipv6Header.GetDestination();
219 }
220 NS_LOG_INFO("local address: " << localAddressIpv6
221 << " remote address: " << remoteAddressIpv6);
222
223 protocol = ipv6Header.GetNextHeader();
224 tos = ipv6Header.GetTrafficClass();
225
226 if (protocol == UdpL4Protocol::PROT_NUMBER)
227 {
228 UdpHeader udpHeader;
229 pCopy->RemoveHeader(udpHeader);
230
231 if (direction == EpcTft::UPLINK)
232 {
233 localPort = udpHeader.GetSourcePort();
234 remotePort = udpHeader.GetDestinationPort();
235 }
236 else
237 {
238 remotePort = udpHeader.GetSourcePort();
239 localPort = udpHeader.GetDestinationPort();
240 }
241 }
242 else if (protocol == TcpL4Protocol::PROT_NUMBER)
243 {
244 TcpHeader tcpHeader;
245 pCopy->RemoveHeader(tcpHeader);
246 if (direction == EpcTft::UPLINK)
247 {
248 localPort = tcpHeader.GetSourcePort();
249 remotePort = tcpHeader.GetDestinationPort();
250 }
251 else
252 {
253 remotePort = tcpHeader.GetSourcePort();
254 localPort = tcpHeader.GetDestinationPort();
255 }
256 }
257 }
258 else
259 {
260 NS_ABORT_MSG("EpcTftClassifier::Classify - Unknown IP type...");
261 }
262
263 if (protocolNumber == Ipv4L3Protocol::PROT_NUMBER)
264 {
265 NS_LOG_INFO("Classifying packet:"
266 << " localAddr=" << localAddressIpv4 << " remoteAddr=" << remoteAddressIpv4
267 << " localPort=" << localPort << " remotePort=" << remotePort << " tos=0x"
268 << (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
273 // last.
274 std::map<uint32_t, Ptr<EpcTft>>::const_reverse_iterator it;
275 NS_LOG_LOGIC("TFT MAP size: " << m_tftMap.size());
276
277 for (it = m_tftMap.rbegin(); it != m_tftMap.rend(); ++it)
278 {
279 NS_LOG_LOGIC("TFT id: " << it->first);
280 NS_LOG_LOGIC(" Ptr<EpcTft>: " << it->second);
281 Ptr<EpcTft> tft = it->second;
282 if (tft->Matches(direction,
283 remoteAddressIpv4,
284 localAddressIpv4,
285 remotePort,
286 localPort,
287 tos))
288 {
289 NS_LOG_LOGIC("matches with TFT ID = " << it->first);
290 return it->first; // the id of the matching TFT
291 }
292 }
293 }
294 else if (protocolNumber == Ipv6L3Protocol::PROT_NUMBER)
295 {
296 NS_LOG_INFO("Classifying packet:"
297 << " localAddr=" << localAddressIpv6 << " remoteAddr=" << remoteAddressIpv6
298 << " localPort=" << localPort << " remotePort=" << remotePort << " tos=0x"
299 << (uint16_t)tos);
300
301 // now it is possible to classify the packet!
302 // we use a reverse iterator since filter priority is not implemented properly.
303 // This way, since the default bearer is expected to be added first, it will be evaluated
304 // last.
305 std::map<uint32_t, Ptr<EpcTft>>::const_reverse_iterator it;
306 NS_LOG_LOGIC("TFT MAP size: " << m_tftMap.size());
307
308 for (it = m_tftMap.rbegin(); it != m_tftMap.rend(); ++it)
309 {
310 NS_LOG_LOGIC("TFT id: " << it->first);
311 NS_LOG_LOGIC(" Ptr<EpcTft>: " << it->second);
312 Ptr<EpcTft> tft = it->second;
313 if (tft->Matches(direction,
314 remoteAddressIpv6,
315 localAddressIpv6,
316 remotePort,
317 localPort,
318 tos))
319 {
320 NS_LOG_LOGIC("matches with TFT ID = " << it->first);
321 return it->first; // the id of the matching TFT
322 }
323 }
324 }
325 NS_LOG_LOGIC("no match");
326 return 0; // no match
327}
328
329} // 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:77
Header for the Transmission Control Protocol.
Definition: tcp-header.h:47
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:112
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:106
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:54
uint16_t GetSourcePort() const
Definition: udp-header.cc:48
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.