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 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
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 }
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
115 {
116  m_flowId = id;
117 }
118 void
120 {
121  m_packetId = id;
122 }
123 void
125 {
126  m_packetSize = size;
127 }
128 uint32_t
130 {
131  return m_flowId;
132 }
133 uint32_t
135 {
136  return m_packetId;
137 }
138 uint32_t
140 {
141  return m_packetSize;
142 }
143 
145 // Ipv4FlowProbe class implementation //
147 
149  Ptr<Ipv4FlowClassifier> classifier,
150  Ptr<Node> node)
151  : FlowProbe (monitor),
152  m_classifier (classifier)
153 {
154  NS_LOG_FUNCTION (this << node->GetId ());
155 
157 
158  if (!ipv4->TraceConnectWithoutContext ("SendOutgoing",
160  {
161  NS_FATAL_ERROR ("trace fail");
162  }
163  if (!ipv4->TraceConnectWithoutContext ("UnicastForward",
165  {
166  NS_FATAL_ERROR ("trace fail");
167  }
168  if (!ipv4->TraceConnectWithoutContext ("LocalDeliver",
170  {
171  NS_FATAL_ERROR ("trace fail");
172  }
173 
174  if (!ipv4->TraceConnectWithoutContext ("Drop",
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";
184 }
185 
187 {
188 }
189 
190 void
191 Ipv4FlowProbe::SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
192 {
193  FlowId flowId;
194  FlowPacketId packetId;
195 
196  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
197  {
198  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
199  NS_LOG_DEBUG ("ReportFirstTx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<"); "
200  << ipHeader << *ipPayload);
201  m_flowMonitor->ReportFirstTx (this, flowId, packetId, size);
202 
203  // tag the packet with the flow id and packet id, so that the packet can be identified even
204  // when Ipv4Header is not accessible at some non-IPv4 protocol layer
205  Ipv4FlowProbeTag fTag (flowId, packetId, size);
206  ipPayload->AddPacketTag (fTag);
207  }
208 }
209 
210 void
211 Ipv4FlowProbe::ForwardLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
212 {
213  FlowId flowId;
214  FlowPacketId packetId;
215 
216  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
217  {
218  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
219  NS_LOG_DEBUG ("ReportForwarding ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
220  m_flowMonitor->ReportForwarding (this, flowId, packetId, size);
221  }
222 
223 }
224 
225 void
226 Ipv4FlowProbe::ForwardUpLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
227 {
228  FlowId flowId;
229  FlowPacketId packetId;
230 
231  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
232  {
233  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
234  Ipv4FlowProbeTag fTag;
235 
236  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
237  ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
238 
239  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
240  NS_LOG_DEBUG ("ReportLastRx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
241  m_flowMonitor->ReportLastRx (this, flowId, packetId, size);
242  }
243 }
244 
245 void
247  Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, uint32_t ifIndex)
248 {
249 #if 0
250  switch (reason)
251  {
253  break;
254 
257  Ipv4Address addri = m_ipv4->GetAddress (ifIndex);
258  Ipv4Mask maski = m_ipv4->GetNetworkMask (ifIndex);
259  Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
260  if (ipHeader.GetDestination () == bcast) // we don't want broadcast packets
261  {
262  return;
263  }
264  }
265 #endif
266 
267  FlowId flowId;
268  FlowPacketId packetId;
269 
270  if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
271  {
272  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
273  Ipv4FlowProbeTag fTag;
274 
275  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
276  ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
277 
278  uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
279  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << reason
280  << ", destIp=" << ipHeader.GetDestination () << "); "
281  << "HDR: " << ipHeader << " PKT: " << *ipPayload);
282 
283  DropReason myReason;
284 
285 
286  switch (reason)
287  {
289  myReason = DROP_TTL_EXPIRE;
290  NS_LOG_DEBUG ("DROP_TTL_EXPIRE");
291  break;
293  myReason = DROP_NO_ROUTE;
294  NS_LOG_DEBUG ("DROP_NO_ROUTE");
295  break;
297  myReason = DROP_BAD_CHECKSUM;
298  NS_LOG_DEBUG ("DROP_BAD_CHECKSUM");
299  break;
301  myReason = DROP_INTERFACE_DOWN;
302  NS_LOG_DEBUG ("DROP_INTERFACE_DOWN");
303  break;
305  myReason = DROP_ROUTE_ERROR;
306  NS_LOG_DEBUG ("DROP_ROUTE_ERROR");
307  break;
309  myReason = DROP_FRAGMENT_TIMEOUT;
310  NS_LOG_DEBUG ("DROP_FRAGMENT_TIMEOUT");
311  break;
312 
313  default:
314  myReason = DROP_INVALID_REASON;
315  NS_FATAL_ERROR ("Unexpected drop reason code " << reason);
316  }
317 
318  m_flowMonitor->ReportDrop (this, flowId, packetId, size, myReason);
319  }
320 }
321 
322 void
324 {
325  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
326  Ipv4FlowProbeTag fTag;
327 
328  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
329  bool tagFound;
330  tagFound = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
331  if (!tagFound)
332  {
333  return;
334  }
335 
336  FlowId flowId = fTag.GetFlowId ();
337  FlowPacketId packetId = fTag.GetPacketId ();
338  uint32_t size = fTag.GetPacketSize ();
339 
340  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << DROP_QUEUE
341  << "); ");
342 
343  m_flowMonitor->ReportDrop (this, flowId, packetId, size, DROP_QUEUE);
344 }
345 
346 } // namespace ns3
347 
348