A Discrete-Event Network Simulator
API
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 "ns3/ipv4-flow-probe.h"
21 
22 #include "ns3/config.h"
23 #include "ns3/flow-id-tag.h"
24 #include "ns3/flow-monitor.h"
25 #include "ns3/ipv4-flow-classifier.h"
26 #include "ns3/log.h"
27 #include "ns3/node.h"
28 #include "ns3/packet.h"
29 #include "ns3/pointer.h"
30 
31 namespace ns3
32 {
33 
34 NS_LOG_COMPONENT_DEFINE("Ipv4FlowProbe");
35 
37 // Ipv4FlowProbeTag class implementation //
39 
49 class Ipv4FlowProbeTag : public Tag
50 {
51  public:
56  static TypeId GetTypeId();
57  TypeId GetInstanceTypeId() const override;
58  uint32_t GetSerializedSize() const override;
59  void Serialize(TagBuffer buf) const override;
60  void Deserialize(TagBuffer buf) override;
61  void Print(std::ostream& os) const override;
71  Ipv4FlowProbeTag(uint32_t flowId,
72  uint32_t packetId,
73  uint32_t packetSize,
74  Ipv4Address src,
75  Ipv4Address dst);
80  void SetFlowId(uint32_t flowId);
85  void SetPacketId(uint32_t packetId);
90  void SetPacketSize(uint32_t packetSize);
95  uint32_t GetFlowId() const;
100  uint32_t GetPacketId() const;
105  uint32_t GetPacketSize() const;
116  bool IsSrcDstValid(Ipv4Address src, Ipv4Address dst) const;
117 
118  private:
119  uint32_t m_flowId;
120  uint32_t m_packetId;
121  uint32_t m_packetSize;
124 };
125 
126 TypeId
128 {
129  static TypeId tid = TypeId("ns3::Ipv4FlowProbeTag")
130  .SetParent<Tag>()
131  .SetGroupName("FlowMonitor")
132  .AddConstructor<Ipv4FlowProbeTag>();
133  return tid;
134 }
135 
136 TypeId
138 {
139  return GetTypeId();
140 }
141 
142 uint32_t
144 {
145  return 4 + 4 + 4 + 8;
146 }
147 
148 void
150 {
151  buf.WriteU32(m_flowId);
152  buf.WriteU32(m_packetId);
153  buf.WriteU32(m_packetSize);
154 
155  uint8_t tBuf[4];
156  m_src.Serialize(tBuf);
157  buf.Write(tBuf, 4);
158  m_dst.Serialize(tBuf);
159  buf.Write(tBuf, 4);
160 }
161 
162 void
164 {
165  m_flowId = buf.ReadU32();
166  m_packetId = buf.ReadU32();
167  m_packetSize = buf.ReadU32();
168 
169  uint8_t tBuf[4];
170  buf.Read(tBuf, 4);
172  buf.Read(tBuf, 4);
174 }
175 
176 void
177 Ipv4FlowProbeTag::Print(std::ostream& os) const
178 {
179  os << "FlowId=" << m_flowId;
180  os << " PacketId=" << m_packetId;
181  os << " PacketSize=" << m_packetSize;
182 }
183 
185  : Tag()
186 {
187 }
188 
190  uint32_t packetId,
191  uint32_t packetSize,
192  Ipv4Address src,
193  Ipv4Address dst)
194  : Tag(),
195  m_flowId(flowId),
196  m_packetId(packetId),
197  m_packetSize(packetSize),
198  m_src(src),
199  m_dst(dst)
200 {
201 }
202 
203 void
205 {
206  m_flowId = id;
207 }
208 
209 void
211 {
212  m_packetId = id;
213 }
214 
215 void
217 {
218  m_packetSize = size;
219 }
220 
221 uint32_t
223 {
224  return m_flowId;
225 }
226 
227 uint32_t
229 {
230  return m_packetId;
231 }
232 
233 uint32_t
235 {
236  return m_packetSize;
237 }
238 
239 bool
241 {
242  return ((m_src == src) && (m_dst == dst));
243 }
244 
246 // Ipv4FlowProbe class implementation //
248 
250  Ptr<Ipv4FlowClassifier> classifier,
251  Ptr<Node> node)
252  : FlowProbe(monitor),
253  m_classifier(classifier)
254 {
255  NS_LOG_FUNCTION(this << node->GetId());
256 
257  m_ipv4 = node->GetObject<Ipv4L3Protocol>();
258 
259  if (!m_ipv4->TraceConnectWithoutContext(
260  "SendOutgoing",
262  {
263  NS_FATAL_ERROR("trace fail");
264  }
265  if (!m_ipv4->TraceConnectWithoutContext(
266  "UnicastForward",
268  {
269  NS_FATAL_ERROR("trace fail");
270  }
271  if (!m_ipv4->TraceConnectWithoutContext(
272  "LocalDeliver",
274  {
275  NS_FATAL_ERROR("trace fail");
276  }
277 
278  if (!m_ipv4->TraceConnectWithoutContext(
279  "Drop",
281  {
282  NS_FATAL_ERROR("trace fail");
283  }
284 
285  std::ostringstream qd;
286  qd << "/NodeList/" << node->GetId() << "/$ns3::TrafficControlLayer/RootQueueDiscList/*/Drop";
288  qd.str(),
290 
291  // code copied from point-to-point-helper.cc
292  std::ostringstream oss;
293  oss << "/NodeList/" << node->GetId() << "/DeviceList/*/TxQueue/Drop";
295  oss.str(),
297 }
298 
300 {
301 }
302 
303 /* static */
304 TypeId
306 {
307  static TypeId tid =
308  TypeId("ns3::Ipv4FlowProbe").SetParent<FlowProbe>().SetGroupName("FlowMonitor")
309  // No AddConstructor because this class has no default constructor.
310  ;
311 
312  return tid;
313 }
314 
315 void
317 {
318  m_ipv4 = nullptr;
319  m_classifier = nullptr;
321 }
322 
323 void
325  Ptr<const Packet> ipPayload,
326  uint32_t interface)
327 {
328  FlowId flowId;
329  FlowPacketId packetId;
330 
331  if (!m_ipv4->IsUnicast(ipHeader.GetDestination()))
332  {
333  // we are not prepared to handle broadcast yet
334  return;
335  }
336 
337  Ipv4FlowProbeTag fTag;
338  bool found = ipPayload->FindFirstMatchingByteTag(fTag);
339  if (found)
340  {
341  return;
342  }
343 
344  if (m_classifier->Classify(ipHeader, ipPayload, &flowId, &packetId))
345  {
346  uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
347  NS_LOG_DEBUG("ReportFirstTx (" << this << ", " << flowId << ", " << packetId << ", " << size
348  << "); " << ipHeader << *ipPayload);
349  m_flowMonitor->ReportFirstTx(this, flowId, packetId, size);
350 
351  // tag the packet with the flow id and packet id, so that the packet can be identified even
352  // when Ipv4Header is not accessible at some non-IPv4 protocol layer
353  Ipv4FlowProbeTag fTag(flowId,
354  packetId,
355  size,
356  ipHeader.GetSource(),
357  ipHeader.GetDestination());
358  ipPayload->AddByteTag(fTag);
359  }
360 }
361 
362 void
364  Ptr<const Packet> ipPayload,
365  uint32_t interface)
366 {
367  Ipv4FlowProbeTag fTag;
368  bool found = ipPayload->FindFirstMatchingByteTag(fTag);
369 
370  if (found)
371  {
372  if (!ipHeader.IsLastFragment() || ipHeader.GetFragmentOffset() != 0)
373  {
374  NS_LOG_WARN("Not counting fragmented packets");
375  return;
376  }
377  if (!fTag.IsSrcDstValid(ipHeader.GetSource(), ipHeader.GetDestination()))
378  {
379  NS_LOG_LOGIC("Not reporting encapsulated packet");
380  return;
381  }
382 
383  FlowId flowId = fTag.GetFlowId();
384  FlowPacketId packetId = fTag.GetPacketId();
385 
386  uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
387  NS_LOG_DEBUG("ReportForwarding (" << this << ", " << flowId << ", " << packetId << ", "
388  << size << ");");
389  m_flowMonitor->ReportForwarding(this, flowId, packetId, size);
390  }
391 }
392 
393 void
395  Ptr<const Packet> ipPayload,
396  uint32_t interface)
397 {
398  Ipv4FlowProbeTag fTag;
399  bool found = ipPayload->FindFirstMatchingByteTag(fTag);
400 
401  if (found)
402  {
403  if (!fTag.IsSrcDstValid(ipHeader.GetSource(), ipHeader.GetDestination()))
404  {
405  NS_LOG_LOGIC("Not reporting encapsulated packet");
406  return;
407  }
408 
409  FlowId flowId = fTag.GetFlowId();
410  FlowPacketId packetId = fTag.GetPacketId();
411 
412  uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
413  NS_LOG_DEBUG("ReportLastRx (" << this << ", " << flowId << ", " << packetId << ", " << size
414  << "); " << ipHeader << *ipPayload);
415  m_flowMonitor->ReportLastRx(this, flowId, packetId, size);
416  }
417 }
418 
419 void
421  Ptr<const Packet> ipPayload,
423  Ptr<Ipv4> ipv4,
424  uint32_t ifIndex)
425 {
426 #if 0
427  switch (reason)
428  {
430  break;
431 
434  Ipv4Address addri = m_ipv4->GetAddress (ifIndex);
435  Ipv4Mask maski = m_ipv4->GetNetworkMask (ifIndex);
436  Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
437  if (ipHeader.GetDestination () == bcast) // we don't want broadcast packets
438  {
439  return;
440  }
441  }
442 #endif
443 
444  Ipv4FlowProbeTag fTag;
445  bool found = ipPayload->FindFirstMatchingByteTag(fTag);
446 
447  if (found)
448  {
449  FlowId flowId = fTag.GetFlowId();
450  FlowPacketId packetId = fTag.GetPacketId();
451 
452  uint32_t size = (ipPayload->GetSize() + ipHeader.GetSerializedSize());
453  NS_LOG_DEBUG("Drop (" << this << ", " << flowId << ", " << packetId << ", " << size << ", "
454  << reason << ", destIp=" << ipHeader.GetDestination() << "); "
455  << "HDR: " << ipHeader << " PKT: " << *ipPayload);
456 
457  DropReason myReason;
458 
459  switch (reason)
460  {
462  myReason = DROP_TTL_EXPIRE;
463  NS_LOG_DEBUG("DROP_TTL_EXPIRE");
464  break;
466  myReason = DROP_NO_ROUTE;
467  NS_LOG_DEBUG("DROP_NO_ROUTE");
468  break;
470  myReason = DROP_BAD_CHECKSUM;
471  NS_LOG_DEBUG("DROP_BAD_CHECKSUM");
472  break;
474  myReason = DROP_INTERFACE_DOWN;
475  NS_LOG_DEBUG("DROP_INTERFACE_DOWN");
476  break;
478  myReason = DROP_ROUTE_ERROR;
479  NS_LOG_DEBUG("DROP_ROUTE_ERROR");
480  break;
482  myReason = DROP_FRAGMENT_TIMEOUT;
483  NS_LOG_DEBUG("DROP_FRAGMENT_TIMEOUT");
484  break;
485 
486  default:
487  myReason = DROP_INVALID_REASON;
488  NS_FATAL_ERROR("Unexpected drop reason code " << reason);
489  }
490 
491  m_flowMonitor->ReportDrop(this, flowId, packetId, size, myReason);
492  }
493 }
494 
495 void
497 {
498  Ipv4FlowProbeTag fTag;
499  bool tagFound = ipPayload->FindFirstMatchingByteTag(fTag);
500 
501  if (!tagFound)
502  {
503  return;
504  }
505 
506  FlowId flowId = fTag.GetFlowId();
507  FlowPacketId packetId = fTag.GetPacketId();
508  uint32_t size = fTag.GetPacketSize();
509 
510  NS_LOG_DEBUG("Drop (" << this << ", " << flowId << ", " << packetId << ", " << size << ", "
511  << DROP_QUEUE << "); ");
512 
513  m_flowMonitor->ReportDrop(this, flowId, packetId, size, DROP_QUEUE);
514 }
515 
516 void
518 {
519  Ipv4FlowProbeTag fTag;
520  bool tagFound = item->GetPacket()->FindFirstMatchingByteTag(fTag);
521 
522  if (!tagFound)
523  {
524  return;
525  }
526 
527  FlowId flowId = fTag.GetFlowId();
528  FlowPacketId packetId = fTag.GetPacketId();
529  uint32_t size = fTag.GetPacketSize();
530 
531  NS_LOG_DEBUG("Drop (" << this << ", " << flowId << ", " << packetId << ", " << size << ", "
532  << DROP_QUEUE_DISC << "); ");
533 
534  m_flowMonitor->ReportDrop(this, flowId, packetId, size, DROP_QUEUE_DISC);
535 }
536 
537 } // namespace ns3
The FlowProbe class is responsible for listening for packet events in a specific point of the simulat...
Definition: flow-probe.h:40
void DoDispose() override
Destructor implementation.
Definition: flow-probe.cc:49
Ptr< FlowMonitor > m_flowMonitor
the FlowMonitor instance
Definition: flow-probe.h:108
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
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:258
uint32_t GetId() const
Definition: node.cc:117
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:962
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:934
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
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:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:961
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
uint32_t FlowId
Abstract identifier of a packet flow.
uint32_t FlowPacketId
Abstract identifier of a packet within a flow.
#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:707
static const uint32_t packetSize
Packet size generated at the AP.