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