OLD | NEW |
(Empty) | |
| 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| 2 /* |
| 3 * Copyright (c) 2008 INRIA |
| 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> |
| 19 * Author: Faker Moatamri <faker.moatamri@sophia.inria.fr> |
| 20 * Author: Lalith Suresh <suresh.lalith@gmail.com> |
| 21 */ |
| 22 |
| 23 /** |
| 24 * \ingroup clickInternetStack |
| 25 * \defgroup clickInternetStackModel Internet Stack Model |
| 26 * |
| 27 * \section clickInternetStackTracingModel Tracing in the Internet Stack |
| 28 * |
| 29 * The internet stack provides a number of trace sources in its various |
| 30 * protocol implementations. These trace sources can be hooked using your own· |
| 31 * custom trace code, or you can use our helper functions in some cases to· |
| 32 * arrange for tracing to be enabled. |
| 33 * |
| 34 * \subsection clickInternetStackArpTracingModel Tracing in ARP |
| 35 * |
| 36 * ARP provides two trace hooks, one in the cache, and one in the layer three |
| 37 * protocol. The trace accessor in the cache is given the name "Drop." When |
| 38 * a packet is transmitted over an interface that requires ARP, it is first |
| 39 * queued for transmission in the ARP cache until the required MAC address is |
| 40 * resolved. There are a number of retries that may be done trying to get the· |
| 41 * address, and if the maximum retry count is exceeded the packet in question· |
| 42 * is dropped by ARP. The single trace hook in the ARP cache is called, |
| 43 * |
| 44 * - If an outbound packet is placed in the ARP cache pending address resolution |
| 45 * and no resolution can be made within the maximum retry count, the outbound· |
| 46 * packet is dropped and this trace is fired; |
| 47 * |
| 48 * A second trace hook lives in the ARP L3 protocol (also named "Drop") and may· |
| 49 * be called for a number of reasons. |
| 50 * |
| 51 * - If an ARP reply is received for an entry that is not waiting for a reply, |
| 52 * the ARP reply packet is dropped and this trace is fired; |
| 53 * - If an ARP reply is received for a non-existant entry, the ARP reply packet· |
| 54 * is dropped and this trace is fired; |
| 55 * - If an ARP cache entry is in the DEAD state (has timed out) and an ARP reply |
| 56 * packet is received, the reply packet is dropped and this trace is fired. |
| 57 * - Each ARP cache entry has a queue of pending packets. If the size of the |
| 58 * queue is exceeded, the outbound packet is dropped and this trace is fired. |
| 59 * |
| 60 * \subsection clickInternetStackIpv4TracingModel Tracing in IPv4 |
| 61 * |
| 62 * The IPv4 layer three protocol provides three trace hooks. These are the· |
| 63 * "Tx" (ns3::Ipv4L3Protocol::m_txTrace), "Rx" (ns3::Ipv4L3Protocol::m_rxTrace)· |
| 64 * and "Drop" (ns3::Ipv4L3Protocol::m_dropTrace) trace sources. |
| 65 * |
| 66 * The "Tx" trace is fired in a number of situations, all of which indicate that |
| 67 * a given packet is about to be sent down to a given ns3::Ipv4Interface. |
| 68 * |
| 69 * - In the case of a packet destined for the broadcast address, the· |
| 70 * Ipv4InterfaceList is iterated and for every interface that is up and can |
| 71 * fragment the packet or has a large enough MTU to transmit the packet, |
| 72 * the trace is hit. See ns3::Ipv4L3Protocol::Send. |
| 73 * |
| 74 * - In the case of a packet that needs routing, the "Tx" trace may be fired |
| 75 * just before a packet is sent to the interface appropriate to the default· |
| 76 * gateway. See ns3::Ipv4L3Protocol::SendRealOut. |
| 77 * |
| 78 * - Also in the case of a packet that needs routing, the "Tx" trace may be· |
| 79 * fired just before a packet is sent to the outgoing interface appropriate |
| 80 * to the discovered route. See ns3::Ipv4L3Protocol::SendRealOut. |
| 81 * |
| 82 * The "Rx" trace is fired when a packet is passed from the device up to the |
| 83 * ns3::Ipv4L3Protocol::Receive function. |
| 84 * |
| 85 * - In the receive function, the Ipv4InterfaceList is iterated, and if the |
| 86 * Ipv4Interface corresponding to the receiving device is fount to be in the |
| 87 * UP state, the trace is fired. |
| 88 * |
| 89 * The "Drop" trace is fired in any case where the packet is dropped (in both |
| 90 * the transmit and receive paths). |
| 91 * |
| 92 * - In the ns3::Ipv4Interface::Receive function, the packet is dropped and the |
| 93 * drop trace is hit if the interface corresponding to the receiving device |
| 94 * is in the DOWN state. |
| 95 * |
| 96 * - Also in the ns3::Ipv4Interface::Receive function, the packet is dropped and |
| 97 * the drop trace is hit if the checksum is found to be bad. |
| 98 * |
| 99 * - In ns3::Ipv4L3Protocol::Send, an outgoing packet bound for the broadcast |
| 100 * address is dropped and the "Drop" trace is fired if the "don't fragement" |
| 101 * bit is set and fragmentation is available and required. |
| 102 * |
| 103 * - Also in ns3::Ipv4L3Protocol::Send, an outgoing packet destined for the· |
| 104 * broadcast address is dropped and the "Drop" trace is hit if fragmentation |
| 105 * is not available and is required (MTU < packet size). |
| 106 * |
| 107 * - In the case of a broadcast address, an outgoing packet is cloned for each |
| 108 * outgoing interface. If any of the interfaces is in the DOWN state, the· |
| 109 * "Drop" trace event fires with a reference to the copied packet. |
| 110 * |
| 111 * - In the case of a packet requiring a route, an outgoing packet is dropped |
| 112 * and the "Drop" trace event fires if no route to the remote host is found. |
| 113 * |
| 114 * - In ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed |
| 115 * is dropped and the "Drop" trace is fired if the "don't fragement" bit is· |
| 116 * set and fragmentation is available and required. |
| 117 * |
| 118 * - Also in ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed |
| 119 * is dropped and the "Drop" trace is hit if fragmentation is not available· |
| 120 * and is required (MTU < packet size). |
| 121 * |
| 122 * - An outgoing packet being routed is dropped and the "Drop" trace event fires |
| 123 * if the required Ipv4Interface is in the DOWN state. |
| 124 * |
| 125 * - If a packet is being forwarded, and the TTL is exceeded (see |
| 126 * ns3::Ipv4L3Protocol::DoForward), the packet is dropped and the "Drop" trace······· |
| 127 * event is fired. |
| 128 * |
| 129 * \subsection clickInternetStackNs3TCPTracingModel Tracing in ns-3 TCP |
| 130 * |
| 131 * There is currently one trace source in the ns-3 TCP implementation named |
| 132 * "CongestionWindow" (see ns3::TcpSocketImpl::m_cWnd). This is set in a number |
| 133 * of places (see file tcp-socket-impl.cc) whenever the value of the congestion |
| 134 * window is changed. |
| 135 * |
| 136 * \subsection clickInternetStackNscTCPTracingModel Tracing in NSC TCP |
| 137 * |
| 138 * There is currently one trace source in the Network Simulation Cradle TCP· |
| 139 * implementation named "CongestionWindow" (see ns3::NscTcpSocketImpl::m_cWnd). |
| 140 * This is set in a number of places (see file nsc-tcp-socket-impl.cc) when· |
| 141 * the value of the cogestion window is initially set. Note that this is not |
| 142 * instrumented from the underlying TCP implementaion. |
| 143 * |
| 144 * \subsection clickInternetStackNs3UdpTracingModel Tracing in ns-3 UDP |
| 145 * |
| 146 * There is currently one trace source in the ns-3 UDP implementation named |
| 147 * "Drop" (see ns3::UdpSocketImpl::m_dropTrace). This is set when a packet |
| 148 * is received in ns3::UdpSocketImpl::ForwardUp and the receive buffer cannot |
| 149 * accomodate the encapsulated data. |
| 150 */ |
| 151 |
| 152 #ifdef NS3_CLICK |
| 153 |
| 154 #include "ns3/assert.h" |
| 155 #include "ns3/log.h" |
| 156 #include "ns3/object.h" |
| 157 #include "ns3/names.h" |
| 158 #include "ns3/ipv4.h" |
| 159 #include "ns3/packet-socket-factory.h" |
| 160 #include "ns3/config.h" |
| 161 #include "ns3/simulator.h" |
| 162 #include "ns3/string.h" |
| 163 #include "ns3/net-device.h" |
| 164 #include "ns3/callback.h" |
| 165 #include "ns3/node.h" |
| 166 #include "ns3/core-config.h" |
| 167 #include "ns3/arp-l3-protocol.h" |
| 168 #include "ns3/ipv4-click-routing.h" |
| 169 #include "ns3/ipv4-l3-click-protocol.h" |
| 170 #include "click-internet-stack-helper.h" |
| 171 #include "trace-helper.h" |
| 172 #include <limits> |
| 173 #include <map> |
| 174 |
| 175 NS_LOG_COMPONENT_DEFINE ("ClickInternetStackHelper"); |
| 176 |
| 177 namespace ns3 { |
| 178 |
| 179 #define INTERFACE_CONTEXT |
| 180 |
| 181 typedef std::pair<Ptr<Ipv4>, uint32_t> InterfacePairIpv4;· |
| 182 typedef std::map<InterfacePairIpv4, Ptr<PcapFileWrapper> > InterfaceFileMapIpv4; |
| 183 typedef std::map<InterfacePairIpv4, Ptr<OutputStreamWrapper> > InterfaceStreamMa
pIpv4; |
| 184 |
| 185 static InterfaceFileMapIpv4 g_interfaceFileMapIpv4; /**< A mapping of Ipv4/inter
face pairs to pcap files */ |
| 186 static InterfaceStreamMapIpv4 g_interfaceStreamMapIpv4; /**< A mapping of Ipv4/i
nterface pairs to ascii streams */ |
| 187 |
| 188 ClickInternetStackHelper::ClickInternetStackHelper () |
| 189 : m_ipv4Enabled (true) |
| 190 { |
| 191 Initialize (); |
| 192 } |
| 193 |
| 194 // private method called by both constructor and Reset () |
| 195 void |
| 196 ClickInternetStackHelper::Initialize () |
| 197 { |
| 198 SetTcp ("ns3::TcpL4Protocol"); |
| 199 } |
| 200 |
| 201 ClickInternetStackHelper::~ClickInternetStackHelper () |
| 202 { |
| 203 } |
| 204 |
| 205 ClickInternetStackHelper::ClickInternetStackHelper (const ClickInternetStackHelp
er &o) |
| 206 { |
| 207 m_ipv4Enabled = o.m_ipv4Enabled; |
| 208 m_tcpFactory = o.m_tcpFactory; |
| 209 } |
| 210 |
| 211 ClickInternetStackHelper & |
| 212 ClickInternetStackHelper::operator = (const ClickInternetStackHelper &o) |
| 213 { |
| 214 if (this == &o) |
| 215 { |
| 216 return *this; |
| 217 } |
| 218 return *this; |
| 219 } |
| 220 |
| 221 void |
| 222 ClickInternetStackHelper::Reset (void) |
| 223 { |
| 224 m_ipv4Enabled = true; |
| 225 Initialize (); |
| 226 } |
| 227 |
| 228 void |
| 229 ClickInternetStackHelper::SetTcp (const std::string tid) |
| 230 { |
| 231 m_tcpFactory.SetTypeId (tid); |
| 232 } |
| 233 |
| 234 void· |
| 235 ClickInternetStackHelper::SetTcp (std::string tid, std::string n0, const Attribu
teValue &v0) |
| 236 { |
| 237 m_tcpFactory.SetTypeId (tid); |
| 238 m_tcpFactory.Set (n0,v0); |
| 239 } |
| 240 |
| 241 void |
| 242 ClickInternetStackHelper::SetClickFile (NodeContainer c, std::string clickfile) |
| 243 { |
| 244 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) |
| 245 { |
| 246 SetClickFile (*i, clickfile); |
| 247 } |
| 248 } |
| 249 |
| 250 void |
| 251 ClickInternetStackHelper::SetClickFile (Ptr<Node> node, std::string clickfile) |
| 252 { |
| 253 m_nodeToClickFileMap.insert (std::make_pair (node, clickfile)); |
| 254 } |
| 255 |
| 256 void |
| 257 ClickInternetStackHelper::SetRoutingTableElement (NodeContainer c, std::string r
t) |
| 258 { |
| 259 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) |
| 260 { |
| 261 SetRoutingTableElement (*i, rt); |
| 262 } |
| 263 } |
| 264 |
| 265 void |
| 266 ClickInternetStackHelper::SetRoutingTableElement (Ptr<Node> node, std::string rt
) |
| 267 { |
| 268 m_nodeToRoutingTableElementMap.insert (std::make_pair (node, rt)); |
| 269 } |
| 270 |
| 271 void· |
| 272 ClickInternetStackHelper::Install (NodeContainer c) const |
| 273 { |
| 274 for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) |
| 275 { |
| 276 Install (*i); |
| 277 } |
| 278 } |
| 279 |
| 280 void· |
| 281 ClickInternetStackHelper::InstallAll (void) const |
| 282 { |
| 283 Install (NodeContainer::GetGlobal ()); |
| 284 } |
| 285 |
| 286 void |
| 287 ClickInternetStackHelper::CreateAndAggregateObjectFromTypeId (Ptr<Node> node, co
nst std::string typeId) |
| 288 { |
| 289 ObjectFactory factory; |
| 290 factory.SetTypeId (typeId); |
| 291 Ptr<Object> protocol = factory.Create <Object> (); |
| 292 node->AggregateObject (protocol); |
| 293 } |
| 294 |
| 295 void |
| 296 ClickInternetStackHelper::Install (Ptr<Node> node) const |
| 297 { |
| 298 if (m_ipv4Enabled) |
| 299 { |
| 300 if (node->GetObject<Ipv4> () != 0) |
| 301 { |
| 302 NS_FATAL_ERROR ("ClickInternetStackHelper::Install (): Aggregating "· |
| 303 "an InternetStack to a node with an existing Ipv4 obje
ct"); |
| 304 return; |
| 305 } |
| 306 |
| 307 CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol"); |
| 308 CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3ClickProtocol"); |
| 309 CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol"); |
| 310 CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol"); |
| 311 node->AggregateObject (m_tcpFactory.Create<Object> ()); |
| 312 Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> (); |
| 313 node->AggregateObject (factory); |
| 314 // Set routing |
| 315 Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> (); |
| 316 Ptr<Ipv4ClickRouting> ipv4Routing = CreateObject<Ipv4ClickRouting> (); |
| 317 std::map< Ptr<Node>, std::string >::const_iterator it; |
| 318 it = m_nodeToClickFileMap.find (node); |
| 319 |
| 320 if (it != m_nodeToClickFileMap.end ()) |
| 321 { |
| 322 ipv4Routing->SetClickFile (it->second); |
| 323 } |
| 324 |
| 325 it = m_nodeToRoutingTableElementMap.find (node); |
| 326 if (it != m_nodeToRoutingTableElementMap.end ()) |
| 327 { |
| 328 ipv4Routing->SetClickRoutingTableElement (it->second); |
| 329 } |
| 330 ipv4->SetRoutingProtocol (ipv4Routing); |
| 331 node->AggregateObject (ipv4Routing); |
| 332 } |
| 333 } |
| 334 |
| 335 void |
| 336 ClickInternetStackHelper::Install (std::string nodeName) const |
| 337 { |
| 338 Ptr<Node> node = Names::Find<Node> (nodeName); |
| 339 Install (node); |
| 340 } |
| 341 |
| 342 static void |
| 343 Ipv4L3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ipv4> ipv4, uint32_t interface) |
| 344 { |
| 345 NS_LOG_FUNCTION (p << ipv4 << interface); |
| 346 |
| 347 // |
| 348 // Since trace sources are independent of interface, if we hook a source |
| 349 // on a particular protocol we will get traces for all of its interfaces. |
| 350 // We need to filter this to only report interfaces for which the user· |
| 351 // has expressed interest. |
| 352 // |
| 353 InterfacePairIpv4 pair = std::make_pair (ipv4, interface); |
| 354 if (g_interfaceFileMapIpv4.find (pair) == g_interfaceFileMapIpv4.end ()) |
| 355 { |
| 356 NS_LOG_INFO ("Ignoring packet to/from interface " << interface); |
| 357 return; |
| 358 } |
| 359 |
| 360 Ptr<PcapFileWrapper> file = g_interfaceFileMapIpv4[pair]; |
| 361 file->Write(Simulator::Now(), p); |
| 362 } |
| 363 |
| 364 bool |
| 365 ClickInternetStackHelper::PcapHooked (Ptr<Ipv4> ipv4) |
| 366 { |
| 367 for ( InterfaceFileMapIpv4::const_iterator i = g_interfaceFileMapIpv4.begin (
);· |
| 368 i != g_interfaceFileMapIpv4.end ();· |
| 369 ++i) |
| 370 { |
| 371 if ((*i).first.first == ipv4) |
| 372 { |
| 373 return true; |
| 374 } |
| 375 } |
| 376 return false; |
| 377 } |
| 378 |
| 379 void· |
| 380 ClickInternetStackHelper::EnablePcapIpv4Internal (std::string prefix, Ptr<Ipv4>
ipv4, uint32_t interface, bool explicitFilename) |
| 381 { |
| 382 NS_LOG_FUNCTION (prefix << ipv4 << interface); |
| 383 |
| 384 if (!m_ipv4Enabled) |
| 385 { |
| 386 NS_LOG_INFO ("Call to enable Ipv4 pcap tracing but Ipv4 not enabled"); |
| 387 return; |
| 388 } |
| 389 |
| 390 // |
| 391 // We have to create a file and a mapping from protocol/interface to file· |
| 392 // irrespective of how many times we want to trace a particular protocol. |
| 393 // |
| 394 PcapHelper pcapHelper; |
| 395 |
| 396 std::string filename; |
| 397 if (explicitFilename) |
| 398 { |
| 399 filename = prefix; |
| 400 } |
| 401 else |
| 402 { |
| 403 filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ipv4, interfac
e); |
| 404 } |
| 405 |
| 406 Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, Pc
apHelper::DLT_RAW); |
| 407 |
| 408 // |
| 409 // However, we only hook the trace source once to avoid multiple trace sink |
| 410 // calls per event (connect is independent of interface). |
| 411 // |
| 412 if (!PcapHooked (ipv4)) |
| 413 { |
| 414 // |
| 415 // Ptr<Ipv4> is aggregated to node and Ipv4L3Protocol is aggregated to· |
| 416 // node so we can get to Ipv4L3Protocol through Ipv4. |
| 417 // |
| 418 Ptr<Ipv4L3Protocol> ipv4L3Protocol = ipv4->GetObject<Ipv4L3Protocol> (); |
| 419 NS_ASSERT_MSG (ipv4L3Protocol, "ClickInternetStackHelper::EnablePcapIpv4In
ternal(): " |
| 420 "m_ipv4Enabled and ipv4L3Protocol inconsistent"); |
| 421 |
| 422 bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Tx", MakeCallba
ck (&Ipv4L3ProtocolRxTxSink)); |
| 423 NS_ASSERT_MSG (result == true, "ClickInternetStackHelper::EnablePcapIpv4In
ternal(): " |
| 424 "Unable to connect ipv4L3Protocol \"Tx\""); |
| 425 |
| 426 result = ipv4L3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&
Ipv4L3ProtocolRxTxSink)); |
| 427 NS_ASSERT_MSG (result == true, "ClickInternetStackHelper::EnablePcapIpv4In
ternal(): " |
| 428 "Unable to connect ipv4L3Protocol \"Rx\""); |
| 429 } |
| 430 |
| 431 g_interfaceFileMapIpv4[std::make_pair (ipv4, interface)] = file; |
| 432 } |
| 433 |
| 434 static void |
| 435 Ipv4L3ProtocolDropSinkWithoutContext ( |
| 436 Ptr<OutputStreamWrapper> stream, |
| 437 Ipv4Header const &header,· |
| 438 Ptr<const Packet> packet, |
| 439 Ipv4L3Protocol::DropReason reason,· |
| 440 Ptr<Ipv4> ipv4,· |
| 441 uint32_t interface) |
| 442 { |
| 443 // |
| 444 // Since trace sources are independent of interface, if we hook a source |
| 445 // on a particular protocol we will get traces for all of its interfaces. |
| 446 // We need to filter this to only report interfaces for which the user· |
| 447 // has expressed interest. |
| 448 // |
| 449 InterfacePairIpv4 pair = std::make_pair (ipv4, interface); |
| 450 if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ()) |
| 451 { |
| 452 NS_LOG_INFO ("Ignoring packet to/from interface " << interface); |
| 453 return; |
| 454 } |
| 455 |
| 456 Ptr<Packet> p = packet->Copy (); |
| 457 p->AddHeader (header); |
| 458 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p
<< std::endl; |
| 459 } |
| 460 |
| 461 static void |
| 462 Ipv4L3ProtocolDropSinkWithContext ( |
| 463 Ptr<OutputStreamWrapper> stream, |
| 464 std::string context, |
| 465 Ipv4Header const &header,· |
| 466 Ptr<const Packet> packet, |
| 467 Ipv4L3Protocol::DropReason reason,· |
| 468 Ptr<Ipv4> ipv4,· |
| 469 uint32_t interface) |
| 470 { |
| 471 // |
| 472 // Since trace sources are independent of interface, if we hook a source |
| 473 // on a particular protocol we will get traces for all of its interfaces. |
| 474 // We need to filter this to only report interfaces for which the user· |
| 475 // has expressed interest. |
| 476 // |
| 477 InterfacePairIpv4 pair = std::make_pair (ipv4, interface); |
| 478 if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ()) |
| 479 { |
| 480 NS_LOG_INFO ("Ignoring packet to/from interface " << interface); |
| 481 return; |
| 482 } |
| 483 |
| 484 Ptr<Packet> p = packet->Copy (); |
| 485 p->AddHeader (header); |
| 486 #ifdef INTERFACE_CONTEXT |
| 487 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << con
text << "(" << interface << ") "· |
| 488 << *p << std::endl; |
| 489 #else |
| 490 *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << con
text << " " << *p << std::endl; |
| 491 #endif |
| 492 } |
| 493 |
| 494 bool |
| 495 ClickInternetStackHelper::AsciiHooked (Ptr<Ipv4> ipv4) |
| 496 { |
| 497 for ( InterfaceStreamMapIpv4::const_iterator i = g_interfaceStreamMapIpv4.beg
in ();· |
| 498 i != g_interfaceStreamMapIpv4.end ();· |
| 499 ++i) |
| 500 { |
| 501 if ((*i).first.first == ipv4) |
| 502 { |
| 503 return true; |
| 504 } |
| 505 } |
| 506 return false; |
| 507 } |
| 508 |
| 509 void· |
| 510 ClickInternetStackHelper::EnableAsciiIpv4Internal ( |
| 511 Ptr<OutputStreamWrapper> stream,· |
| 512 std::string prefix,· |
| 513 Ptr<Ipv4> ipv4,· |
| 514 uint32_t interface, |
| 515 bool explicitFilename) |
| 516 { |
| 517 if (!m_ipv4Enabled) |
| 518 { |
| 519 NS_LOG_INFO ("Call to enable Ipv4 ascii tracing but Ipv4 not enabled"); |
| 520 return; |
| 521 } |
| 522 |
| 523 // |
| 524 // Our trace sinks are going to use packet printing, so we have to· |
| 525 // make sure that is turned on. |
| 526 // |
| 527 Packet::EnablePrinting (); |
| 528 |
| 529 // |
| 530 // If we are not provided an OutputStreamWrapper, we are expected to create· |
| 531 // one using the usual trace filename conventions and hook WithoutContext |
| 532 // since there will be one file per context and therefore the context would |
| 533 // be redundant. |
| 534 // |
| 535 if (stream == 0) |
| 536 { |
| 537 // |
| 538 // Set up an output stream object to deal with private ofstream copy· |
| 539 // constructor and lifetime issues. Let the helper decide the actual |
| 540 // name of the file given the prefix. |
| 541 // |
| 542 // We have to create a stream and a mapping from protocol/interface to· |
| 543 // stream irrespective of how many times we want to trace a particular· |
| 544 // protocol. |
| 545 // |
| 546 AsciiTraceHelper asciiTraceHelper; |
| 547 |
| 548 std::string filename; |
| 549 if (explicitFilename) |
| 550 { |
| 551 filename = prefix; |
| 552 } |
| 553 else |
| 554 { |
| 555 filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ipv4
, interface); |
| 556 } |
| 557 |
| 558 Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (fi
lename); |
| 559 |
| 560 // |
| 561 // However, we only hook the trace sources once to avoid multiple trace si
nk |
| 562 // calls per event (connect is independent of interface). |
| 563 // |
| 564 if (!AsciiHooked (ipv4)) |
| 565 { |
| 566 // |
| 567 // We can use the default drop sink for the ArpL3Protocol since it has |
| 568 // the usual signature. We can get to the Ptr<ArpL3Protocol> through |
| 569 // our Ptr<Ipv4> since they must both be aggregated to the same node. |
| 570 // |
| 571 Ptr<ArpL3Protocol> arpL3Protocol = ipv4->GetObject<ArpL3Protocol> (); |
| 572 asciiTraceHelper.HookDefaultDropSinkWithoutContext<ArpL3Protocol> (arp
L3Protocol, "Drop", theStream); |
| 573 |
| 574 // |
| 575 // The drop sink for the Ipv4L3Protocol uses a different signature tha
n |
| 576 // the default sink, so we have to cook one up for ourselves. We can
get |
| 577 // to the Ptr<Ipv4L3Protocol> through our Ptr<Ipv4> since they must bo
th· |
| 578 // be aggregated to the same node. |
| 579 // |
| 580 Ptr<Ipv4L3Protocol> ipv4L3Protocol = ipv4->GetObject<Ipv4L3Protocol> (
); |
| 581 bool __attribute__ ((unused)) result = ipv4L3Protocol->TraceConnectWit
houtContext ("Drop",· |
| 582
MakeBoundCallback (&Ipv4L3ProtocolDropSinkWithoutContext, |
| 583
theStream)); |
| 584 NS_ASSERT_MSG (result == true, "ClickInternetStackHelper::EanableAscii
Ipv4Internal(): " |
| 585 "Unable to connect ipv4L3Protocol \"Drop\""); |
| 586 } |
| 587 |
| 588 g_interfaceStreamMapIpv4[std::make_pair (ipv4, interface)] = theStream; |
| 589 return; |
| 590 } |
| 591 |
| 592 // |
| 593 // If we are provided an OutputStreamWrapper, we are expected to use it, and |
| 594 // to provide a context. We are free to come up with our own context if we |
| 595 // want, and use the AsciiTraceHelper Hook*WithContext functions, but for· |
| 596 // compatibility and simplicity, we just use Config::Connect and let it deal |
| 597 // with the context. |
| 598 // |
| 599 // We need to associate the ipv4/interface with a stream to express interest |
| 600 // in tracing events on that pair, however, we only hook the trace sources· |
| 601 // once to avoid multiple trace sink calls per event (connect is independent |
| 602 // of interface). |
| 603 // |
| 604 if (!AsciiHooked (ipv4)) |
| 605 { |
| 606 Ptr<Node> node = ipv4->GetObject<Node> (); |
| 607 std::ostringstream oss; |
| 608 |
| 609 // |
| 610 // For the ARP Drop, we are going to use the default trace sink provided b
y· |
| 611 // the ascii trace helper. There is actually no AsciiTraceHelper in sight······· |
| 612 // here, but the default trace sinks are actually publicly available stati
c· |
| 613 // functions that are always there waiting for just such a case. |
| 614 // |
| 615 oss << "/NodeList/" << node->GetId () << "/$ns3::ArpL3Protocol/Drop"; |
| 616 Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::Default
DropSinkWithContext, stream)); |
| 617 |
| 618 // |
| 619 // This has all kinds of parameters coming with, so we have to cook up our |
| 620 // own sink. |
| 621 // |
| 622 oss.str (""); |
| 623 oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv4L3Protocol/Drop"; |
| 624 Config::Connect (oss.str (), MakeBoundCallback (&Ipv4L3ProtocolDropSinkWit
hContext, stream)); |
| 625 } |
| 626 |
| 627 g_interfaceStreamMapIpv4[std::make_pair (ipv4, interface)] = stream; |
| 628 } |
| 629 |
| 630 } // namespace ns3 |
| 631 |
| 632 #endif // NS3_CLICK |
OLD | NEW |