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// SPDX-License-Identifier: GPL-2.0-only
5//
6// Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt> <gjcarneiro@gmail.com>
7//
8
9#include "ipv4-flow-probe.h"
10
11#include "flow-monitor.h"
13
14#include "ns3/config.h"
15#include "ns3/flow-id-tag.h"
16#include "ns3/log.h"
17#include "ns3/node.h"
18#include "ns3/packet.h"
19#include "ns3/pointer.h"
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("Ipv4FlowProbe");
25
26//////////////////////////////////////
27// Ipv4FlowProbeTag class implementation //
28//////////////////////////////////////
29
30/**
31 * \ingroup flow-monitor
32 *
33 * \brief Tag used to allow a fast identification of the packet
34 *
35 * This tag is added by FlowMonitor when a packet is seen for
36 * the first time, and it is then used to classify the packet in
37 * the following hops.
38 */
39class Ipv4FlowProbeTag : public Tag
40{
41 public:
42 /**
43 * \brief Get the type ID.
44 * \return the object TypeId
45 */
46 static TypeId GetTypeId();
47 TypeId GetInstanceTypeId() const override;
48 uint32_t GetSerializedSize() const override;
49 void Serialize(TagBuffer buf) const override;
50 void Deserialize(TagBuffer buf) override;
51 void Print(std::ostream& os) const override;
53 /**
54 * \brief Constructor
55 * \param flowId the flow identifier
56 * \param packetId the packet identifier
57 * \param packetSize the packet size
58 * \param src packet source address
59 * \param dst packet destination address
60 */
62 uint32_t packetId,
64 Ipv4Address src,
65 Ipv4Address dst);
66 /**
67 * \brief Set the flow identifier
68 * \param flowId the flow identifier
69 */
70 void SetFlowId(uint32_t flowId);
71 /**
72 * \brief Set the packet identifier
73 * \param packetId the packet identifier
74 */
75 void SetPacketId(uint32_t packetId);
76 /**
77 * \brief Set the packet size
78 * \param packetSize the packet size
79 */
81 /**
82 * \brief Set the flow identifier
83 * \returns the flow identifier
84 */
85 uint32_t GetFlowId() const;
86 /**
87 * \brief Set the packet identifier
88 * \returns the packet identifier
89 */
90 uint32_t GetPacketId() const;
91 /**
92 * \brief Get the packet size
93 * \returns the packet size
94 */
95 uint32_t GetPacketSize() const;
96 /**
97 * \brief Checks if the addresses stored in tag are matching
98 * the arguments.
99 *
100 * This check is important for IP over IP encapsulation.
101 *
102 * \param src Source address.
103 * \param dst Destination address.
104 * \returns True if the addresses are matching.
105 */
106 bool IsSrcDstValid(Ipv4Address src, Ipv4Address dst) const;
107
108 private:
109 uint32_t m_flowId; //!< flow identifier
110 uint32_t m_packetId; //!< packet identifier
111 uint32_t m_packetSize; //!< packet size
112 Ipv4Address m_src; //!< IP source
113 Ipv4Address m_dst; //!< IP destination
114};
115
116TypeId
118{
119 static TypeId tid = TypeId("ns3::Ipv4FlowProbeTag")
120 .SetParent<Tag>()
121 .SetGroupName("FlowMonitor")
122 .AddConstructor<Ipv4FlowProbeTag>();
123 return tid;
124}
125
126TypeId
128{
129 return GetTypeId();
130}
131
134{
135 return 4 + 4 + 4 + 8;
136}
137
138void
140{
141 buf.WriteU32(m_flowId);
142 buf.WriteU32(m_packetId);
144
145 uint8_t tBuf[4];
146 m_src.Serialize(tBuf);
147 buf.Write(tBuf, 4);
148 m_dst.Serialize(tBuf);
149 buf.Write(tBuf, 4);
150}
151
152void
154{
155 m_flowId = buf.ReadU32();
156 m_packetId = buf.ReadU32();
157 m_packetSize = buf.ReadU32();
158
159 uint8_t tBuf[4];
160 buf.Read(tBuf, 4);
162 buf.Read(tBuf, 4);
164}
165
166void
167Ipv4FlowProbeTag::Print(std::ostream& os) const
168{
169 os << "FlowId=" << m_flowId;
170 os << " PacketId=" << m_packetId;
171 os << " PacketSize=" << m_packetSize;
172}
173
178
180 uint32_t packetId,
182 Ipv4Address src,
183 Ipv4Address dst)
184 : Tag(),
185 m_flowId(flowId),
186 m_packetId(packetId),
187 m_packetSize(packetSize),
188 m_src(src),
189 m_dst(dst)
190{
191}
192
193void
198
199void
204
205void
210
213{
214 return m_flowId;
215}
216
219{
220 return m_packetId;
221}
222
225{
226 return m_packetSize;
227}
228
229bool
231{
232 return ((m_src == src) && (m_dst == dst));
233}
234
235////////////////////////////////////////
236// Ipv4FlowProbe class implementation //
237////////////////////////////////////////
238
240 Ptr<Ipv4FlowClassifier> classifier,
241 Ptr<Node> node)
242 : FlowProbe(monitor),
243 m_classifier(classifier)
244{
245 NS_LOG_FUNCTION(this << node->GetId());
246
247 m_ipv4 = node->GetObject<Ipv4L3Protocol>();
248
249 if (!m_ipv4->TraceConnectWithoutContext(
250 "SendOutgoing",
252 {
253 NS_FATAL_ERROR("trace fail");
254 }
255 if (!m_ipv4->TraceConnectWithoutContext(
256 "UnicastForward",
258 {
259 NS_FATAL_ERROR("trace fail");
260 }
261 if (!m_ipv4->TraceConnectWithoutContext(
262 "LocalDeliver",
264 {
265 NS_FATAL_ERROR("trace fail");
266 }
267
268 if (!m_ipv4->TraceConnectWithoutContext(
269 "Drop",
271 {
272 NS_FATAL_ERROR("trace fail");
273 }
274
275 std::ostringstream qd;
276 qd << "/NodeList/" << node->GetId() << "/$ns3::TrafficControlLayer/RootQueueDiscList/*/Drop";
278 qd.str(),
280
281 // code copied from point-to-point-helper.cc
282 std::ostringstream oss;
283 oss << "/NodeList/" << node->GetId() << "/DeviceList/*/TxQueue/Drop";
285 oss.str(),
287}
288
292
293/* static */
294TypeId
296{
297 static TypeId tid =
298 TypeId("ns3::Ipv4FlowProbe").SetParent<FlowProbe>().SetGroupName("FlowMonitor")
299 // No AddConstructor because this class has no default constructor.
300 ;
301
302 return tid;
303}
304
305void
307{
308 m_ipv4 = nullptr;
309 m_classifier = nullptr;
311}
312
313void
315 Ptr<const Packet> ipPayload,
316 uint32_t interface)
317{
318 FlowId flowId;
319 FlowPacketId packetId;
320
321 if (!m_ipv4->IsUnicast(ipHeader.GetDestination()))
322 {
323 // we are not prepared to handle broadcast yet
324 return;
325 }
326
327 Ipv4FlowProbeTag fTag;
328 bool found = ipPayload->FindFirstMatchingByteTag(fTag);
329 if (found)
330 {
331 return;
332 }
333
334 if (m_classifier->Classify(ipHeader, ipPayload, &flowId, &packetId))
335 {
336 uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
337 NS_LOG_DEBUG("ReportFirstTx (" << this << ", " << flowId << ", " << packetId << ", " << size
338 << "); " << ipHeader << *ipPayload);
339 m_flowMonitor->ReportFirstTx(this, flowId, packetId, size);
340
341 // tag the packet with the flow id and packet id, so that the packet can be identified even
342 // when Ipv4Header is not accessible at some non-IPv4 protocol layer
343 Ipv4FlowProbeTag fTag(flowId,
344 packetId,
345 size,
346 ipHeader.GetSource(),
347 ipHeader.GetDestination());
348 ipPayload->AddByteTag(fTag);
349 }
350}
351
352void
354 Ptr<const Packet> ipPayload,
355 uint32_t interface)
356{
357 Ipv4FlowProbeTag fTag;
358 bool found = ipPayload->FindFirstMatchingByteTag(fTag);
359
360 if (found)
361 {
362 if (!ipHeader.IsLastFragment() || ipHeader.GetFragmentOffset() != 0)
363 {
364 NS_LOG_WARN("Not counting fragmented packets");
365 return;
366 }
367 if (!fTag.IsSrcDstValid(ipHeader.GetSource(), ipHeader.GetDestination()))
368 {
369 NS_LOG_LOGIC("Not reporting encapsulated packet");
370 return;
371 }
372
373 FlowId flowId = fTag.GetFlowId();
374 FlowPacketId packetId = fTag.GetPacketId();
375
376 uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
377 NS_LOG_DEBUG("ReportForwarding (" << this << ", " << flowId << ", " << packetId << ", "
378 << size << ");");
379 m_flowMonitor->ReportForwarding(this, flowId, packetId, size);
380 }
381}
382
383void
385 Ptr<const Packet> ipPayload,
386 uint32_t interface)
387{
388 Ipv4FlowProbeTag fTag;
389 bool found = ipPayload->FindFirstMatchingByteTag(fTag);
390
391 if (found)
392 {
393 if (!fTag.IsSrcDstValid(ipHeader.GetSource(), ipHeader.GetDestination()))
394 {
395 NS_LOG_LOGIC("Not reporting encapsulated packet");
396 return;
397 }
398
399 FlowId flowId = fTag.GetFlowId();
400 FlowPacketId packetId = fTag.GetPacketId();
401
402 uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
403 NS_LOG_DEBUG("ReportLastRx (" << this << ", " << flowId << ", " << packetId << ", " << size
404 << "); " << ipHeader << *ipPayload);
405 m_flowMonitor->ReportLastRx(this, flowId, packetId, size);
406 }
407}
408
409void
411 Ptr<const Packet> ipPayload,
413 Ptr<Ipv4> ipv4,
414 uint32_t ifIndex)
415{
416#if 0
417 switch (reason)
418 {
420 break;
421
424 Ipv4Address addri = m_ipv4->GetAddress (ifIndex);
425 Ipv4Mask maski = m_ipv4->GetNetworkMask (ifIndex);
426 Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
427 if (ipHeader.GetDestination () == bcast) // we don't want broadcast packets
428 {
429 return;
430 }
431 }
432#endif
433
434 Ipv4FlowProbeTag fTag;
435 bool found = ipPayload->FindFirstMatchingByteTag(fTag);
436
437 if (found)
438 {
439 FlowId flowId = fTag.GetFlowId();
440 FlowPacketId packetId = fTag.GetPacketId();
441
442 uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
443 NS_LOG_DEBUG("Drop (" << this << ", " << flowId << ", " << packetId << ", " << size << ", "
444 << reason << ", destIp=" << ipHeader.GetDestination() << "); "
445 << "HDR: " << ipHeader << " PKT: " << *ipPayload);
446
447 DropReason myReason;
448
449 switch (reason)
450 {
452 myReason = DROP_TTL_EXPIRE;
453 NS_LOG_DEBUG("DROP_TTL_EXPIRE");
454 break;
456 myReason = DROP_NO_ROUTE;
457 NS_LOG_DEBUG("DROP_NO_ROUTE");
458 break;
460 myReason = DROP_BAD_CHECKSUM;
461 NS_LOG_DEBUG("DROP_BAD_CHECKSUM");
462 break;
464 myReason = DROP_INTERFACE_DOWN;
465 NS_LOG_DEBUG("DROP_INTERFACE_DOWN");
466 break;
468 myReason = DROP_ROUTE_ERROR;
469 NS_LOG_DEBUG("DROP_ROUTE_ERROR");
470 break;
472 myReason = DROP_FRAGMENT_TIMEOUT;
473 NS_LOG_DEBUG("DROP_FRAGMENT_TIMEOUT");
474 break;
475
476 default:
477 myReason = DROP_INVALID_REASON;
478 NS_FATAL_ERROR("Unexpected drop reason code " << reason);
479 }
480
481 m_flowMonitor->ReportDrop(this, flowId, packetId, size, myReason);
482 }
483}
484
485void
487{
488 Ipv4FlowProbeTag fTag;
489 bool tagFound = ipPayload->FindFirstMatchingByteTag(fTag);
490
491 if (!tagFound)
492 {
493 return;
494 }
495
496 FlowId flowId = fTag.GetFlowId();
497 FlowPacketId packetId = fTag.GetPacketId();
498 uint32_t size = fTag.GetPacketSize();
499
500 NS_LOG_DEBUG("Drop (" << this << ", " << flowId << ", " << packetId << ", " << size << ", "
501 << DROP_QUEUE << "); ");
502
503 m_flowMonitor->ReportDrop(this, flowId, packetId, size, DROP_QUEUE);
504}
505
506void
508{
509 Ipv4FlowProbeTag fTag;
510 bool tagFound = item->GetPacket()->FindFirstMatchingByteTag(fTag);
511
512 if (!tagFound)
513 {
514 return;
515 }
516
517 FlowId flowId = fTag.GetFlowId();
518 FlowPacketId packetId = fTag.GetPacketId();
519 uint32_t size = fTag.GetPacketSize();
520
521 NS_LOG_DEBUG("Drop (" << this << ", " << flowId << ", " << packetId << ", " << size << ", "
522 << DROP_QUEUE_DISC << "); ");
523
524 m_flowMonitor->ReportDrop(this, flowId, packetId, size, DROP_QUEUE_DISC);
525}
526
527} // namespace ns3
The FlowProbe class is responsible for listening for packet events in a specific point of the simulat...
Definition flow-probe.h:30
void DoDispose() override
Destructor implementation.
Definition flow-probe.cc:38
Ptr< FlowMonitor > m_flowMonitor
the FlowMonitor instance
Definition flow-probe.h:98
Ipv4 addresses are stored in host order in this class.
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:23
Ipv4Address GetSource() const
bool IsLastFragment() const
Ipv4Address GetDestination() const
uint32_t GetSerializedSize() const override
uint16_t GetFragmentOffset() const
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
Smart pointer class similar to boost::intrusive_ptr.
read and write tag data
Definition tag-buffer.h:41
TAG_BUFFER_INLINE uint32_t ReadU32()
Definition tag-buffer.h:206
void Read(uint8_t *buffer, uint32_t size)
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition tag-buffer.h:176
void Write(const uint8_t *buffer, uint32_t size)
tag a set of bytes in a packet
Definition tag.h:28
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase &cb)
Definition config.cc:953
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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:250
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:684
static const uint32_t packetSize
Packet size generated at the AP.