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 auto insert = m_flowMap.insert(std::pair<FiveTuple, FlowId>(tuple, 0));
150
151 // if the insertion succeeded, we need to assign this tuple a new flow identifier
152 if (insert.second)
153 {
154 FlowId newFlowId = GetNewFlowId();
155 insert.first->second = newFlowId;
156 m_flowPktIdMap[newFlowId] = 0;
157 m_flowDscpMap[newFlowId];
158 }
159 else
160 {
161 m_flowPktIdMap[insert.first->second]++;
162 }
163
164 // increment the counter of packets with the same DSCP value
165 Ipv6Header::DscpType dscp = ipHeader.GetDscp();
166 auto dscpInserter = m_flowDscpMap[insert.first->second].insert(
167 std::pair<Ipv6Header::DscpType, uint32_t>(dscp, 1));
168
169 // if the insertion did not succeed, we need to increment the counter
170 if (!dscpInserter.second)
171 {
172 m_flowDscpMap[insert.first->second][dscp]++;
173 }
174
175 *out_flowId = insert.first->second;
176 *out_packetId = m_flowPktIdMap[*out_flowId];
177
178 return true;
179}
180
183{
184 for (auto iter = m_flowMap.begin(); iter != m_flowMap.end(); iter++)
185 {
186 if (iter->second == flowId)
187 {
188 return iter->first;
189 }
190 }
191 NS_FATAL_ERROR("Could not find the flow with ID " << flowId);
192 FiveTuple retval = {Ipv6Address::GetZero(), Ipv6Address::GetZero(), 0, 0, 0};
193 return retval;
194}
195
196bool
197Ipv6FlowClassifier::SortByCount::operator()(std::pair<Ipv6Header::DscpType, uint32_t> left,
198 std::pair<Ipv6Header::DscpType, uint32_t> right)
199{
200 return left.second > right.second;
201}
202
203std::vector<std::pair<Ipv6Header::DscpType, uint32_t>>
205{
206 auto flow = m_flowDscpMap.find(flowId);
207
208 if (flow == m_flowDscpMap.end())
209 {
210 NS_FATAL_ERROR("Could not find the flow with ID " << flowId);
211 }
212
213 std::vector<std::pair<Ipv6Header::DscpType, uint32_t>> v(flow->second.begin(),
214 flow->second.end());
215 std::sort(v.begin(), v.end(), SortByCount());
216 return v;
217}
218
219void
220Ipv6FlowClassifier::SerializeToXmlStream(std::ostream& os, uint16_t indent) const
221{
222 Indent(os, indent);
223 os << "<Ipv6FlowClassifier>\n";
224
225 indent += 2;
226 for (auto iter = m_flowMap.begin(); iter != m_flowMap.end(); iter++)
227 {
228 Indent(os, indent);
229 os << "<Flow flowId=\"" << iter->second << "\""
230 << " sourceAddress=\"" << iter->first.sourceAddress << "\""
231 << " destinationAddress=\"" << iter->first.destinationAddress << "\""
232 << " protocol=\"" << int(iter->first.protocol) << "\""
233 << " sourcePort=\"" << iter->first.sourcePort << "\""
234 << " destinationPort=\"" << iter->first.destinationPort << "\">\n";
235
236 indent += 2;
237 auto flow = m_flowDscpMap.find(iter->second);
238
239 if (flow != m_flowDscpMap.end())
240 {
241 for (auto i = flow->second.begin(); i != flow->second.end(); i++)
242 {
243 Indent(os, indent);
244 os << "<Dscp value=\"0x" << std::hex << static_cast<uint32_t>(i->first) << "\""
245 << " packets=\"" << std::dec << i->second << "\" />\n";
246 }
247 }
248
249 indent -= 2;
250 Indent(os, indent);
251 os << "</Flow>\n";
252 }
253
254 indent -= 2;
255 Indent(os, indent);
256 os << "</Ipv6FlowClassifier>\n";
257}
258
259} // 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:77
#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.