A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv4-flow-classifier.cc
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 
35 bool operator < (const Ipv4FlowClassifier::FiveTuple &t1,
36  const Ipv4FlowClassifier::FiveTuple &t2)
37 {
38  if (t1.sourceAddress < t2.sourceAddress)
39  {
40  return true;
41  }
42  if (t1.sourceAddress != t2.sourceAddress)
43  {
44  return false;
45  }
46 
47  if (t1.destinationAddress < t2.destinationAddress)
48  {
49  return true;
50  }
51  if (t1.destinationAddress != t2.destinationAddress)
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 
86 bool operator == (const Ipv4FlowClassifier::FiveTuple &t1,
87  const Ipv4FlowClassifier::FiveTuple &t2)
88 {
89  return (t1.sourceAddress == t2.sourceAddress &&
90  t1.destinationAddress == t2.destinationAddress &&
91  t1.protocol == t2.protocol &&
92  t1.sourcePort == t2.sourcePort &&
93  t1.destinationPort == t2.destinationPort);
94 }
95 
96 
97 
98 Ipv4FlowClassifier::Ipv4FlowClassifier ()
99 {
100 }
101 
102 bool
104  uint32_t *out_flowId, uint32_t *out_packetId)
105 {
106  if (ipHeader.GetDestination () == Ipv4Address::GetBroadcast ())
107  {
108  // we are not prepared to handle broadcast yet
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  switch (tuple.protocol)
118  {
119  case UDP_PROT_NUMBER:
120  {
121  UdpHeader udpHeader;
122  ipPayload->PeekHeader (udpHeader);
123  tuple.sourcePort = udpHeader.GetSourcePort ();
124  tuple.destinationPort = udpHeader.GetDestinationPort ();
125  }
126  break;
127 
128  case TCP_PROT_NUMBER:
129  {
130  TcpHeader tcpHeader;
131  ipPayload->PeekHeader (tcpHeader);
132  tuple.sourcePort = tcpHeader.GetSourcePort ();
133  tuple.destinationPort = tcpHeader.GetDestinationPort ();
134  }
135  break;
136 
137  default:
138  return false;
139  }
140 
141  // try to insert the tuple, but check if it already exists
142  std::pair<std::map<FiveTuple, FlowId>::iterator, bool> insert
143  = m_flowMap.insert (std::pair<FiveTuple, FlowId> (tuple, 0));
144 
145  // if the insertion succeeded, we need to assign this tuple a new flow identifier
146  if (insert.second)
147  {
148  insert.first->second = GetNewFlowId ();
149  }
150 
151  *out_flowId = insert.first->second;
152  *out_packetId = ipHeader.GetIdentification ();
153 
154  return true;
155 }
156 
157 
159 Ipv4FlowClassifier::FindFlow (FlowId flowId) const
160 {
161  for (std::map<FiveTuple, FlowId>::const_iterator
162  iter = m_flowMap.begin (); iter != m_flowMap.end (); iter++)
163  {
164  if (iter->second == flowId)
165  {
166  return iter->first;
167  }
168  }
169  NS_FATAL_ERROR ("Could not find the flow with ID " << flowId);
170  FiveTuple retval = { Ipv4Address::GetZero (), Ipv4Address::GetZero (), 0, 0, 0 };
171  return retval;
172 }
173 
174 void
175 Ipv4FlowClassifier::SerializeToXmlStream (std::ostream &os, int indent) const
176 {
177 #define INDENT(level) for (int __xpto = 0; __xpto < level; __xpto++) os << ' ';
178 
179  INDENT (indent); os << "<Ipv4FlowClassifier>\n";
180 
181  indent += 2;
182  for (std::map<FiveTuple, FlowId>::const_iterator
183  iter = m_flowMap.begin (); iter != m_flowMap.end (); iter++)
184  {
185  INDENT (indent);
186  os << "<Flow flowId=\"" << iter->second << "\""
187  << " sourceAddress=\"" << iter->first.sourceAddress << "\""
188  << " destinationAddress=\"" << iter->first.destinationAddress << "\""
189  << " protocol=\"" << int(iter->first.protocol) << "\""
190  << " sourcePort=\"" << iter->first.sourcePort << "\""
191  << " destinationPort=\"" << iter->first.destinationPort << "\""
192  << " />\n";
193  }
194 
195  indent -= 2;
196  INDENT (indent); os << "</Ipv4FlowClassifier>\n";
197 
198 #undef INDENT
199 }
200 
201 
202 } // namespace ns3
203 
uint16_t GetDestinationPort() const
Definition: tcp-header.cc:92
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:303
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:271
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:290
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
Packet header for IPv4.
Definition: ipv4-header.h:31
FiveTuple FindFlow(FlowId flowId) const
Searches for the FiveTuple corresponding to the given flowId.
static Ipv4Address GetBroadcast(void)
uint32_t PeekHeader(Header &header) const
Definition: packet.cc:294
Header for the Transmission Control Protocol.
Definition: tcp-header.h:43
uint16_t GetSourcePort(void) const
Definition: udp-header.cc:64
Packet header for UDP packets.
Definition: udp-header.h:39
static Ipv4Address GetZero(void)
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
uint16_t GetSourcePort() const
Definition: tcp-header.cc:88
uint16_t GetDestinationPort(void) const
Definition: udp-header.cc:69