A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 using namespace std;
34 
35 NS_LOG_COMPONENT_DEFINE ("Ipv4FlowProbe");
36 
38 // Ipv4FlowProbeTag class implementation //
40 
41 class Ipv4FlowProbeTag : public Tag
42 {
43 public:
44  static TypeId GetTypeId (void);
45  virtual TypeId GetInstanceTypeId (void) const;
46  virtual uint32_t GetSerializedSize (void) const;
47  virtual void Serialize (TagBuffer buf) const;
48  virtual void Deserialize (TagBuffer buf);
49  virtual void Print (std::ostream &os) const;
51  Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize);
52  void SetFlowId (uint32_t flowId);
53  void SetPacketId (uint32_t packetId);
54  void SetPacketSize (uint32_t packetSize);
55  uint32_t GetFlowId (void) const;
56  uint32_t GetPacketId (void) const;
57  uint32_t GetPacketSize (void) const;
58 private:
59  uint32_t m_flowId;
60  uint32_t m_packetId;
61  uint32_t m_packetSize;
62 
63 };
64 
65 TypeId
67 {
68  static TypeId tid = TypeId ("ns3::Ipv4FlowProbeTag")
69  .SetParent<Tag> ()
70  .AddConstructor<Ipv4FlowProbeTag> ()
71  ;
72  return tid;
73 }
74 TypeId
76 {
77  return GetTypeId ();
78 }
79 uint32_t
81 {
82  return 4 + 4 + 4;
83 }
84 void
86 {
87  buf.WriteU32 (m_flowId);
88  buf.WriteU32 (m_packetId);
89  buf.WriteU32 (m_packetSize);
90 }
91 void
93 {
94  m_flowId = buf.ReadU32 ();
95  m_packetId = buf.ReadU32 ();
96  m_packetSize = buf.ReadU32 ();
97 }
98 void
99 Ipv4FlowProbeTag::Print (std::ostream &os) const
100 {
101  os << "FlowId=" << m_flowId;
102  os << "PacketId=" << m_packetId;
103  os << "PacketSize=" << m_packetSize;
104 }
106  : Tag ()
107 {
108 }
109 
110 Ipv4FlowProbeTag::Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize)
111  : Tag (), m_flowId (flowId), m_packetId (packetId), m_packetSize (packetSize)
112 {
113 }
114 
115 void
117 {
118  m_flowId = id;
119 }
120 void
122 {
123  m_packetId = id;
124 }
125 void
127 {
128  m_packetSize = size;
129 }
130 uint32_t
132 {
133  return m_flowId;
134 }
135 uint32_t
137 {
138  return m_packetId;
139 }
140 uint32_t
142 {
143  return m_packetSize;
144 }
145 
147 // Ipv4FlowProbe class implementation //
149 
151  Ptr<Ipv4FlowClassifier> classifier,
152  Ptr<Node> node)
153  : FlowProbe (monitor),
154  m_classifier (classifier)
155 {
156  NS_LOG_FUNCTION (this << node->GetId ());
157 
159 
160  if (!ipv4->TraceConnectWithoutContext ("SendOutgoing",
162  {
163  NS_FATAL_ERROR ("trace fail");
164  }
165  if (!ipv4->TraceConnectWithoutContext ("UnicastForward",
167  {
168  NS_FATAL_ERROR ("trace fail");
169  }
170  if (!ipv4->TraceConnectWithoutContext ("LocalDeliver",
172  {
173  NS_FATAL_ERROR ("trace fail");
174  }
175 
176  if (!ipv4->TraceConnectWithoutContext ("Drop",
178  {
179  NS_FATAL_ERROR ("trace fail");
180  }
181 
182  // code copied from point-to-point-helper.cc
183  std::ostringstream oss;
184  oss << "/NodeList/" << node->GetId () << "/DeviceList/*/TxQueue/Drop";
186 }
187 
189 {
190 }
191 
192 void
193 Ipv4FlowProbe::SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
194 {
195  FlowId flowId;
196  FlowPacketId packetId;
197 
198  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
199  {
200  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
201  NS_LOG_DEBUG ("ReportFirstTx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<"); "
202  << ipHeader << *ipPayload);
203  m_flowMonitor->ReportFirstTx (this, flowId, packetId, size);
204 
205  // tag the packet with the flow id and packet id, so that the packet can be identified even
206  // when Ipv4Header is not accessible at some non-IPv4 protocol layer
207  Ipv4FlowProbeTag fTag (flowId, packetId, size);
208  ipPayload->AddPacketTag (fTag);
209  }
210 }
211 
212 void
213 Ipv4FlowProbe::ForwardLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
214 {
215  FlowId flowId;
216  FlowPacketId packetId;
217 
218  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
219  {
220  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
221  NS_LOG_DEBUG ("ReportForwarding ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
222  m_flowMonitor->ReportForwarding (this, flowId, packetId, size);
223  }
224 
225 }
226 
227 void
228 Ipv4FlowProbe::ForwardUpLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
229 {
230  FlowId flowId;
231  FlowPacketId packetId;
232 
233  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
234  {
235  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
236  Ipv4FlowProbeTag fTag;
237 
238  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
239  ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
240 
241  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
242  NS_LOG_DEBUG ("ReportLastRx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
243  m_flowMonitor->ReportLastRx (this, flowId, packetId, size);
244  }
245 }
246 
247 void
249  Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, uint32_t ifIndex)
250 {
251 #if 0
252  switch (reason)
253  {
255  break;
256 
259  Ipv4Address addri = m_ipv4->GetAddress (ifIndex);
260  Ipv4Mask maski = m_ipv4->GetNetworkMask (ifIndex);
261  Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
262  if (ipHeader.GetDestination () == bcast) // we don't want broadcast packets
263  {
264  return;
265  }
266  }
267 #endif
268 
269  FlowId flowId;
270  FlowPacketId packetId;
271 
272  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
273  {
274  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
275  Ipv4FlowProbeTag fTag;
276 
277  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
278  ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
279 
280  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
281  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << reason
282  << ", destIp=" << ipHeader.GetDestination () << "); "
283  << "HDR: " << ipHeader << " PKT: " << *ipPayload);
284 
285  DropReason myReason;
286 
287 
288  switch (reason)
289  {
291  myReason = DROP_TTL_EXPIRE;
292  NS_LOG_DEBUG ("DROP_TTL_EXPIRE");
293  break;
295  myReason = DROP_NO_ROUTE;
296  NS_LOG_DEBUG ("DROP_NO_ROUTE");
297  break;
299  myReason = DROP_BAD_CHECKSUM;
300  NS_LOG_DEBUG ("DROP_BAD_CHECKSUM");
301  break;
303  myReason = DROP_INTERFACE_DOWN;
304  NS_LOG_DEBUG ("DROP_INTERFACE_DOWN");
305  break;
307  myReason = DROP_ROUTE_ERROR;
308  NS_LOG_DEBUG ("DROP_ROUTE_ERROR");
309  break;
311  myReason = DROP_FRAGMENT_TIMEOUT;
312  NS_LOG_DEBUG ("DROP_FRAGMENT_TIMEOUT");
313  break;
314 
315  default:
316  myReason = DROP_INVALID_REASON;
317  NS_FATAL_ERROR ("Unexpected drop reason code " << reason);
318  }
319 
320  m_flowMonitor->ReportDrop (this, flowId, packetId, size, myReason);
321  }
322 }
323 
324 void
326 {
327  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
328  Ipv4FlowProbeTag fTag;
329 
330  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
331  bool tagFound;
332  tagFound = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
333  if (!tagFound)
334  {
335  return;
336  }
337 
338  FlowId flowId = fTag.GetFlowId ();
339  FlowPacketId packetId = fTag.GetPacketId ();
340  uint32_t size = fTag.GetPacketSize ();
341 
342  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << DROP_QUEUE
343  << "); ");
344 
345  m_flowMonitor->ReportDrop (this, flowId, packetId, size, DROP_QUEUE);
346 }
347 
348 } // namespace ns3
349 
350