|
|
|
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/ipv6-flow-probe.h" |
23 |
#include "ns3/ipv6-flow-classifier.h" |
24 |
#include "ns3/node.h" |
25 |
#include "ns3/packet.h" |
26 |
#include "ns3/flow-monitor.h" |
27 |
#include "ns3/log.h" |
28 |
#include "ns3/pointer.h" |
29 |
#include "ns3/config.h" |
30 |
#include "ns3/flow-id-tag.h" |
31 |
|
32 |
namespace ns3 { |
33 |
|
34 |
NS_LOG_COMPONENT_DEFINE ("Ipv6FlowProbe") |
35 |
; |
36 |
|
37 |
////////////////////////////////////// |
38 |
// Ipv6FlowProbeTag class implementation // |
39 |
////////////////////////////////////// |
40 |
|
41 |
/** |
42 |
* \ingroup flow-monitor |
43 |
* |
44 |
* \brief Tag used to allow a fast identification of the packet |
45 |
* |
46 |
* This tag is added by FlowMonitor when a packet is seen for |
47 |
* the first time, and it is then used to classify the packet in |
48 |
* the following hops. |
49 |
*/ |
50 |
class Ipv6FlowProbeTag : public Tag |
51 |
{ |
52 |
public: |
53 |
/** |
54 |
* \brief Get the type ID. |
55 |
* \return the object TypeId |
56 |
*/ |
57 |
static TypeId GetTypeId (void); |
58 |
virtual TypeId GetInstanceTypeId (void) const; |
59 |
virtual uint32_t GetSerializedSize (void) const; |
60 |
virtual void Serialize (TagBuffer buf) const; |
61 |
virtual void Deserialize (TagBuffer buf); |
62 |
virtual void Print (std::ostream &os) const; |
63 |
Ipv6FlowProbeTag (); |
64 |
/** |
65 |
* \brief Consructor |
66 |
* \param flowId the flow identifier |
67 |
* \param packetId the packet identifier |
68 |
* \param packetSize the packet size |
69 |
*/ |
70 |
Ipv6FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize); |
71 |
/** |
72 |
* \brief Set the flow identifier |
73 |
* \param flowId the flow identifier |
74 |
*/ |
75 |
void SetFlowId (uint32_t flowId); |
76 |
/** |
77 |
* \brief Set the packet identifier |
78 |
* \param packetId the packet identifier |
79 |
*/ |
80 |
void SetPacketId (uint32_t packetId); |
81 |
/** |
82 |
* \brief Set the packet size |
83 |
* \param packetSize the packet size |
84 |
*/ |
85 |
void SetPacketSize (uint32_t packetSize); |
86 |
/** |
87 |
* \brief Set the flow identifier |
88 |
* \returns the flow identifier |
89 |
*/ |
90 |
uint32_t GetFlowId (void) const; |
91 |
/** |
92 |
* \brief Set the packet identifier |
93 |
* \returns the packet identifier |
94 |
*/ |
95 |
uint32_t GetPacketId (void) const; |
96 |
/** |
97 |
* \brief Get the packet size |
98 |
* \returns the packet size |
99 |
*/ |
100 |
uint32_t GetPacketSize (void) const; |
101 |
private: |
102 |
uint32_t m_flowId; //!< flow identifier |
103 |
uint32_t m_packetId; //!< packet identifier |
104 |
uint32_t m_packetSize; //!< packet size |
105 |
|
106 |
}; |
107 |
|
108 |
TypeId |
109 |
Ipv6FlowProbeTag::GetTypeId (void) |
110 |
{ |
111 |
static TypeId tid = TypeId ("ns3::Ipv6FlowProbeTag") |
112 |
.SetParent<Tag> () |
113 |
.AddConstructor<Ipv6FlowProbeTag> () |
114 |
; |
115 |
return tid; |
116 |
} |
117 |
TypeId |
118 |
Ipv6FlowProbeTag::GetInstanceTypeId (void) const |
119 |
{ |
120 |
return GetTypeId (); |
121 |
} |
122 |
uint32_t |
123 |
Ipv6FlowProbeTag::GetSerializedSize (void) const |
124 |
{ |
125 |
return 4 + 4 + 4; |
126 |
} |
127 |
void |
128 |
Ipv6FlowProbeTag::Serialize (TagBuffer buf) const |
129 |
{ |
130 |
buf.WriteU32 (m_flowId); |
131 |
buf.WriteU32 (m_packetId); |
132 |
buf.WriteU32 (m_packetSize); |
133 |
} |
134 |
void |
135 |
Ipv6FlowProbeTag::Deserialize (TagBuffer buf) |
136 |
{ |
137 |
m_flowId = buf.ReadU32 (); |
138 |
m_packetId = buf.ReadU32 (); |
139 |
m_packetSize = buf.ReadU32 (); |
140 |
} |
141 |
void |
142 |
Ipv6FlowProbeTag::Print (std::ostream &os) const |
143 |
{ |
144 |
os << "FlowId=" << m_flowId; |
145 |
os << "PacketId=" << m_packetId; |
146 |
os << "PacketSize=" << m_packetSize; |
147 |
} |
148 |
Ipv6FlowProbeTag::Ipv6FlowProbeTag () |
149 |
: Tag () |
150 |
{ |
151 |
} |
152 |
|
153 |
Ipv6FlowProbeTag::Ipv6FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize) |
154 |
: Tag (), m_flowId (flowId), m_packetId (packetId), m_packetSize (packetSize) |
155 |
{ |
156 |
} |
157 |
|
158 |
void |
159 |
Ipv6FlowProbeTag::SetFlowId (uint32_t id) |
160 |
{ |
161 |
m_flowId = id; |
162 |
} |
163 |
void |
164 |
Ipv6FlowProbeTag::SetPacketId (uint32_t id) |
165 |
{ |
166 |
m_packetId = id; |
167 |
} |
168 |
void |
169 |
Ipv6FlowProbeTag::SetPacketSize (uint32_t size) |
170 |
{ |
171 |
m_packetSize = size; |
172 |
} |
173 |
uint32_t |
174 |
Ipv6FlowProbeTag::GetFlowId (void) const |
175 |
{ |
176 |
return m_flowId; |
177 |
} |
178 |
uint32_t |
179 |
Ipv6FlowProbeTag::GetPacketId (void) const |
180 |
{ |
181 |
return m_packetId; |
182 |
} |
183 |
uint32_t |
184 |
Ipv6FlowProbeTag::GetPacketSize (void) const |
185 |
{ |
186 |
return m_packetSize; |
187 |
} |
188 |
|
189 |
//////////////////////////////////////// |
190 |
// Ipv6FlowProbe class implementation // |
191 |
//////////////////////////////////////// |
192 |
|
193 |
Ipv6FlowProbe::Ipv6FlowProbe (Ptr<FlowMonitor> monitor, |
194 |
Ptr<Ipv6FlowClassifier> classifier, |
195 |
Ptr<Node> node) |
196 |
: FlowProbe (monitor), |
197 |
m_classifier (classifier) |
198 |
{ |
199 |
NS_LOG_FUNCTION (this << node->GetId ()); |
200 |
|
201 |
Ptr<Ipv6L3Protocol> ipv6 = node->GetObject<Ipv6L3Protocol> (); |
202 |
|
203 |
if (!ipv6->TraceConnectWithoutContext ("SendOutgoing", |
204 |
MakeCallback (&Ipv6FlowProbe::SendOutgoingLogger, Ptr<Ipv6FlowProbe> (this)))) |
205 |
{ |
206 |
NS_FATAL_ERROR ("trace fail"); |
207 |
} |
208 |
if (!ipv6->TraceConnectWithoutContext ("UnicastForward", |
209 |
MakeCallback (&Ipv6FlowProbe::ForwardLogger, Ptr<Ipv6FlowProbe> (this)))) |
210 |
{ |
211 |
NS_FATAL_ERROR ("trace fail"); |
212 |
} |
213 |
if (!ipv6->TraceConnectWithoutContext ("LocalDeliver", |
214 |
MakeCallback (&Ipv6FlowProbe::ForwardUpLogger, Ptr<Ipv6FlowProbe> (this)))) |
215 |
{ |
216 |
NS_FATAL_ERROR ("trace fail"); |
217 |
} |
218 |
|
219 |
if (!ipv6->TraceConnectWithoutContext ("Drop", |
220 |
MakeCallback (&Ipv6FlowProbe::DropLogger, Ptr<Ipv6FlowProbe> (this)))) |
221 |
{ |
222 |
NS_FATAL_ERROR ("trace fail"); |
223 |
} |
224 |
|
225 |
// code copied from point-to-point-helper.cc |
226 |
std::ostringstream oss; |
227 |
oss << "/NodeList/" << node->GetId () << "/DeviceList/*/TxQueue/Drop"; |
228 |
Config::ConnectWithoutContext (oss.str (), MakeCallback (&Ipv6FlowProbe::QueueDropLogger, Ptr<Ipv6FlowProbe> (this))); |
229 |
} |
230 |
|
231 |
Ipv6FlowProbe::~Ipv6FlowProbe () |
232 |
{ |
233 |
} |
234 |
|
235 |
void |
236 |
Ipv6FlowProbe::DoDispose () |
237 |
{ |
238 |
FlowProbe::DoDispose (); |
239 |
} |
240 |
|
241 |
void |
242 |
Ipv6FlowProbe::SendOutgoingLogger (const Ipv6Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface) |
243 |
{ |
244 |
FlowId flowId; |
245 |
FlowPacketId packetId; |
246 |
|
247 |
if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId)) |
248 |
{ |
249 |
uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ()); |
250 |
NS_LOG_DEBUG ("ReportFirstTx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<"); " |
251 |
<< ipHeader << *ipPayload); |
252 |
m_flowMonitor->ReportFirstTx (this, flowId, packetId, size); |
253 |
|
254 |
// tag the packet with the flow id and packet id, so that the packet can be identified even |
255 |
// when Ipv6Header is not accessible at some non-IPv6 protocol layer |
256 |
Ipv6FlowProbeTag fTag (flowId, packetId, size); |
257 |
ipPayload->AddPacketTag (fTag); |
258 |
} |
259 |
} |
260 |
|
261 |
void |
262 |
Ipv6FlowProbe::ForwardLogger (const Ipv6Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface) |
263 |
{ |
264 |
// peek the tags that are added by Ipv6FlowProbe::SendOutgoingLogger () |
265 |
Ipv6FlowProbeTag fTag; |
266 |
|
267 |
bool found = ipPayload->PeekPacketTag (fTag); |
268 |
|
269 |
if (found) |
270 |
{ |
271 |
FlowId flowId = fTag.GetFlowId (); |
272 |
FlowPacketId packetId = fTag.GetPacketId (); |
273 |
|
274 |
uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ()); |
275 |
NS_LOG_DEBUG ("ReportForwarding ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");"); |
276 |
m_flowMonitor->ReportForwarding (this, flowId, packetId, size); |
277 |
} |
278 |
} |
279 |
|
280 |
void |
281 |
Ipv6FlowProbe::ForwardUpLogger (const Ipv6Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface) |
282 |
{ |
283 |
// remove the tags that are added by Ipv6FlowProbe::SendOutgoingLogger () |
284 |
Ipv6FlowProbeTag fTag; |
285 |
|
286 |
// ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904 |
287 |
bool found = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag); |
288 |
|
289 |
if (found) |
290 |
{ |
291 |
FlowId flowId = fTag.GetFlowId (); |
292 |
FlowPacketId packetId = fTag.GetPacketId (); |
293 |
|
294 |
uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ()); |
295 |
NS_LOG_DEBUG ("ReportLastRx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");"); |
296 |
m_flowMonitor->ReportLastRx (this, flowId, packetId, size); |
297 |
} |
298 |
} |
299 |
|
300 |
void |
301 |
Ipv6FlowProbe::DropLogger (const Ipv6Header &ipHeader, Ptr<const Packet> ipPayload, |
302 |
Ipv6L3Protocol::DropReason reason, Ptr<Ipv6> ipv6, uint32_t ifIndex) |
303 |
{ |
304 |
#if 0 |
305 |
switch (reason) |
306 |
{ |
307 |
case Ipv6L3Protocol::DROP_NO_ROUTE: |
308 |
break; |
309 |
|
310 |
case Ipv6L3Protocol::DROP_TTL_EXPIRED: |
311 |
case Ipv6L3Protocol::DROP_BAD_CHECKSUM: |
312 |
Ipv6Address addri = m_ipv6->GetAddress (ifIndex); |
313 |
Ipv6Mask maski = m_ipv6->GetNetworkMask (ifIndex); |
314 |
Ipv6Address bcast = addri.GetSubnetDirectedBroadcast (maski); |
315 |
if (ipHeader.GetDestination () == bcast) // we don't want broadcast packets |
316 |
{ |
317 |
return; |
318 |
} |
319 |
} |
320 |
#endif |
321 |
|
322 |
// remove the tags that are added by Ipv6FlowProbe::SendOutgoingLogger () |
323 |
Ipv6FlowProbeTag fTag; |
324 |
|
325 |
// ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904 |
326 |
bool found = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag); |
327 |
|
328 |
if (found) |
329 |
{ |
330 |
FlowId flowId = fTag.GetFlowId (); |
331 |
FlowPacketId packetId = fTag.GetPacketId (); |
332 |
|
333 |
uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ()); |
334 |
NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << reason |
335 |
<< ", destIp=" << ipHeader.GetDestinationAddress () << "); " |
336 |
<< "HDR: " << ipHeader << " PKT: " << *ipPayload); |
337 |
|
338 |
DropReason myReason; |
339 |
|
340 |
|
341 |
switch (reason) |
342 |
{ |
343 |
case Ipv6L3Protocol::DROP_TTL_EXPIRED: |
344 |
myReason = DROP_TTL_EXPIRE; |
345 |
NS_LOG_DEBUG ("DROP_TTL_EXPIRE"); |
346 |
break; |
347 |
case Ipv6L3Protocol::DROP_NO_ROUTE: |
348 |
myReason = DROP_NO_ROUTE; |
349 |
NS_LOG_DEBUG ("DROP_NO_ROUTE"); |
350 |
break; |
351 |
case Ipv6L3Protocol::DROP_INTERFACE_DOWN: |
352 |
myReason = DROP_INTERFACE_DOWN; |
353 |
NS_LOG_DEBUG ("DROP_INTERFACE_DOWN"); |
354 |
break; |
355 |
case Ipv6L3Protocol::DROP_ROUTE_ERROR: |
356 |
myReason = DROP_ROUTE_ERROR; |
357 |
NS_LOG_DEBUG ("DROP_ROUTE_ERROR"); |
358 |
break; |
359 |
case Ipv6L3Protocol::DROP_UNKNOWN_PROTOCOL: |
360 |
myReason = DROP_UNKNOWN_PROTOCOL; |
361 |
NS_LOG_DEBUG ("DROP_UNKNOWN_PROTOCOL"); |
362 |
break; |
363 |
case Ipv6L3Protocol::DROP_UNKNOWN_OPTION: |
364 |
myReason = DROP_UNKNOWN_OPTION; |
365 |
NS_LOG_DEBUG ("DROP_UNKNOWN_OPTION"); |
366 |
break; |
367 |
case Ipv6L3Protocol::DROP_MALFORMED_HEADER: |
368 |
myReason = DROP_MALFORMED_HEADER; |
369 |
NS_LOG_DEBUG ("DROP_MALFORMED_HEADER"); |
370 |
break; |
371 |
case Ipv6L3Protocol::DROP_FRAGMENT_TIMEOUT: |
372 |
myReason = DROP_FRAGMENT_TIMEOUT; |
373 |
NS_LOG_DEBUG ("DROP_FRAGMENT_TIMEOUT"); |
374 |
break; |
375 |
default: |
376 |
myReason = DROP_INVALID_REASON; |
377 |
NS_FATAL_ERROR ("Unexpected drop reason code " << reason); |
378 |
} |
379 |
|
380 |
m_flowMonitor->ReportDrop (this, flowId, packetId, size, myReason); |
381 |
} |
382 |
} |
383 |
|
384 |
void |
385 |
Ipv6FlowProbe::QueueDropLogger (Ptr<const Packet> ipPayload) |
386 |
{ |
387 |
// remove the tags that are added by Ipv6FlowProbe::SendOutgoingLogger () |
388 |
Ipv6FlowProbeTag fTag; |
389 |
|
390 |
// ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904 |
391 |
bool tagFound = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag); |
392 |
if (!tagFound) |
393 |
{ |
394 |
return; |
395 |
} |
396 |
|
397 |
FlowId flowId = fTag.GetFlowId (); |
398 |
FlowPacketId packetId = fTag.GetPacketId (); |
399 |
uint32_t size = fTag.GetPacketSize (); |
400 |
|
401 |
NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << DROP_QUEUE |
402 |
<< "); "); |
403 |
|
404 |
m_flowMonitor->ReportDrop (this, flowId, packetId, size, DROP_QUEUE); |
405 |
} |
406 |
|
407 |
} // namespace ns3 |
408 |
|
409 |
|