A Discrete-Event Network Simulator
API
ipv6-flow-classifier.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 //
3 // Copyright (c) 2009 INESC Porto
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 // Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt> <gjcarneiro@gmail.com>
19 // Modifications: Tommaso Pecorella <tommaso.pecorella@unifi.it>
20 //
21 
22 #include "ns3/packet.h"
23 
24 #include "ipv6-flow-classifier.h"
25 #include "ns3/udp-header.h"
26 #include "ns3/tcp-header.h"
27 
28 namespace ns3 {
29 
30 /* see http://www.iana.org/assignments/protocol-numbers */
31 const uint8_t TCP_PROT_NUMBER = 6;
32 const uint8_t UDP_PROT_NUMBER = 17;
33 
34 
35 
38 {
39  if (t1.sourceAddress < t2.sourceAddress)
40  {
41  return true;
42  }
43  if (t1.sourceAddress != t2.sourceAddress)
44  {
45  return false;
46  }
47 
49  {
50  return true;
51  }
53  {
54  return false;
55  }
56 
57  if (t1.protocol < t2.protocol)
58  {
59  return true;
60  }
61  if (t1.protocol != t2.protocol)
62  {
63  return false;
64  }
65 
66  if (t1.sourcePort < t2.sourcePort)
67  {
68  return true;
69  }
70  if (t1.sourcePort != t2.sourcePort)
71  {
72  return false;
73  }
74 
75  if (t1.destinationPort < t2.destinationPort)
76  {
77  return true;
78  }
79  if (t1.destinationPort != t2.destinationPort)
80  {
81  return false;
82  }
83 
84  return false;
85 }
86 
89 {
90  return (t1.sourceAddress == t2.sourceAddress &&
92  t1.protocol == t2.protocol &&
93  t1.sourcePort == t2.sourcePort &&
95 }
96 
97 
98 
100 {
101 }
102 
103 bool
105  uint32_t *out_flowId, uint32_t *out_packetId)
106 {
107  if (ipHeader.GetDestinationAddress ().IsMulticast ())
108  {
109  // we are not prepared to handle multicast yet
110  return false;
111  }
112 
113  FiveTuple tuple;
114  tuple.sourceAddress = ipHeader.GetSourceAddress ();
115  tuple.destinationAddress = ipHeader.GetDestinationAddress ();
116  tuple.protocol = ipHeader.GetNextHeader ();
117 
118  if ((tuple.protocol != UDP_PROT_NUMBER) && (tuple.protocol != TCP_PROT_NUMBER))
119  {
120  return false;
121  }
122 
123  if (ipPayload->GetSize () < 4)
124  {
125  // the packet doesn't carry enough bytes
126  return false;
127  }
128 
129  // we rely on the fact that for both TCP and UDP the ports are
130  // carried in the first 4 octects.
131  // This allows to read the ports even on fragmented packets
132  // not carrying a full TCP or UDP header.
133 
134  uint8_t data[4];
135  ipPayload->CopyData (data, 4);
136 
137  uint16_t srcPort = 0;
138  srcPort |= data[0];
139  srcPort <<= 8;
140  srcPort |= data[1];
141 
142  uint16_t dstPort = 0;
143  dstPort |= data[2];
144  dstPort <<= 8;
145  dstPort |= data[3];
146 
147  tuple.sourcePort = srcPort;
148  tuple.destinationPort = dstPort;
149 
150  // try to insert the tuple, but check if it already exists
151  std::pair<std::map<FiveTuple, FlowId>::iterator, bool> insert
152  = m_flowMap.insert (std::pair<FiveTuple, FlowId> (tuple, 0));
153 
154  // if the insertion succeeded, we need to assign this tuple a new flow identifier
155  if (insert.second)
156  {
157  FlowId newFlowId = GetNewFlowId ();
158  insert.first->second = newFlowId;
159  m_flowPktIdMap[newFlowId] = 0;
160  }
161  else
162  {
163  m_flowPktIdMap[insert.first->second] ++;
164  }
165 
166  *out_flowId = insert.first->second;
167  *out_packetId = m_flowPktIdMap[*out_flowId];
168 
169  return true;
170 }
171 
172 
175 {
176  for (std::map<FiveTuple, FlowId>::const_iterator
177  iter = m_flowMap.begin (); iter != m_flowMap.end (); iter++)
178  {
179  if (iter->second == flowId)
180  {
181  return iter->first;
182  }
183  }
184  NS_FATAL_ERROR ("Could not find the flow with ID " << flowId);
185  FiveTuple retval = { Ipv6Address::GetZero (), Ipv6Address::GetZero (), 0, 0, 0 };
186  return retval;
187 }
188 
189 void
191 {
192 #define INDENT(level) for (int __xpto = 0; __xpto < level; __xpto++) os << ' ';
193 
194  INDENT (indent); os << "<Ipv6FlowClassifier>\n";
195 
196  indent += 2;
197  for (std::map<FiveTuple, FlowId>::const_iterator
198  iter = m_flowMap.begin (); iter != m_flowMap.end (); iter++)
199  {
200  INDENT (indent);
201  os << "<Flow flowId=\"" << iter->second << "\""
202  << " sourceAddress=\"" << iter->first.sourceAddress << "\""
203  << " destinationAddress=\"" << iter->first.destinationAddress << "\""
204  << " protocol=\"" << int(iter->first.protocol) << "\""
205  << " sourcePort=\"" << iter->first.sourcePort << "\""
206  << " destinationPort=\"" << iter->first.destinationPort << "\""
207  << " />\n";
208  }
209 
210  indent -= 2;
211  INDENT (indent); os << "</Ipv6FlowClassifier>\n";
212 
213 #undef INDENT
214 }
215 
216 
217 } // namespace ns3
218 
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
Packet header for IPv6.
Definition: ipv6-header.h:34
FiveTuple FindFlow(FlowId flowId) const
Searches for the FiveTuple corresponding to the given flowId.
FlowId GetNewFlowId()
Returns a new, unique Flow Identifier.
Ipv6Address destinationAddress
Destination address.
const uint8_t TCP_PROT_NUMBER
TCP Protocol number.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
bool Classify(const Ipv6Header &ipHeader, Ptr< const Packet > ipPayload, uint32_t *out_flowId, uint32_t *out_packetId)
try to classify the packet into flow-id and packet-id
def indent(source, debug, level)
Definition: check-style.py:286
virtual void SerializeToXmlStream(std::ostream &os, int indent) const
Serializes the results to an std::ostream in XML format.
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
uint8_t data[writeSize]
std::map< FiveTuple, FlowId > m_flowMap
Map to Flows Identifiers to FlowIds.
Ipv6Address sourceAddress
Source address.
bool operator<(const int64x64_t &lhs, const int64x64_t &rhs)
Less than operator.
Definition: int64x64-128.h:356
std::map< FlowId, FlowPacketId > m_flowPktIdMap
Map to FlowIds to FlowPacketId.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
const uint8_t UDP_PROT_NUMBER
UDP Protocol number.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.cc:95
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:356
uint16_t destinationPort
Destination port.
Structure to classify a packet.
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
#define INDENT(level)
uint32_t FlowId
Abstract identifier of a packet flow.