A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv4-flow-probe.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//
19
20#include "ipv4-flow-probe.h"
21
22#include "flow-monitor.h"
24
25#include "ns3/config.h"
26#include "ns3/flow-id-tag.h"
27#include "ns3/log.h"
28#include "ns3/node.h"
29#include "ns3/packet.h"
30#include "ns3/pointer.h"
31
32namespace ns3
33{
34
35NS_LOG_COMPONENT_DEFINE("Ipv4FlowProbe");
36
37//////////////////////////////////////
38// Ipv4FlowProbeTag 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 */
50class Ipv4FlowProbeTag : public Tag
51{
52 public:
53 /**
54 * \brief Get the type ID.
55 * \return the object TypeId
56 */
57 static TypeId GetTypeId();
58 TypeId GetInstanceTypeId() const override;
59 uint32_t GetSerializedSize() const override;
60 void Serialize(TagBuffer buf) const override;
61 void Deserialize(TagBuffer buf) override;
62 void Print(std::ostream& os) const override;
64 /**
65 * \brief Constructor
66 * \param flowId the flow identifier
67 * \param packetId the packet identifier
68 * \param packetSize the packet size
69 * \param src packet source address
70 * \param dst packet destination address
71 */
73 uint32_t packetId,
75 Ipv4Address src,
76 Ipv4Address dst);
77 /**
78 * \brief Set the flow identifier
79 * \param flowId the flow identifier
80 */
81 void SetFlowId(uint32_t flowId);
82 /**
83 * \brief Set the packet identifier
84 * \param packetId the packet identifier
85 */
86 void SetPacketId(uint32_t packetId);
87 /**
88 * \brief Set the packet size
89 * \param packetSize the packet size
90 */
92 /**
93 * \brief Set the flow identifier
94 * \returns the flow identifier
95 */
96 uint32_t GetFlowId() const;
97 /**
98 * \brief Set the packet identifier
99 * \returns the packet identifier
100 */
101 uint32_t GetPacketId() const;
102 /**
103 * \brief Get the packet size
104 * \returns the packet size
105 */
106 uint32_t GetPacketSize() const;
107 /**
108 * \brief Checks if the addresses stored in tag are matching
109 * the arguments.
110 *
111 * This check is important for IP over IP encapsulation.
112 *
113 * \param src Source address.
114 * \param dst Destination address.
115 * \returns True if the addresses are matching.
116 */
117 bool IsSrcDstValid(Ipv4Address src, Ipv4Address dst) const;
118
119 private:
120 uint32_t m_flowId; //!< flow identifier
121 uint32_t m_packetId; //!< packet identifier
122 uint32_t m_packetSize; //!< packet size
123 Ipv4Address m_src; //!< IP source
124 Ipv4Address m_dst; //!< IP destination
125};
126
127TypeId
129{
130 static TypeId tid = TypeId("ns3::Ipv4FlowProbeTag")
131 .SetParent<Tag>()
132 .SetGroupName("FlowMonitor")
133 .AddConstructor<Ipv4FlowProbeTag>();
134 return tid;
135}
136
137TypeId
139{
140 return GetTypeId();
141}
142
145{
146 return 4 + 4 + 4 + 8;
147}
148
149void
151{
152 buf.WriteU32(m_flowId);
153 buf.WriteU32(m_packetId);
155
156 uint8_t tBuf[4];
157 m_src.Serialize(tBuf);
158 buf.Write(tBuf, 4);
159 m_dst.Serialize(tBuf);
160 buf.Write(tBuf, 4);
161}
162
163void
165{
166 m_flowId = buf.ReadU32();
167 m_packetId = buf.ReadU32();
168 m_packetSize = buf.ReadU32();
169
170 uint8_t tBuf[4];
171 buf.Read(tBuf, 4);
173 buf.Read(tBuf, 4);
175}
176
177void
178Ipv4FlowProbeTag::Print(std::ostream& os) const
179{
180 os << "FlowId=" << m_flowId;
181 os << " PacketId=" << m_packetId;
182 os << " PacketSize=" << m_packetSize;
183}
184
186 : Tag()
187{
188}
189
191 uint32_t packetId,
193 Ipv4Address src,
194 Ipv4Address dst)
195 : Tag(),
196 m_flowId(flowId),
197 m_packetId(packetId),
198 m_packetSize(packetSize),
199 m_src(src),
200 m_dst(dst)
201{
202}
203
204void
206{
207 m_flowId = id;
208}
209
210void
212{
213 m_packetId = id;
214}
215
216void
218{
219 m_packetSize = size;
220}
221
224{
225 return m_flowId;
226}
227
230{
231 return m_packetId;
232}
233
236{
237 return m_packetSize;
238}
239
240bool
242{
243 return ((m_src == src) && (m_dst == dst));
244}
245
246////////////////////////////////////////
247// Ipv4FlowProbe class implementation //
248////////////////////////////////////////
249
251 Ptr<Ipv4FlowClassifier> classifier,
252 Ptr<Node> node)
253 : FlowProbe(monitor),
254 m_classifier(classifier)
255{
256 NS_LOG_FUNCTION(this << node->GetId());
257
258 m_ipv4 = node->GetObject<Ipv4L3Protocol>();
259
260 if (!m_ipv4->TraceConnectWithoutContext(
261 "SendOutgoing",
263 {
264 NS_FATAL_ERROR("trace fail");
265 }
266 if (!m_ipv4->TraceConnectWithoutContext(
267 "UnicastForward",
269 {
270 NS_FATAL_ERROR("trace fail");
271 }
272 if (!m_ipv4->TraceConnectWithoutContext(
273 "LocalDeliver",
275 {
276 NS_FATAL_ERROR("trace fail");
277 }
278
279 if (!m_ipv4->TraceConnectWithoutContext(
280 "Drop",
282 {
283 NS_FATAL_ERROR("trace fail");
284 }
285
286 std::ostringstream qd;
287 qd << "/NodeList/" << node->GetId() << "/$ns3::TrafficControlLayer/RootQueueDiscList/*/Drop";
289 qd.str(),
291
292 // code copied from point-to-point-helper.cc
293 std::ostringstream oss;
294 oss << "/NodeList/" << node->GetId() << "/DeviceList/*/TxQueue/Drop";
296 oss.str(),
298}
299
301{
302}
303
304/* static */
305TypeId
307{
308 static TypeId tid =
309 TypeId("ns3::Ipv4FlowProbe").SetParent<FlowProbe>().SetGroupName("FlowMonitor")
310 // No AddConstructor because this class has no default constructor.
311 ;
312
313 return tid;
314}
315
316void
318{
319 m_ipv4 = nullptr;
320 m_classifier = nullptr;
322}
323
324void
326 Ptr<const Packet> ipPayload,
327 uint32_t interface)
328{
329 FlowId flowId;
330 FlowPacketId packetId;
331
332 if (!m_ipv4->IsUnicast(ipHeader.GetDestination()))
333 {
334 // we are not prepared to handle broadcast yet
335 return;
336 }
337
338 Ipv4FlowProbeTag fTag;
339 bool found = ipPayload->FindFirstMatchingByteTag(fTag);
340 if (found)
341 {
342 return;
343 }
344
345 if (m_classifier->Classify(ipHeader, ipPayload, &flowId, &packetId))
346 {
347 uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
348 NS_LOG_DEBUG("ReportFirstTx (" << this << ", " << flowId << ", " << packetId << ", " << size
349 << "); " << ipHeader << *ipPayload);
350 m_flowMonitor->ReportFirstTx(this, flowId, packetId, size);
351
352 // tag the packet with the flow id and packet id, so that the packet can be identified even
353 // when Ipv4Header is not accessible at some non-IPv4 protocol layer
354 Ipv4FlowProbeTag fTag(flowId,
355 packetId,
356 size,
357 ipHeader.GetSource(),
358 ipHeader.GetDestination());
359 ipPayload->AddByteTag(fTag);
360 }
361}
362
363void
365 Ptr<const Packet> ipPayload,
366 uint32_t interface)
367{
368 Ipv4FlowProbeTag fTag;
369 bool found = ipPayload->FindFirstMatchingByteTag(fTag);
370
371 if (found)
372 {
373 if (!ipHeader.IsLastFragment() || ipHeader.GetFragmentOffset() != 0)
374 {
375 NS_LOG_WARN("Not counting fragmented packets");
376 return;
377 }
378 if (!fTag.IsSrcDstValid(ipHeader.GetSource(), ipHeader.GetDestination()))
379 {
380 NS_LOG_LOGIC("Not reporting encapsulated packet");
381 return;
382 }
383
384 FlowId flowId = fTag.GetFlowId();
385 FlowPacketId packetId = fTag.GetPacketId();
386
387 uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
388 NS_LOG_DEBUG("ReportForwarding (" << this << ", " << flowId << ", " << packetId << ", "
389 << size << ");");
390 m_flowMonitor->ReportForwarding(this, flowId, packetId, size);
391 }
392}
393
394void
396 Ptr<const Packet> ipPayload,
397 uint32_t interface)
398{
399 Ipv4FlowProbeTag fTag;
400 bool found = ipPayload->FindFirstMatchingByteTag(fTag);
401
402 if (found)
403 {
404 if (!fTag.IsSrcDstValid(ipHeader.GetSource(), ipHeader.GetDestination()))
405 {
406 NS_LOG_LOGIC("Not reporting encapsulated packet");
407 return;
408 }
409
410 FlowId flowId = fTag.GetFlowId();
411 FlowPacketId packetId = fTag.GetPacketId();
412
413 uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
414 NS_LOG_DEBUG("ReportLastRx (" << this << ", " << flowId << ", " << packetId << ", " << size
415 << "); " << ipHeader << *ipPayload);
416 m_flowMonitor->ReportLastRx(this, flowId, packetId, size);
417 }
418}
419
420void
422 Ptr<const Packet> ipPayload,
424 Ptr<Ipv4> ipv4,
425 uint32_t ifIndex)
426{
427#if 0
428 switch (reason)
429 {
431 break;
432
435 Ipv4Address addri = m_ipv4->GetAddress (ifIndex);
436 Ipv4Mask maski = m_ipv4->GetNetworkMask (ifIndex);
437 Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
438 if (ipHeader.GetDestination () == bcast) // we don't want broadcast packets
439 {
440 return;
441 }
442 }
443#endif
444
445 Ipv4FlowProbeTag fTag;
446 bool found = ipPayload->FindFirstMatchingByteTag(fTag);
447
448 if (found)
449 {
450 FlowId flowId = fTag.GetFlowId();
451 FlowPacketId packetId = fTag.GetPacketId();
452
453 uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
454 NS_LOG_DEBUG("Drop (" << this << ", " << flowId << ", " << packetId << ", " << size << ", "
455 << reason << ", destIp=" << ipHeader.GetDestination() << "); "
456 << "HDR: " << ipHeader << " PKT: " << *ipPayload);
457
458 DropReason myReason;
459
460 switch (reason)
461 {
463 myReason = DROP_TTL_EXPIRE;
464 NS_LOG_DEBUG("DROP_TTL_EXPIRE");
465 break;
467 myReason = DROP_NO_ROUTE;
468 NS_LOG_DEBUG("DROP_NO_ROUTE");
469 break;
471 myReason = DROP_BAD_CHECKSUM;
472 NS_LOG_DEBUG("DROP_BAD_CHECKSUM");
473 break;
475 myReason = DROP_INTERFACE_DOWN;
476 NS_LOG_DEBUG("DROP_INTERFACE_DOWN");
477 break;
479 myReason = DROP_ROUTE_ERROR;
480 NS_LOG_DEBUG("DROP_ROUTE_ERROR");
481 break;
483 myReason = DROP_FRAGMENT_TIMEOUT;
484 NS_LOG_DEBUG("DROP_FRAGMENT_TIMEOUT");
485 break;
486
487 default:
488 myReason = DROP_INVALID_REASON;
489 NS_FATAL_ERROR("Unexpected drop reason code " << reason);
490 }
491
492 m_flowMonitor->ReportDrop(this, flowId, packetId, size, myReason);
493 }
494}
495
496void
498{
499 Ipv4FlowProbeTag fTag;
500 bool tagFound = ipPayload->FindFirstMatchingByteTag(fTag);
501
502 if (!tagFound)
503 {
504 return;
505 }
506
507 FlowId flowId = fTag.GetFlowId();
508 FlowPacketId packetId = fTag.GetPacketId();
509 uint32_t size = fTag.GetPacketSize();
510
511 NS_LOG_DEBUG("Drop (" << this << ", " << flowId << ", " << packetId << ", " << size << ", "
512 << DROP_QUEUE << "); ");
513
514 m_flowMonitor->ReportDrop(this, flowId, packetId, size, DROP_QUEUE);
515}
516
517void
519{
520 Ipv4FlowProbeTag fTag;
521 bool tagFound = item->GetPacket()->FindFirstMatchingByteTag(fTag);
522
523 if (!tagFound)
524 {
525 return;
526 }
527
528 FlowId flowId = fTag.GetFlowId();
529 FlowPacketId packetId = fTag.GetPacketId();
530 uint32_t size = fTag.GetPacketSize();
531
532 NS_LOG_DEBUG("Drop (" << this << ", " << flowId << ", " << packetId << ", " << size << ", "
533 << DROP_QUEUE_DISC << "); ");
534
535 m_flowMonitor->ReportDrop(this, flowId, packetId, size, DROP_QUEUE_DISC);
536}
537
538} // namespace ns3
The FlowProbe class is responsible for listening for packet events in a specific point of the simulat...
Definition: flow-probe.h:41
void DoDispose() override
Destructor implementation.
Definition: flow-probe.cc:49
Ptr< FlowMonitor > m_flowMonitor
the FlowMonitor instance
Definition: flow-probe.h:109
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
Ipv4Address GetSubnetDirectedBroadcast(const Ipv4Mask &mask) const
Generate subnet-directed broadcast address corresponding to mask.
void Serialize(uint8_t buf[4]) const
Serialize this address to a 4-byte buffer.
static Ipv4Address Deserialize(const uint8_t buf[4])
DropReason
enumeration of possible reasons why a packet may be dropped
@ DROP_ROUTE_ERROR
Route error.
@ DROP_BAD_CHECKSUM
Packet dropped due to invalid checksum in the IPv4 header.
@ DROP_TTL_EXPIRE
Packet dropped due to TTL decremented to zero during IPv4 forwarding.
@ DROP_INTERFACE_DOWN
Interface is down so can not send packet.
@ DROP_NO_ROUTE
Packet dropped due to missing route to the destination.
@ DROP_INVALID_REASON
Fallback reason (no known reason)
@ DROP_QUEUE_DISC
Packet dropped by the queue disc.
@ DROP_FRAGMENT_TIMEOUT
Fragment timeout exceeded.
@ DROP_QUEUE
Packet dropped due to queue overflow.
void SendOutgoingLogger(const Ipv4Header &ipHeader, Ptr< const Packet > ipPayload, uint32_t interface)
Log a packet being sent.
void DropLogger(const Ipv4Header &ipHeader, Ptr< const Packet > ipPayload, Ipv4L3Protocol::DropReason reason, Ptr< Ipv4 > ipv4, uint32_t ifIndex)
Log a packet being dropped.
void QueueDropLogger(Ptr< const Packet > ipPayload)
Log a packet being dropped by a queue.
void ForwardUpLogger(const Ipv4Header &ipHeader, Ptr< const Packet > ipPayload, uint32_t interface)
Log a packet being received by the destination.
Ptr< Ipv4L3Protocol > m_ipv4
the Ipv4L3Protocol this probe is bound to
static TypeId GetTypeId()
Register this type.
void DoDispose() override
Destructor implementation.
Ipv4FlowProbe(Ptr< FlowMonitor > monitor, Ptr< Ipv4FlowClassifier > classifier, Ptr< Node > node)
Constructor.
void QueueDiscDropLogger(Ptr< const QueueDiscItem > item)
Log a packet being dropped by a queue disc.
void ForwardLogger(const Ipv4Header &ipHeader, Ptr< const Packet > ipPayload, uint32_t interface)
Log a packet being forwarded.
Ptr< Ipv4FlowClassifier > m_classifier
the Ipv4FlowClassifier this probe is associated with
Tag used to allow a fast identification of the packet.
uint32_t GetPacketId() const
Set the packet identifier.
void Deserialize(TagBuffer buf) override
uint32_t m_packetSize
packet size
void Print(std::ostream &os) const override
uint32_t GetPacketSize() const
Get the packet size.
bool IsSrcDstValid(Ipv4Address src, Ipv4Address dst) const
Checks if the addresses stored in tag are matching the arguments.
Ipv4Address m_dst
IP destination.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
static TypeId GetTypeId()
Get the type ID.
void SetPacketSize(uint32_t packetSize)
Set the packet size.
uint32_t m_packetId
packet identifier
uint32_t GetSerializedSize() const override
void Serialize(TagBuffer buf) const override
void SetFlowId(uint32_t flowId)
Set the flow identifier.
uint32_t m_flowId
flow identifier
uint32_t GetFlowId() const
Set the flow identifier.
void SetPacketId(uint32_t packetId)
Set the packet identifier.
Ipv4Address m_src
IP source.
Packet header for IPv4.
Definition: ipv4-header.h:34
Ipv4Address GetSource() const
Definition: ipv4-header.cc:302
bool IsLastFragment() const
Definition: ipv4-header.cc:217
Ipv4Address GetDestination() const
Definition: ipv4-header.cc:316
uint32_t GetSerializedSize() const override
Definition: ipv4-header.cc:384
uint16_t GetFragmentOffset() const
Definition: ipv4-header.cc:254
Implement the IPv4 layer.
DropReason
Reason why a packet has been dropped.
@ DROP_BAD_CHECKSUM
Bad checksum.
@ DROP_NO_ROUTE
No route to host.
@ DROP_INTERFACE_DOWN
Interface is down so can not send packet.
@ DROP_TTL_EXPIRED
Packet TTL has expired.
@ DROP_ROUTE_ERROR
Route error.
@ DROP_FRAGMENT_TIMEOUT
Fragment timeout exceeded.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:257
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
read and write tag data
Definition: tag-buffer.h:52
TAG_BUFFER_INLINE uint32_t ReadU32()
Definition: tag-buffer.h:217
void Read(uint8_t *buffer, uint32_t size)
Definition: tag-buffer.cc:183
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition: tag-buffer.h:187
void Write(const uint8_t *buffer, uint32_t size)
Definition: tag-buffer.cc:129
tag a set of bytes in a packet
Definition: tag.h:39
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:964
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
static const uint32_t packetSize
Packet size generated at the AP.