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