A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv4-flow-probe.cc
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 
39 class Ipv4FlowProbeTag : public Tag
40 {
41 public:
42  static TypeId GetTypeId (void);
43  virtual TypeId GetInstanceTypeId (void) const;
44  virtual uint32_t GetSerializedSize (void) const;
45  virtual void Serialize (TagBuffer buf) const;
46  virtual void Deserialize (TagBuffer buf);
47  virtual void Print (std::ostream &os) const;
49  Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize);
50  void SetFlowId (uint32_t flowId);
51  void SetPacketId (uint32_t packetId);
52  void SetPacketSize (uint32_t packetSize);
53  uint32_t GetFlowId (void) const;
54  uint32_t GetPacketId (void) const;
55  uint32_t GetPacketSize (void) const;
56 private:
57  uint32_t m_flowId;
58  uint32_t m_packetId;
59  uint32_t m_packetSize;
60 
61 };
62 
63 TypeId
64 Ipv4FlowProbeTag::GetTypeId (void)
65 {
66  static TypeId tid = TypeId ("ns3::Ipv4FlowProbeTag")
67  .SetParent<Tag> ()
68  .AddConstructor<Ipv4FlowProbeTag> ()
69  ;
70  return tid;
71 }
72 TypeId
74 {
75  return GetTypeId ();
76 }
77 uint32_t
79 {
80  return 4 + 4 + 4;
81 }
82 void
84 {
85  buf.WriteU32 (m_flowId);
86  buf.WriteU32 (m_packetId);
87  buf.WriteU32 (m_packetSize);
88 }
89 void
91 {
92  m_flowId = buf.ReadU32 ();
93  m_packetId = buf.ReadU32 ();
94  m_packetSize = buf.ReadU32 ();
95 }
96 void
97 Ipv4FlowProbeTag::Print (std::ostream &os) const
98 {
99  os << "FlowId=" << m_flowId;
100  os << "PacketId=" << m_packetId;
101  os << "PacketSize=" << m_packetSize;
102 }
103 Ipv4FlowProbeTag::Ipv4FlowProbeTag ()
104  : Tag ()
105 {
106 }
107 
108 Ipv4FlowProbeTag::Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize)
109  : Tag (), m_flowId (flowId), m_packetId (packetId), m_packetSize (packetSize)
110 {
111 }
112 
113 void
114 Ipv4FlowProbeTag::SetFlowId (uint32_t id)
115 {
116  m_flowId = id;
117 }
118 void
119 Ipv4FlowProbeTag::SetPacketId (uint32_t id)
120 {
121  m_packetId = id;
122 }
123 void
124 Ipv4FlowProbeTag::SetPacketSize (uint32_t size)
125 {
126  m_packetSize = size;
127 }
128 uint32_t
129 Ipv4FlowProbeTag::GetFlowId (void) const
130 {
131  return m_flowId;
132 }
133 uint32_t
134 Ipv4FlowProbeTag::GetPacketId (void) const
135 {
136  return m_packetId;
137 }
138 uint32_t
139 Ipv4FlowProbeTag::GetPacketSize (void) const
140 {
141  return m_packetSize;
142 }
143 
145 // Ipv4FlowProbe class implementation //
147 
148 Ipv4FlowProbe::Ipv4FlowProbe (Ptr<FlowMonitor> monitor,
149  Ptr<Ipv4FlowClassifier> classifier,
150  Ptr<Node> node)
151  : FlowProbe (monitor),
152  m_classifier (classifier)
153 {
154  NS_LOG_FUNCTION (this << node->GetId ());
155 
156  Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol> ();
157 
158  if (!ipv4->TraceConnectWithoutContext ("SendOutgoing",
159  MakeCallback (&Ipv4FlowProbe::SendOutgoingLogger, Ptr<Ipv4FlowProbe> (this))))
160  {
161  NS_FATAL_ERROR ("trace fail");
162  }
163  if (!ipv4->TraceConnectWithoutContext ("UnicastForward",
164  MakeCallback (&Ipv4FlowProbe::ForwardLogger, Ptr<Ipv4FlowProbe> (this))))
165  {
166  NS_FATAL_ERROR ("trace fail");
167  }
168  if (!ipv4->TraceConnectWithoutContext ("LocalDeliver",
169  MakeCallback (&Ipv4FlowProbe::ForwardUpLogger, Ptr<Ipv4FlowProbe> (this))))
170  {
171  NS_FATAL_ERROR ("trace fail");
172  }
173 
174  if (!ipv4->TraceConnectWithoutContext ("Drop",
175  MakeCallback (&Ipv4FlowProbe::DropLogger, Ptr<Ipv4FlowProbe> (this))))
176  {
177  NS_FATAL_ERROR ("trace fail");
178  }
179 
180  // code copied from point-to-point-helper.cc
181  std::ostringstream oss;
182  oss << "/NodeList/" << node->GetId () << "/DeviceList/*/TxQueue/Drop";
183  Config::ConnectWithoutContext (oss.str (), MakeCallback (&Ipv4FlowProbe::QueueDropLogger, Ptr<Ipv4FlowProbe> (this)));
184 }
185 
186 Ipv4FlowProbe::~Ipv4FlowProbe ()
187 {
188 }
189 
190 void
192 {
194 }
195 
196 void
197 Ipv4FlowProbe::SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
198 {
199  FlowId flowId;
200  FlowPacketId packetId;
201 
202  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
203  {
204  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
205  NS_LOG_DEBUG ("ReportFirstTx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<"); "
206  << ipHeader << *ipPayload);
207  m_flowMonitor->ReportFirstTx (this, flowId, packetId, size);
208 
209  // tag the packet with the flow id and packet id, so that the packet can be identified even
210  // when Ipv4Header is not accessible at some non-IPv4 protocol layer
211  Ipv4FlowProbeTag fTag (flowId, packetId, size);
212  ipPayload->AddPacketTag (fTag);
213  }
214 }
215 
216 void
217 Ipv4FlowProbe::ForwardLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
218 {
219  FlowId flowId;
220  FlowPacketId packetId;
221 
222  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
223  {
224  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
225  NS_LOG_DEBUG ("ReportForwarding ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
226  m_flowMonitor->ReportForwarding (this, flowId, packetId, size);
227  }
228 
229 }
230 
231 void
232 Ipv4FlowProbe::ForwardUpLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
233 {
234  FlowId flowId;
235  FlowPacketId packetId;
236 
237  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
238  {
239  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
240  Ipv4FlowProbeTag fTag;
241 
242  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
243  ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
244 
245  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
246  NS_LOG_DEBUG ("ReportLastRx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
247  m_flowMonitor->ReportLastRx (this, flowId, packetId, size);
248  }
249 }
250 
251 void
252 Ipv4FlowProbe::DropLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload,
253  Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, uint32_t ifIndex)
254 {
255 #if 0
256  switch (reason)
257  {
259  break;
260 
263  Ipv4Address addri = m_ipv4->GetAddress (ifIndex);
264  Ipv4Mask maski = m_ipv4->GetNetworkMask (ifIndex);
265  Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
266  if (ipHeader.GetDestination () == bcast) // we don't want broadcast packets
267  {
268  return;
269  }
270  }
271 #endif
272 
273  FlowId flowId;
274  FlowPacketId packetId;
275 
276  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
277  {
278  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
279  Ipv4FlowProbeTag fTag;
280 
281  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
282  ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
283 
284  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
285  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << reason
286  << ", destIp=" << ipHeader.GetDestination () << "); "
287  << "HDR: " << ipHeader << " PKT: " << *ipPayload);
288 
289  DropReason myReason;
290 
291 
292  switch (reason)
293  {
295  myReason = DROP_TTL_EXPIRE;
296  NS_LOG_DEBUG ("DROP_TTL_EXPIRE");
297  break;
299  myReason = DROP_NO_ROUTE;
300  NS_LOG_DEBUG ("DROP_NO_ROUTE");
301  break;
303  myReason = DROP_BAD_CHECKSUM;
304  NS_LOG_DEBUG ("DROP_BAD_CHECKSUM");
305  break;
307  myReason = DROP_INTERFACE_DOWN;
308  NS_LOG_DEBUG ("DROP_INTERFACE_DOWN");
309  break;
311  myReason = DROP_ROUTE_ERROR;
312  NS_LOG_DEBUG ("DROP_ROUTE_ERROR");
313  break;
315  myReason = DROP_FRAGMENT_TIMEOUT;
316  NS_LOG_DEBUG ("DROP_FRAGMENT_TIMEOUT");
317  break;
318 
319  default:
320  myReason = DROP_INVALID_REASON;
321  NS_FATAL_ERROR ("Unexpected drop reason code " << reason);
322  }
323 
324  m_flowMonitor->ReportDrop (this, flowId, packetId, size, myReason);
325  }
326 }
327 
328 void
329 Ipv4FlowProbe::QueueDropLogger (Ptr<const Packet> ipPayload)
330 {
331  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
332  Ipv4FlowProbeTag fTag;
333 
334  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
335  bool tagFound;
336  tagFound = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
337  if (!tagFound)
338  {
339  return;
340  }
341 
342  FlowId flowId = fTag.GetFlowId ();
343  FlowPacketId packetId = fTag.GetPacketId ();
344  uint32_t size = fTag.GetPacketSize ();
345 
346  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << DROP_QUEUE
347  << "); ");
348 
349  m_flowMonitor->ReportDrop (this, flowId, packetId, size, DROP_QUEUE);
350 }
351 
352 } // namespace ns3
353 
354 
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual void DoDispose(void)
void AddPacketTag(const Tag &tag) const
Definition: packet.cc:868
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
TAG_BUFFER_INLINE uint32_t ReadU32(void)
Definition: tag-buffer.h:199
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
virtual uint32_t GetSerializedSize(void) const
DropReason
Reason why a packet has been dropped.
Packet header for IPv4.
Definition: ipv4-header.h:31
virtual void Serialize(TagBuffer buf) const
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition: tag-buffer.h:170
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
Packet dropped due to invalid checksum in the IPv4 header.
tag a set of bytes in a packet
Definition: tag.h:36
virtual void Print(std::ostream &os) const
virtual TypeId GetInstanceTypeId(void) const
virtual void Deserialize(TagBuffer buf)
Packet dropped due to TTL decremented to zero during IPv4 forwarding.
read and write tag data
Definition: tag-buffer.h:51
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
Packet dropped due to missing route to the destination.
DropReason
enumeration of possible reasons why a packet may be dropped
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:373
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:717
virtual void DoDispose(void)
Definition: flow-probe.cc:39