A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv6-flow-classifier.cc
Go to the documentation of this file.
1//
2// Copyright (c) 2009 INESC Porto
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License version 2 as
6// published by the Free Software Foundation;
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program; if not, write to the Free Software
15// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16//
17// Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt> <gjcarneiro@gmail.com>
18// Modifications: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19//
20
22
23#include "ns3/packet.h"
24#include "ns3/tcp-header.h"
25#include "ns3/udp-header.h"
26
27#include <algorithm>
28
29namespace ns3
30{
31
32/* see http://www.iana.org/assignments/protocol-numbers */
33const uint8_t TCP_PROT_NUMBER = 6;
34const uint8_t UDP_PROT_NUMBER = 17;
35
36bool
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
76 {
77 return true;
78 }
80 {
81 return false;
82 }
83
84 return false;
85}
86
87bool
89{
90 return (t1.sourceAddress == t2.sourceAddress &&
93}
94
96{
97}
98
99bool
101 Ptr<const Packet> ipPayload,
102 uint32_t* out_flowId,
103 uint32_t* out_packetId)
104{
105 if (ipHeader.GetDestination().IsMulticast())
106 {
107 // we are not prepared to handle multicast yet
108 return false;
109 }
110
111 FiveTuple tuple;
112 tuple.sourceAddress = ipHeader.GetSource();
113 tuple.destinationAddress = ipHeader.GetDestination();
114 tuple.protocol = ipHeader.GetNextHeader();
115
116 if ((tuple.protocol != UDP_PROT_NUMBER) && (tuple.protocol != TCP_PROT_NUMBER))
117 {
118 return false;
119 }
120
121 if (ipPayload->GetSize() < 4)
122 {
123 // the packet doesn't carry enough bytes
124 return false;
125 }
126
127 // we rely on the fact that for both TCP and UDP the ports are
128 // carried in the first 4 octets.
129 // This allows to read the ports even on fragmented packets
130 // not carrying a full TCP or UDP header.
131
132 uint8_t data[4];
133 ipPayload->CopyData(data, 4);
134
135 uint16_t srcPort = 0;
136 srcPort |= data[0];
137 srcPort <<= 8;
138 srcPort |= data[1];
139
140 uint16_t dstPort = 0;
141 dstPort |= data[2];
142 dstPort <<= 8;
143 dstPort |= data[3];
144
145 tuple.sourcePort = srcPort;
146 tuple.destinationPort = dstPort;
147
148 // try to insert the tuple, but check if it already exists
149 std::pair<std::map<FiveTuple, FlowId>::iterator, bool> insert =
150 m_flowMap.insert(std::pair<FiveTuple, FlowId>(tuple, 0));
151
152 // if the insertion succeeded, we need to assign this tuple a new flow identifier
153 if (insert.second)
154 {
155 FlowId newFlowId = GetNewFlowId();
156 insert.first->second = newFlowId;
157 m_flowPktIdMap[newFlowId] = 0;
158 m_flowDscpMap[newFlowId];
159 }
160 else
161 {
162 m_flowPktIdMap[insert.first->second]++;
163 }
164
165 // increment the counter of packets with the same DSCP value
166 Ipv6Header::DscpType dscp = ipHeader.GetDscp();
167 std::pair<std::map<Ipv6Header::DscpType, uint32_t>::iterator, bool> dscpInserter =
168 m_flowDscpMap[insert.first->second].insert(
169 std::pair<Ipv6Header::DscpType, uint32_t>(dscp, 1));
170
171 // if the insertion did not succeed, we need to increment the counter
172 if (!dscpInserter.second)
173 {
174 m_flowDscpMap[insert.first->second][dscp]++;
175 }
176
177 *out_flowId = insert.first->second;
178 *out_packetId = m_flowPktIdMap[*out_flowId];
179
180 return true;
181}
182
185{
186 for (std::map<FiveTuple, FlowId>::const_iterator iter = m_flowMap.begin();
187 iter != m_flowMap.end();
188 iter++)
189 {
190 if (iter->second == flowId)
191 {
192 return iter->first;
193 }
194 }
195 NS_FATAL_ERROR("Could not find the flow with ID " << flowId);
196 FiveTuple retval = {Ipv6Address::GetZero(), Ipv6Address::GetZero(), 0, 0, 0};
197 return retval;
198}
199
200bool
201Ipv6FlowClassifier::SortByCount::operator()(std::pair<Ipv6Header::DscpType, uint32_t> left,
202 std::pair<Ipv6Header::DscpType, uint32_t> right)
203{
204 return left.second > right.second;
205}
206
207std::vector<std::pair<Ipv6Header::DscpType, uint32_t>>
209{
210 std::map<FlowId, std::map<Ipv6Header::DscpType, uint32_t>>::const_iterator flow =
211 m_flowDscpMap.find(flowId);
212
213 if (flow == m_flowDscpMap.end())
214 {
215 NS_FATAL_ERROR("Could not find the flow with ID " << flowId);
216 }
217
218 std::vector<std::pair<Ipv6Header::DscpType, uint32_t>> v(flow->second.begin(),
219 flow->second.end());
220 std::sort(v.begin(), v.end(), SortByCount());
221 return v;
222}
223
224void
225Ipv6FlowClassifier::SerializeToXmlStream(std::ostream& os, uint16_t indent) const
226{
227 Indent(os, indent);
228 os << "<Ipv6FlowClassifier>\n";
229
230 indent += 2;
231 for (std::map<FiveTuple, FlowId>::const_iterator iter = m_flowMap.begin();
232 iter != m_flowMap.end();
233 iter++)
234 {
235 Indent(os, indent);
236 os << "<Flow flowId=\"" << iter->second << "\""
237 << " sourceAddress=\"" << iter->first.sourceAddress << "\""
238 << " destinationAddress=\"" << iter->first.destinationAddress << "\""
239 << " protocol=\"" << int(iter->first.protocol) << "\""
240 << " sourcePort=\"" << iter->first.sourcePort << "\""
241 << " destinationPort=\"" << iter->first.destinationPort << "\">\n";
242
243 indent += 2;
244 std::map<FlowId, std::map<Ipv6Header::DscpType, uint32_t>>::const_iterator flow =
245 m_flowDscpMap.find(iter->second);
246
247 if (flow != m_flowDscpMap.end())
248 {
249 for (std::map<Ipv6Header::DscpType, uint32_t>::const_iterator i = flow->second.begin();
250 i != flow->second.end();
251 i++)
252 {
253 Indent(os, indent);
254 os << "<Dscp value=\"0x" << std::hex << static_cast<uint32_t>(i->first) << "\""
255 << " packets=\"" << std::dec << i->second << "\" />\n";
256 }
257 }
258
259 indent -= 2;
260 Indent(os, indent);
261 os << "</Flow>\n";
262 }
263
264 indent -= 2;
265 Indent(os, indent);
266 os << "</Ipv6FlowClassifier>\n";
267}
268
269} // namespace ns3
FlowId GetNewFlowId()
Returns a new, unique Flow Identifier.
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
Comparator used to sort the vector of DSCP values.
bool operator()(std::pair< Ipv6Header::DscpType, uint32_t > left, std::pair< Ipv6Header::DscpType, uint32_t > right)
Comparator function.
std::map< FiveTuple, FlowId > m_flowMap
Map to Flows Identifiers to FlowIds.
void SerializeToXmlStream(std::ostream &os, uint16_t indent) const override
Serializes the results to an std::ostream in XML format.
std::vector< std::pair< Ipv6Header::DscpType, uint32_t > > GetDscpCounts(FlowId flowId) const
get the DSCP values of the packets belonging to the flow with the given FlowId, sorted in decreasing ...
FiveTuple FindFlow(FlowId flowId) const
Searches for the FiveTuple corresponding to the given flowId.
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
std::map< FlowId, FlowPacketId > m_flowPktIdMap
Map to FlowIds to FlowPacketId.
std::map< FlowId, std::map< Ipv6Header::DscpType, uint32_t > > m_flowDscpMap
Map FlowIds to (DSCP value, packet count) pairs.
Packet header for IPv6.
Definition: ipv6-header.h:35
DscpType GetDscp() const
Definition: ipv6-header.cc:223
uint8_t GetNextHeader() const
Get the next header.
Definition: ipv6-header.cc:88
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:124
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
DscpType
DiffServ Code Points Code Points defined in Assured Forwarding (AF) RFC 2597 Expedited Forwarding (EF...
Definition: ipv6-header.h:46
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
Every class exported by the ns3 library is enclosed in the ns3 namespace.
const uint8_t TCP_PROT_NUMBER
TCP Protocol number.
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.h:157
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:170
const uint8_t UDP_PROT_NUMBER
UDP Protocol number.
uint8_t data[writeSize]
Helper to indent output a specified number of steps.
Definition: test.cc:648
Structure to classify a packet.
uint16_t destinationPort
Destination port.
Ipv6Address destinationAddress
Destination address.
Ipv6Address sourceAddress
Source address.