A Discrete-Event Network Simulator
API
ipv4-flow-probe.cc
Go to the documentation of this file.
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 //
20 
21 #include "ns3/ipv4-flow-probe.h"
22 #include "ns3/ipv4-flow-classifier.h"
23 #include "ns3/node.h"
24 #include "ns3/packet.h"
25 #include "ns3/flow-monitor.h"
26 #include "ns3/log.h"
27 #include "ns3/pointer.h"
28 #include "ns3/config.h"
29 #include "ns3/flow-id-tag.h"
30 
31 namespace ns3 {
32 
33 NS_LOG_COMPONENT_DEFINE ("Ipv4FlowProbe");
34 
36 // Ipv4FlowProbeTag class implementation //
38 
48 class Ipv4FlowProbeTag : public Tag
49 {
50 public:
55  static TypeId GetTypeId (void);
56  virtual TypeId GetInstanceTypeId (void) const;
57  virtual uint32_t GetSerializedSize (void) const;
58  virtual void Serialize (TagBuffer buf) const;
59  virtual void Deserialize (TagBuffer buf);
60  virtual void Print (std::ostream &os) const;
70  Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize, Ipv4Address src, Ipv4Address dst);
75  void SetFlowId (uint32_t flowId);
80  void SetPacketId (uint32_t packetId);
85  void SetPacketSize (uint32_t packetSize);
90  uint32_t GetFlowId (void) const;
95  uint32_t GetPacketId (void) const;
100  uint32_t GetPacketSize (void) const;
111  bool IsSrcDstValid (Ipv4Address src, Ipv4Address dst) const;
112 private:
113  uint32_t m_flowId;
114  uint32_t m_packetId;
115  uint32_t m_packetSize;
118 };
119 
120 TypeId
122 {
123  static TypeId tid = TypeId ("ns3::Ipv4FlowProbeTag")
124  .SetParent<Tag> ()
125  .SetGroupName ("FlowMonitor")
126  .AddConstructor<Ipv4FlowProbeTag> ()
127  ;
128  return tid;
129 }
130 TypeId
132 {
133  return GetTypeId ();
134 }
135 uint32_t
137 {
138  return 4 + 4 + 4 + 8;
139 }
140 void
142 {
143  buf.WriteU32 (m_flowId);
144  buf.WriteU32 (m_packetId);
145  buf.WriteU32 (m_packetSize);
146 
147  uint8_t tBuf[4];
148  m_src.Serialize (tBuf);
149  buf.Write (tBuf, 4);
150  m_dst.Serialize (tBuf);
151  buf.Write (tBuf, 4);
152 }
153 void
155 {
156  m_flowId = buf.ReadU32 ();
157  m_packetId = buf.ReadU32 ();
158  m_packetSize = buf.ReadU32 ();
159 
160  uint8_t tBuf[4];
161  buf.Read (tBuf, 4);
163  buf.Read (tBuf, 4);
165 }
166 void
167 Ipv4FlowProbeTag::Print (std::ostream &os) const
168 {
169  os << "FlowId=" << m_flowId;
170  os << " PacketId=" << m_packetId;
171  os << " PacketSize=" << m_packetSize;
172 }
174  : Tag ()
175 {
176 }
177 
178 Ipv4FlowProbeTag::Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize, Ipv4Address src, Ipv4Address dst)
179  : Tag (), m_flowId (flowId), m_packetId (packetId), m_packetSize (packetSize), m_src (src), m_dst (dst)
180 {
181 }
182 
183 void
185 {
186  m_flowId = id;
187 }
188 void
190 {
191  m_packetId = id;
192 }
193 void
195 {
196  m_packetSize = size;
197 }
198 uint32_t
200 {
201  return m_flowId;
202 }
203 uint32_t
205 {
206  return m_packetId;
207 }
208 uint32_t
210 {
211  return m_packetSize;
212 }
213 bool
215 {
216  return ((m_src == src) && (m_dst == dst));
217 }
218 
220 // Ipv4FlowProbe class implementation //
222 
224  Ptr<Ipv4FlowClassifier> classifier,
225  Ptr<Node> node)
226  : FlowProbe (monitor),
227  m_classifier (classifier)
228 {
229  NS_LOG_FUNCTION (this << node->GetId ());
230 
231  m_ipv4 = node->GetObject<Ipv4L3Protocol> ();
232 
233  if (!m_ipv4->TraceConnectWithoutContext ("SendOutgoing",
235  {
236  NS_FATAL_ERROR ("trace fail");
237  }
238  if (!m_ipv4->TraceConnectWithoutContext ("UnicastForward",
240  {
241  NS_FATAL_ERROR ("trace fail");
242  }
243  if (!m_ipv4->TraceConnectWithoutContext ("LocalDeliver",
245  {
246  NS_FATAL_ERROR ("trace fail");
247  }
248 
249  if (!m_ipv4->TraceConnectWithoutContext ("Drop",
251  {
252  NS_FATAL_ERROR ("trace fail");
253  }
254 
255  std::ostringstream qd;
256  qd << "/NodeList/" << node->GetId () << "/$ns3::TrafficControlLayer/RootQueueDiscList/*/Drop";
258 
259  // code copied from point-to-point-helper.cc
260  std::ostringstream oss;
261  oss << "/NodeList/" << node->GetId () << "/DeviceList/*/TxQueue/Drop";
263 }
264 
266 {
267 }
268 
269 /* static */
270 TypeId
272 {
273  static TypeId tid = TypeId ("ns3::Ipv4FlowProbe")
274  .SetParent<FlowProbe> ()
275  .SetGroupName ("FlowMonitor")
276  // No AddConstructor because this class has no default constructor.
277  ;
278 
279  return tid;
280 }
281 
282 void
284 {
285  m_ipv4 = 0;
286  m_classifier = 0;
288 }
289 
290 void
291 Ipv4FlowProbe::SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
292 {
293  FlowId flowId;
294  FlowPacketId packetId;
295 
296  if (!m_ipv4->IsUnicast(ipHeader.GetDestination ()))
297  {
298  // we are not prepared to handle broadcast yet
299  return;
300  }
301 
302  Ipv4FlowProbeTag fTag;
303  bool found = ipPayload->FindFirstMatchingByteTag (fTag);
304  if (found)
305  {
306  return;
307  }
308 
309  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
310  {
311  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
312  NS_LOG_DEBUG ("ReportFirstTx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<"); "
313  << ipHeader << *ipPayload);
314  m_flowMonitor->ReportFirstTx (this, flowId, packetId, size);
315 
316  // tag the packet with the flow id and packet id, so that the packet can be identified even
317  // when Ipv4Header is not accessible at some non-IPv4 protocol layer
318  Ipv4FlowProbeTag fTag (flowId, packetId, size, ipHeader.GetSource (), ipHeader.GetDestination ());
319  ipPayload->AddByteTag (fTag);
320  }
321 }
322 
323 void
324 Ipv4FlowProbe::ForwardLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
325 {
326  Ipv4FlowProbeTag fTag;
327  bool found = ipPayload->FindFirstMatchingByteTag (fTag);
328 
329  if (found)
330  {
331  if (!ipHeader.IsLastFragment () || ipHeader.GetFragmentOffset () != 0)
332  {
333  NS_LOG_WARN ("Not counting fragmented packets");
334  return;
335  }
336  if (!fTag.IsSrcDstValid (ipHeader.GetSource (), ipHeader.GetDestination ()))
337  {
338  NS_LOG_LOGIC ("Not reporting encapsulated packet");
339  return;
340  }
341 
342  FlowId flowId = fTag.GetFlowId ();
343  FlowPacketId packetId = fTag.GetPacketId ();
344 
345  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
346  NS_LOG_DEBUG ("ReportForwarding ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
347  m_flowMonitor->ReportForwarding (this, flowId, packetId, size);
348  }
349 }
350 
351 void
352 Ipv4FlowProbe::ForwardUpLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
353 {
354  Ipv4FlowProbeTag fTag;
355  bool found = ipPayload->FindFirstMatchingByteTag (fTag);
356 
357  if (found)
358  {
359  if (!fTag.IsSrcDstValid (ipHeader.GetSource (), ipHeader.GetDestination ()))
360  {
361  NS_LOG_LOGIC ("Not reporting encapsulated packet");
362  return;
363  }
364 
365  FlowId flowId = fTag.GetFlowId ();
366  FlowPacketId packetId = fTag.GetPacketId ();
367 
368  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
369  NS_LOG_DEBUG ("ReportLastRx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<"); "
370  << ipHeader << *ipPayload);
371  m_flowMonitor->ReportLastRx (this, flowId, packetId, size);
372  }
373 }
374 
375 void
377  Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, uint32_t ifIndex)
378 {
379 #if 0
380  switch (reason)
381  {
383  break;
384 
387  Ipv4Address addri = m_ipv4->GetAddress (ifIndex);
388  Ipv4Mask maski = m_ipv4->GetNetworkMask (ifIndex);
389  Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
390  if (ipHeader.GetDestination () == bcast) // we don't want broadcast packets
391  {
392  return;
393  }
394  }
395 #endif
396 
397  Ipv4FlowProbeTag fTag;
398  bool found = ipPayload->FindFirstMatchingByteTag (fTag);
399 
400  if (found)
401  {
402  FlowId flowId = fTag.GetFlowId ();
403  FlowPacketId packetId = fTag.GetPacketId ();
404 
405  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
406  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << reason
407  << ", destIp=" << ipHeader.GetDestination () << "); "
408  << "HDR: " << ipHeader << " PKT: " << *ipPayload);
409 
410  DropReason myReason;
411 
412 
413  switch (reason)
414  {
416  myReason = DROP_TTL_EXPIRE;
417  NS_LOG_DEBUG ("DROP_TTL_EXPIRE");
418  break;
420  myReason = DROP_NO_ROUTE;
421  NS_LOG_DEBUG ("DROP_NO_ROUTE");
422  break;
424  myReason = DROP_BAD_CHECKSUM;
425  NS_LOG_DEBUG ("DROP_BAD_CHECKSUM");
426  break;
428  myReason = DROP_INTERFACE_DOWN;
429  NS_LOG_DEBUG ("DROP_INTERFACE_DOWN");
430  break;
432  myReason = DROP_ROUTE_ERROR;
433  NS_LOG_DEBUG ("DROP_ROUTE_ERROR");
434  break;
436  myReason = DROP_FRAGMENT_TIMEOUT;
437  NS_LOG_DEBUG ("DROP_FRAGMENT_TIMEOUT");
438  break;
439 
440  default:
441  myReason = DROP_INVALID_REASON;
442  NS_FATAL_ERROR ("Unexpected drop reason code " << reason);
443  }
444 
445  m_flowMonitor->ReportDrop (this, flowId, packetId, size, myReason);
446  }
447 }
448 
449 void
451 {
452  Ipv4FlowProbeTag fTag;
453  bool tagFound = ipPayload->FindFirstMatchingByteTag (fTag);
454 
455  if (!tagFound)
456  {
457  return;
458  }
459 
460  FlowId flowId = fTag.GetFlowId ();
461  FlowPacketId packetId = fTag.GetPacketId ();
462  uint32_t size = fTag.GetPacketSize ();
463 
464  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << DROP_QUEUE
465  << "); ");
466 
467  m_flowMonitor->ReportDrop (this, flowId, packetId, size, DROP_QUEUE);
468 }
469 
470 void
472 {
473  Ipv4FlowProbeTag fTag;
474  bool tagFound = item->GetPacket ()->FindFirstMatchingByteTag (fTag);
475 
476  if (!tagFound)
477  {
478  return;
479  }
480 
481  FlowId flowId = fTag.GetFlowId ();
482  FlowPacketId packetId = fTag.GetPacketId ();
483  uint32_t size = fTag.GetPacketSize ();
484 
485  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << DROP_QUEUE_DISC
486  << "); ");
487 
488  m_flowMonitor->ReportDrop (this, flowId, packetId, size, DROP_QUEUE_DISC);
489 }
490 
491 } // namespace ns3
492 
493 
uint32_t FlowPacketId
Abstract identifier of a packet within a flow.
Tag used to allow a fast identification of the packet.
static Ipv4Address Deserialize(const uint8_t buf[4])
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:797
void ForwardUpLogger(const Ipv4Header &ipHeader, Ptr< const Packet > ipPayload, uint32_t interface)
Log a packet being received by the destination.
void Write(const uint8_t *buffer, uint32_t size)
Definition: tag-buffer.cc:125
Interface is down so can not send packet.
uint32_t m_flowId
flow identifier
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
virtual void DoDispose(void)
Destructor implementation.
void SetPacketSize(uint32_t packetSize)
Set the packet size.
DropReason
enumeration of possible reasons why a packet may be dropped
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:459
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:258
Packet dropped due to TTL decremented to zero during IPv4 forwarding.
Ipv4FlowProbe(Ptr< FlowMonitor > monitor, Ptr< Ipv4FlowClassifier > classifier, Ptr< Node > node)
Constructor.
Ipv4Address m_src
IP source.
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:796
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
TAG_BUFFER_INLINE uint32_t ReadU32(void)
Definition: tag-buffer.h:215
void SendOutgoingLogger(const Ipv4Header &ipHeader, Ptr< const Packet > ipPayload, uint32_t interface)
Log a packet being sent.
Ipv4Address m_dst
IP destination.
Ptr< FlowMonitor > m_flowMonitor
the FlowMonitor instance
Definition: flow-probe.h:106
Ipv4Address GetSubnetDirectedBroadcast(Ipv4Mask const &mask) const
Generate subnet-directed broadcast address corresponding to mask.
virtual uint32_t GetSerializedSize(void) const
void ForwardLogger(const Ipv4Header &ipHeader, Ptr< const Packet > ipPayload, uint32_t interface)
Log a packet being forwarded.
Packet header for IPv4.
Definition: ipv4-header.h:33
void SetFlowId(uint32_t flowId)
Set the flow identifier.
uint32_t m_packetSize
packet size
virtual void Serialize(TagBuffer buf) const
void QueueDropLogger(Ptr< const Packet > ipPayload)
Log a packet being dropped by a queue.
Packet dropped due to queue overflow.
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition: tag-buffer.h:186
void QueueDiscDropLogger(Ptr< const QueueDiscItem > item)
Log a packet being dropped by a queue disc.
void SetPacketId(uint32_t packetId)
Set the packet identifier.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:832
void Serialize(uint8_t buf[4]) const
Serialize this address to a 4-byte buffer.
uint32_t GetPacketId(void) const
Set the packet identifier.
Packet dropped due to invalid checksum in the IPv4 header.
tag a set of bytes in a packet
Definition: tag.h:36
uint32_t m_packetId
packet identifier
Implement the IPv4 layer.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
virtual void Print(std::ostream &os) const
bool IsSrcDstValid(Ipv4Address src, Ipv4Address dst) const
Checks if the addresses stored in tag are matching the arguments.
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
Ptr< Ipv4FlowClassifier > m_classifier
the Ipv4FlowClassifier this probe is associated with
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
virtual void Deserialize(TagBuffer buf)
uint32_t GetFlowId(void) const
Set the flow identifier.
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
The FlowProbe class is responsible for listening for packet events in a specific point of the simulat...
Definition: flow-probe.h:39
uint32_t GetPacketSize(void) const
Get the packet size.
Fallback reason (no known reason)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
read and write tag data
Definition: tag-buffer.h:51
uint32_t GetId(void) const
Definition: node.cc:107
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
Packet dropped due to missing route to the destination.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:269
DropReason
Reason why a packet has been dropped.
void Read(uint8_t *buffer, uint32_t size)
Definition: tag-buffer.cc:176
static TypeId GetTypeId(void)
Register this type.
static const uint32_t packetSize
Packet dropped by the queue disc.
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:375
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:914
Interface is down so can not send packet.
Ptr< Ipv4L3Protocol > m_ipv4
the Ipv4L3Protocol this probe is bound to
virtual void DoDispose(void)
Destructor implementation.
Definition: flow-probe.cc:50
static TypeId GetTypeId(void)
Get the type ID.
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:781
uint32_t FlowId
Abstract identifier of a packet flow.
void DropLogger(const Ipv4Header &ipHeader, Ptr< const Packet > ipPayload, Ipv4L3Protocol::DropReason reason, Ptr< Ipv4 > ipv4, uint32_t ifIndex)
Log a packet being dropped.