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/udp-l4-protocol.h"
35 #include "ns3/tcp-l4-protocol.h"
36 #include "ns3/icmpv6-l4-protocol.h"
37 #include "ns3/icmpv4-l4-protocol.h"
38 
39 namespace ns3 {
40 
41 NS_LOG_COMPONENT_DEFINE ("EpcTftClassifier");
42 
44 {
45  NS_LOG_FUNCTION (this);
46 }
47 
48 void
50 {
51  NS_LOG_FUNCTION (this << tft << id);
52  m_tftMap[id] = tft;
53 
54  // simple sanity check: there shouldn't be more than 16 bearers (hence TFTs) per UE
55  NS_ASSERT (m_tftMap.size () <= 16);
56 }
57 
58 void
60 {
61  NS_LOG_FUNCTION (this << id);
62  m_tftMap.erase (id);
63 }
64 
65 
66 uint32_t
68 {
69  NS_LOG_FUNCTION (this << p << p->GetSize () << direction);
70 
71  Ptr<Packet> pCopy = p->Copy ();
72 
73  uint8_t ipType;
74  pCopy->CopyData (&ipType, 1);
75  ipType = (ipType>>4) & 0x0f;
76 
77  Ipv4Address localAddressIpv4;
78  Ipv4Address remoteAddressIpv4;
79 
80  Ipv6Address localAddressIpv6;
81  Ipv6Address remoteAddressIpv6;
82 
83  uint8_t protocol;
84  uint8_t tos;
85 
86  uint16_t localPort = 0;
87  uint16_t remotePort = 0;
88 
89  if (ipType == 0x04)
90  {
91  Ipv4Header ipv4Header;
92  pCopy->RemoveHeader (ipv4Header);
93 
94  if (direction == EpcTft::UPLINK)
95  {
96  localAddressIpv4 = ipv4Header.GetSource ();
97  remoteAddressIpv4 = ipv4Header.GetDestination ();
98  }
99  else
100  {
101  NS_ASSERT (direction == EpcTft::DOWNLINK);
102  remoteAddressIpv4 = ipv4Header.GetSource ();
103  localAddressIpv4 = ipv4Header.GetDestination ();
104  }
105  NS_LOG_INFO ("local address: " << localAddressIpv4 << " 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 " << isLastFragment);
113 
114  protocol = ipv4Header.GetProtocol ();
115  tos = ipv4Header.GetTos ();
116 
117  // Port info only can be get if it is the first fragment and
118  // there is enough data in the payload
119  // We keep the port info for fragmented packets,
120  // i.e. it is the first one but it is not the last one
121  if (fragmentOffset == 0)
122  {
123  if (protocol == UdpL4Protocol::PROT_NUMBER && payloadSize >= 8)
124  {
125  UdpHeader udpHeader;
126  pCopy->RemoveHeader (udpHeader);
127  if (direction == EpcTft::UPLINK)
128  {
129  localPort = udpHeader.GetSourcePort ();
130  remotePort = udpHeader.GetDestinationPort ();
131  }
132  else
133  {
134  remotePort = udpHeader.GetSourcePort ();
135  localPort = udpHeader.GetDestinationPort ();
136  }
137  if (!isLastFragment)
138  {
139  std::tuple<uint32_t, uint32_t, uint8_t, uint16_t> fragmentKey =
140  std::make_tuple (ipv4Header.GetSource ().Get (),
141  ipv4Header.GetDestination ().Get (),
142  protocol,
143  ipv4Header.GetIdentification ());
144 
145  m_classifiedIpv4Fragments[fragmentKey] = std::make_pair (localPort, remotePort);
146  }
147  }
148  else if (protocol == TcpL4Protocol::PROT_NUMBER && payloadSize >= 20)
149  {
150  TcpHeader tcpHeader;
151  pCopy->RemoveHeader (tcpHeader);
152  if (direction == EpcTft::UPLINK)
153  {
154  localPort = tcpHeader.GetSourcePort ();
155  remotePort = tcpHeader.GetDestinationPort ();
156  }
157  else
158  {
159  remotePort = tcpHeader.GetSourcePort ();
160  localPort = tcpHeader.GetDestinationPort ();
161  }
162 
163  if (!isLastFragment)
164  {
165  std::tuple<uint32_t, uint32_t, uint8_t, uint16_t> fragmentKey =
166  std::make_tuple (ipv4Header.GetSource ().Get (),
167  ipv4Header.GetDestination ().Get (),
168  protocol,
169  ipv4Header.GetIdentification ());
170 
171  m_classifiedIpv4Fragments[fragmentKey] = std::make_pair (localPort, remotePort);
172  }
173  }
174 
175  // else
176  // First fragment but not enough data for port info or not UDP/TCP protocol.
177  // Nothing can be done, i.e. we cannot get port info from packet.
178  }
179  else
180  {
181  // Not first fragment, so port info is not available but
182  // port info should already be known (if there is not fragment reordering)
183  std::tuple<uint32_t, uint32_t, uint8_t, uint16_t> fragmentKey =
184  std::make_tuple (ipv4Header.GetSource ().Get (),
185  ipv4Header.GetDestination ().Get (),
186  protocol,
187  ipv4Header.GetIdentification ());
188 
189  std::map< std::tuple<uint32_t, uint32_t, uint8_t, uint16_t>,
190  std::pair<uint32_t, uint32_t> >::iterator it =
191  m_classifiedIpv4Fragments.find (fragmentKey);
192 
193  if (it != m_classifiedIpv4Fragments.end ())
194  {
195  localPort = it->second.first;
196  remotePort = it->second.second;
197 
198  if (isLastFragment)
199  {
200  m_classifiedIpv4Fragments.erase (fragmentKey);
201  }
202  }
203  }
204  }
205  else if (ipType == 0x06)
206  {
207  Ipv6Header ipv6Header;
208  pCopy->RemoveHeader (ipv6Header);
209 
210  if (direction == EpcTft::UPLINK)
211  {
212  localAddressIpv6 = ipv6Header.GetSourceAddress ();
213  remoteAddressIpv6 = ipv6Header.GetDestinationAddress ();
214  }
215  else
216  {
217  NS_ASSERT (direction == EpcTft::DOWNLINK);
218  remoteAddressIpv6 = ipv6Header.GetSourceAddress ();
219  localAddressIpv6 = ipv6Header.GetDestinationAddress ();
220  }
221  NS_LOG_INFO ("local address: " << localAddressIpv6 << " 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 
264  if (ipType == 0x04)
265  {
266  NS_LOG_INFO ("Classifying packet:"
267  << " localAddr=" << localAddressIpv4
268  << " remoteAddr=" << remoteAddressIpv4
269  << " localPort=" << localPort
270  << " remotePort=" << remotePort
271  << " tos=0x" << (uint16_t) tos );
272 
273  // now it is possible to classify the packet!
274  // we use a reverse iterator since filter priority is not implemented properly.
275  // This way, since the default bearer is expected to be added first, it will be evaluated 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, remoteAddressIpv4, localAddressIpv4, remotePort, localPort, tos))
285  {
286  NS_LOG_LOGIC ("matches with TFT ID = " << it->first);
287  return it->first; // the id of the matching TFT
288  }
289  }
290  }
291  else if (ipType == 0x06)
292  {
293  NS_LOG_INFO ("Classifying packet:"
294  << " localAddr=" << localAddressIpv6
295  << " remoteAddr=" << remoteAddressIpv6
296  << " localPort=" << localPort
297  << " remotePort=" << remotePort
298  << " tos=0x" << (uint16_t) tos );
299 
300  // now it is possible to classify the packet!
301  // we use a reverse iterator since filter priority is not implemented properly.
302  // This way, since the default bearer is expected to be added first, it will be evaluated last.
303  std::map <uint32_t, Ptr<EpcTft> >::const_reverse_iterator it;
304  NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ());
305 
306  for (it = m_tftMap.rbegin (); it != m_tftMap.rend (); ++it)
307  {
308  NS_LOG_LOGIC ("TFT id: " << it->first );
309  NS_LOG_LOGIC (" Ptr<EpcTft>: " << it->second);
310  Ptr<EpcTft> tft = it->second;
311  if (tft->Matches (direction, remoteAddressIpv6, localAddressIpv6, remotePort, localPort, tos))
312  {
313  NS_LOG_LOGIC ("matches with TFT ID = " << it->first);
314  return it->first; // the id of the matching TFT
315  }
316  }
317  }
318  NS_LOG_LOGIC ("no match");
319  return 0; // no match
320 }
321 
322 
323 } // namespace ns3
Direction
Indicates the direction of the traffic that is to be classified.
Definition: epc-tft.h:57
Packet header for IPv6.
Definition: ipv6-header.h:34
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:831
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
void Add(Ptr< EpcTft > tft, uint32_t id)
add a TFT to the Classifier
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
uint8_t GetTos(void) const
Definition: ipv4-header.cc:194
#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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:278
uint32_t Classify(Ptr< Packet > p, EpcTft::Direction direction)
classify an IP packet
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:272
Packet header for IPv4.
Definition: ipv4-header.h:33
uint16_t GetDestinationPort(void) const
Definition: udp-header.cc:70
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
static const uint8_t PROT_NUMBER
protocol number (0x6)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
Packet header for UDP packets.
Definition: udp-header.h:39
std::map< uint32_t, Ptr< EpcTft > > m_tftMap
TFT map.
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
Describes an IPv6 address.
Definition: ipv6-address.h:49
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
uint8_t GetTrafficClass(void) const
Get the "Traffic class" field.
Definition: ipv6-header.cc:50
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
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...
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
uint16_t GetSourcePort(void) const
Definition: udp-header.cc:65
void Delete(uint32_t id)
delete an existing TFT from the classifier
uint32_t Get(void) const
Get the host-order 32-bit IP address.
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
static const uint8_t PROT_NUMBER
protocol number (0x11)