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 "ipv4-flow-probe.h"
21 
22 #include "flow-monitor.h"
23 #include "ipv4-flow-classifier.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 
32 namespace ns3
33 {
34 
35 NS_LOG_COMPONENT_DEFINE("Ipv4FlowProbe");
36 
38 // Ipv4FlowProbeTag class implementation //
40 
50 class Ipv4FlowProbeTag : public Tag
51 {
52  public:
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;
72  Ipv4FlowProbeTag(uint32_t flowId,
73  uint32_t packetId,
74  uint32_t packetSize,
75  Ipv4Address src,
76  Ipv4Address dst);
81  void SetFlowId(uint32_t flowId);
86  void SetPacketId(uint32_t packetId);
91  void SetPacketSize(uint32_t packetSize);
96  uint32_t GetFlowId() const;
101  uint32_t GetPacketId() const;
106  uint32_t GetPacketSize() const;
117  bool IsSrcDstValid(Ipv4Address src, Ipv4Address dst) const;
118 
119  private:
120  uint32_t m_flowId;
121  uint32_t m_packetId;
122  uint32_t m_packetSize;
125 };
126 
127 TypeId
129 {
130  static TypeId tid = TypeId("ns3::Ipv4FlowProbeTag")
131  .SetParent<Tag>()
132  .SetGroupName("FlowMonitor")
133  .AddConstructor<Ipv4FlowProbeTag>();
134  return tid;
135 }
136 
137 TypeId
139 {
140  return GetTypeId();
141 }
142 
143 uint32_t
145 {
146  return 4 + 4 + 4 + 8;
147 }
148 
149 void
151 {
152  buf.WriteU32(m_flowId);
153  buf.WriteU32(m_packetId);
154  buf.WriteU32(m_packetSize);
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 
163 void
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 
177 void
178 Ipv4FlowProbeTag::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,
192  uint32_t packetSize,
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 
204 void
206 {
207  m_flowId = id;
208 }
209 
210 void
212 {
213  m_packetId = id;
214 }
215 
216 void
218 {
219  m_packetSize = size;
220 }
221 
222 uint32_t
224 {
225  return m_flowId;
226 }
227 
228 uint32_t
230 {
231  return m_packetId;
232 }
233 
234 uint32_t
236 {
237  return m_packetSize;
238 }
239 
240 bool
242 {
243  return ((m_src == src) && (m_dst == dst));
244 }
245 
247 // Ipv4FlowProbe class implementation //
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 */
305 TypeId
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 
316 void
318 {
319  m_ipv4 = nullptr;
320  m_classifier = nullptr;
322 }
323 
324 void
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 
363 void
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 
394 void
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 
420 void
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 
496 void
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 
517 void
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
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:861
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:943
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:915
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:931
bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:960
#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:704
static const uint32_t packetSize
Packet size generated at the AP.