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 
41 namespace ns3 {
42 
43 NS_LOG_COMPONENT_DEFINE ("EpcTftClassifier");
44 
46 {
47  NS_LOG_FUNCTION (this);
48 }
49 
50 void
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 
60 void
62 {
63  NS_LOG_FUNCTION (this << id);
64  m_tftMap.erase (id);
65 }
66 
67 uint32_t
68 EpcTftClassifier::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.