A Discrete-Event Network Simulator
API
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 
42 namespace ns3
43 {
44 
45 NS_LOG_COMPONENT_DEFINE("EpcTftClassifier");
46 
48 {
49  NS_LOG_FUNCTION(this);
50 }
51 
52 void
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 
62 void
64 {
65  NS_LOG_FUNCTION(this << id);
66  m_tftMap.erase(id);
67 }
68 
69 uint32_t
70 EpcTftClassifier::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:43
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:50
Packet header for IPv6.
Definition: ipv6-header.h:36
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).
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
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.