diff --git a/src/helper/internet-stack-helper.cc b/src/helper/internet-stack-helper.cc index f9021f252..709afa033 100644 --- a/src/helper/internet-stack-helper.cc +++ b/src/helper/internet-stack-helper.cc @@ -162,22 +162,39 @@ #include "ns3/callback.h" #include "ns3/node.h" #include "ns3/core-config.h" -#include "ns3/pcap-writer.h" -#include "ns3/ascii-writer.h" +#include "ns3/arp-l3-protocol.h" #include "internet-stack-helper.h" #include "ipv4-list-routing-helper.h" #include "ipv4-static-routing-helper.h" #include "ipv4-global-routing-helper.h" #include "ipv6-list-routing-helper.h" #include "ipv6-static-routing-helper.h" +#include "pcap-helper.h" +#include "ascii-trace-helper.h" #include +#include + +NS_LOG_COMPONENT_DEFINE ("InternetStackHelper"); namespace ns3 { -#if 0 -std::vector InternetStackHelper::m_traces; -std::string InternetStackHelper::m_pcapBaseFilename; -#endif +// +// Things are going to work differently here with respect to trace file handling +// than in most places because the Tx and Rx trace sources we are interested in +// are going to multiplex receive and transmit callbacks for all Ipv4 and +// interface pairs through one callback. We want packets to or from each +// distinct pair to go to an individual file, so we have got to demultiplex the +// Ipv4 and interface pair into a corresponding Ptr at the +// callback. +// +// This has got to continue to work properly after the helper has been +// destroyed; but must be cleaned up at the end of time to avoid leaks. A +// global map of interface pairs to pcap file objects seems to fit the bill. +// +typedef std::pair, uint32_t> InterfacePair; +typedef std::map > InterfaceFileMap; + +static InterfaceFileMap g_interfaceFileMap; InternetStackHelper::InternetStackHelper () : m_routing (0), @@ -269,23 +286,6 @@ void InternetStackHelper::SetIpv6StackInstall (bool enable) m_ipv6Enabled = enable; } -void -InternetStackHelper::Cleanup (void) -{ -#if 0 - uint32_t illegal = std::numeric_limits::max (); - - for (std::vector::iterator i = m_traces.begin (); - i != m_traces.end (); i++) - { - i->nodeId = illegal; - i->interfaceId = illegal; - i->writer = 0; - } - m_traces.clear (); -#endif -} - void InternetStackHelper::SetTcp (const std::string tid) { @@ -378,100 +378,77 @@ InternetStackHelper::Install (std::string nodeName) const Install (node); } +static void +Ipv4L3ProtocolRxTxSink (Ptr p, Ptr ipv4, uint32_t interface) +{ + NS_LOG_FUNCTION (p << ipv4 << interface); + + InterfacePair pair = std::make_pair (ipv4, interface); + + if (g_interfaceFileMap.find (pair) == g_interfaceFileMap.end ()) + { + NS_LOG_INFO ("Ignoring packet to/from interface " << interface); + return; + } + + Ptr file = g_interfaceFileMap[pair]; + file->Write(Simulator::Now(), p); +} + void InternetStackHelper::EnablePcapInternal (std::string prefix, Ptr ipv4, uint32_t interface) { -#if 0 - // - // We would normally create the pcap file here, but we need to create a file - // for each interface. This is because when the trace sink for Rx and Tx are - // called, we get the packet and an interface ID. We want to group packets - // to/from a given interface id into a pcap file, but we have no knowledge - // here about what interfaces are created. So we have to go with the flow. - // Look for the file creation to happen in the - // - PcapHelper pcapHelper; - std::string filename = pcapHelper.GetFilenameFromNode (prefix, node); - Ptr file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_RAW); + NS_LOG_FUNCTION (prefix << ipv4 << interface); + + PcapHelper pcapHelper; + std::string filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ipv4, interface); + Ptr file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_RAW); + g_interfaceFileMap[std::make_pair (ipv4, interface)] = file; - // - // We want to enable Tx and Rx traces on Ipv4L3Protocol if m_ipv4Enabled; and - // we want to enable Tx and Rx traces on Ipv6L3Protocol if m_ipv6Enabled. The - // simple way to do that is to let Config::Connect wander through the global - // node list looking for and then the appropriate protocols and trace - // sources. Since we have the node handy, we can be quicker about it, but it - // takes slightly more work here. - // if (m_ipv4Enabled) { - Ptr ipv4L3Protocol = node->GetObject (); + // + // Ptr is aggregated to node and Ipv4L3Protocol is aggregated to + // node so we can get to Ipv4L3Protocol through Ipv4. + // + Ptr ipv4L3Protocol = ipv4->GetObject (); NS_ASSERT_MSG (ipv4L3Protocol, "InternetStackHelper::EnablePcapInternal(): " "m_ipv4Enabled and ipv4L3Protocol inconsistent"); - bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Tx", MakeBoundCallback (&DefaultSink, file)); + bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Tx", MakeCallback (&Ipv4L3ProtocolRxTxSink)); NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv4L3Protocol \"Tx\""); - result = ipv4L3Protocol->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&DefaultSink, file)); + result = ipv4L3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&Ipv4L3ProtocolRxTxSink)); NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv4L3Protocol \"Rx\""); - } - - if (m_ipv6Enabled) - { - Ptr ipv6L3Protocol = node->GetObject (); - NS_FATAL_ERROR_UNLESS (ipv6L3Protocol, "InternetStackHelper::EnablePcapInternal(): " - "m_ipv6Enabled and ipv6L3Protocol inconsistent"); - - bool result = ipv6L3Protocol->TraceConnectWithoutContext ("Tx", MakeBoundCallback (&DefaultSink, file)); - NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv6L3Protocol \"Tx\""); - - result = ipv6L3Protocol->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&DefaultSink, file)); - NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv6L3Protocol \"Rx\""); - - } -#endif } +static void +Ipv4L3ProtocolDropSinkWithoutContext ( + Ptr stream, + Ipv4Header const &header, + Ptr packet, + Ipv4L3Protocol::DropReason reason, + uint32_t interface) +{ + Ptr p = packet->Copy (); + p->AddHeader (header); + *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; +} - -#if 0 - // - // We want to enable drop traces on Ipv4L3Protocol and ArpL3Protocol if - // m_ipv4Enabled; and we want to enable the drop trace on Ipv6L3Protocol - // if enabled. The simple way to do that is to let Config::Connect wander - // through the global node list looking for and then the appropriate - // protocols and trace sources. Since we have the node handy, we can be - // quicker about it, but it takes slightly more work here. - // - if (m_ipv4Enabled) - { - Ptr ipv4L3Protocol = node->GetObject (); - NS_ASSERT_MSG (ipv4L3Protocol, "InternetStackHelper::EnablePcapInternal(): " - "m_ipv4Enabled and ipv4L3Protocol inconsistent"); - - bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&DefaultSink, file)); - NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv4L3Protocol \"Drop\""); - - Ptr arpL3Protocol = node->GetObject (); - NS_ASSERT_MSG (arpL3Protocol, "InternetStackHelper::EnablePcapInternal(): " - "m_ipv4Enabled and arpL3Protocol inconsistent"); - - result = arpL3Protocol->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&DefaultSink, file)); - NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect arpL3Protocol \"Drop\""); - } - - if (m_ipv6Enabled) - { - Ptr ipv6L3Protocol = node->GetObject (); - NS_FATAL_ERROR_UNLESS (ipv6L3Protocol, "InternetStackHelper::EnablePcapInternal(): " - "m_ipv6Enabled and ipv6L3Protocol inconsistent"); - - bool result = ipv6L3Protocol->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&DefaultSink, file)); - NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv6L3Protocol \"Drop\""); - } -#endif - - +static void +Ipv4L3ProtocolDropSinkWithContext ( + Ptr stream, + std::string context, + Ipv4Header const &header, + Ptr packet, + Ipv4L3Protocol::DropReason reason, + uint32_t interface) +{ + Ptr p = packet->Copy (); + p->AddHeader (header); + *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl; +} void InternetStackHelper::EnableAsciiInternal ( @@ -480,21 +457,8 @@ InternetStackHelper::EnableAsciiInternal ( Ptr ipv4, uint32_t interface) { -#if 0 // - // All of the ascii enable functions vector through here including the ones - // that are wandering through all of devices on perhaps all of the nodes in - // the system. We can only deal with devices of type CsmaNetDevice. - // - Ptr device = nd->GetObject (); - if (device == 0) - { - NS_LOG_INFO ("CsmaHelper::EnableAsciiInternal(): Device " << device << " not of type ns3::CsmaNetDevice"); - return; - } - - // - // Our default trace sinks are going to use packet printing, so we have to + // Our trace sinks are going to use packet printing, so we have to // make sure that is turned on. // Packet::EnablePrinting (); @@ -513,23 +477,27 @@ InternetStackHelper::EnableAsciiInternal ( // name of the file given the prefix. // AsciiTraceHelper asciiTraceHelper; - std::string filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device); + std::string filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ipv4, interface); Ptr theStream = asciiTraceHelper.CreateFileStream (filename, "w"); // - // The MacRx trace source provides our "r" event. + // We can use the default drop sink for the ArpL3Protocol since it has + // the usual signature. We can get to the Ptr through + // our Ptr since they must both be aggregated to the same node. // - asciiTraceHelper.HookDefaultReceiveSinkWithoutContext (device, "MacRx", theStream); + Ptr arpL3Protocol = ipv4->GetObject (); + asciiTraceHelper.HookDefaultDropSinkWithoutContext (arpL3Protocol, "Drop", theStream); // - // The "+", '-', and 'd' events are driven by trace sources actually in the - // transmit queue. + // The drop sink for the Ipv4L3Protocol uses a different signature than + // the default sink, so we have to cook one up for ourselves. We can get + // to the Ptr through our Ptr since they must both + // be aggregated to the same node. // - Ptr queue = device->GetQueue (); - asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext (queue, "Enqueue", theStream); - asciiTraceHelper.HookDefaultDropSinkWithoutContext (queue, "Drop", theStream); - asciiTraceHelper.HookDefaultDequeueSinkWithoutContext (queue, "Dequeue", theStream); - + Ptr ipv4L3Protocol = ipv4->GetObject (); + bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Drop", + MakeBoundCallback (&Ipv4L3ProtocolDropSinkWithoutContext, theStream)); + NS_ASSERT_MSG (result == true, "InternetStackHelper::EnableAsciiInternal(): Unable to connect ipv4L3Protocol \"Drop\""); return; } @@ -540,34 +508,21 @@ InternetStackHelper::EnableAsciiInternal ( // compatibility and simplicity, we just use Config::Connect and let it deal // with the context. // - // Note that we are going to use the default trace sinks provided by the - // ascii trace helper. There is actually no AsciiTraceHelper in sight here, - // but the default trace sinks are actually publicly available static - // functions that are always there waiting for just such a case. - // - uint32_t nodeid = nd->GetNode ()->GetId (); - uint32_t deviceid = nd->GetIfIndex (); + Ptr node = ipv4->GetObject (); std::ostringstream oss; - oss << "/NodeList/" << nd->GetNode ()->GetId () << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/MacRx"; - Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultReceiveSinkWithContext, stream)); - - oss.str (""); - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/TxQueue/Enqueue"; - Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultEnqueueSinkWithContext, stream)); - - oss.str (""); - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/TxQueue/Dequeue"; - Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDequeueSinkWithContext, stream)); - - oss.str (""); - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/TxQueue/Drop"; + // We are going to use the default trace sink provided by the ascii trace + // helper. There is actually no AsciiTraceHelper in sight here, but the + // default trace sinks are actually publicly available static functions + // that are always there waiting for just such a case. + // + oss << "/NodeList/" << node->GetId () << "/$ns3::ArpL3Protocol/Drop"; Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream)); -#endif + + oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv4L3Protocol/Drop"; + Config::Connect (oss.str (), MakeBoundCallback (&Ipv4L3ProtocolDropSinkWithContext, stream)); } - - #if 0 void InternetStackHelper::EnableAscii (std::ostream &os, NodeContainer n) @@ -590,100 +545,6 @@ InternetStackHelper::EnableAscii (std::ostream &os, NodeContainer n) } } -void -InternetStackHelper::EnableAsciiAll (std::ostream &os) -{ - EnableAscii (os, NodeContainer::GetGlobal ()); -} - -void -InternetStackHelper::EnablePcapAll (std::string filename) -{ - Simulator::ScheduleDestroy (&InternetStackHelper::Cleanup); - - InternetStackHelper::m_pcapBaseFilename = filename; - Config::Connect ("/NodeList/*/$ns3::Ipv4L3Protocol/Tx", - MakeCallback (&InternetStackHelper::LogTxIp)); - Config::Connect ("/NodeList/*/$ns3::Ipv4L3Protocol/Rx", - MakeCallback (&InternetStackHelper::LogRxIp)); - - /* IPv6 */ - Config::Connect ("/NodeList/*/$ns3::Ipv6L3Protocol/Tx", - MakeCallback (&InternetStackHelper::LogTxIp)); - Config::Connect ("/NodeList/*/$ns3::Ipv6L3Protocol/Rx", - MakeCallback (&InternetStackHelper::LogRxIp)); -} - -uint32_t -InternetStackHelper::GetNodeIndex (std::string context) -{ - std::string::size_type pos; - pos = context.find ("/NodeList/"); - NS_ASSERT (pos == 0); - std::string::size_type afterNodeIndex = context.find ("/", 11); - NS_ASSERT (afterNodeIndex != std::string::npos); - std::string index = context.substr (10, afterNodeIndex - 10); - std::istringstream iss; - iss.str (index); - uint32_t nodeIndex; - iss >> nodeIndex; - return nodeIndex; -} - -void -InternetStackHelper::LogTxIp (std::string context, Ptr packet, uint32_t interfaceIndex) -{ - Ptr writer = InternetStackHelper::GetStream (GetNodeIndex (context), interfaceIndex); - writer->WritePacket (packet); -} - -void -InternetStackHelper::LogRxIp (std::string context, Ptr packet, uint32_t interfaceIndex) -{ - Ptr writer = InternetStackHelper::GetStream (GetNodeIndex (context), interfaceIndex); - writer->WritePacket (packet); -} - -Ptr -InternetStackHelper::GetStream (uint32_t nodeId, uint32_t interfaceId) -{ - for (std::vector::iterator i = m_traces.begin (); - i != m_traces.end (); i++) - { - if (i->nodeId == nodeId && - i->interfaceId == interfaceId) - { - return i->writer; - } - } - InternetStackHelper::Trace trace; - trace.nodeId = nodeId; - trace.interfaceId = interfaceId; - trace.writer = CreateObject (); - std::ostringstream oss; - oss << m_pcapBaseFilename << "-" << nodeId << "-" << interfaceId << ".pcap"; - trace.writer->Open (oss.str ()); - trace.writer->WriteIpHeader (); - m_traces.push_back (trace); - return trace.writer; -} - -void -InternetStackHelper::AsciiDropEventArp (Ptr writer, std::string path, Ptr packet) -{ - writer->WritePacket (AsciiWriter::DROP, path, packet); -} - -void -InternetStackHelper::AsciiDropEventIpv4 (Ptr writer, std::string path, - Ipv4Header const &header, Ptr packet, - Ipv4L3Protocol::DropReason reason, uint32_t interface) -{ - Ptr p = packet->Copy (); - p->AddHeader (header); - writer->WritePacket (AsciiWriter::DROP, path, p); -} - void InternetStackHelper::AsciiDropEventIpv6 (Ptr writer, std::string path, Ipv6Header const &header, Ptr packet, diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index d42484f51..ea1eb977d 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -442,7 +442,7 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr { if (ipv4Interface->IsUp ()) { - m_rxTrace (packet, interface); + m_rxTrace (packet, m_node->GetObject (), interface); break; } else @@ -450,7 +450,7 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr NS_LOG_LOGIC ("Dropping received packet-- interface is down"); Ipv4Header ipHeader; packet->RemoveHeader (ipHeader); - m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, interface); + m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject (), interface); return; } } @@ -465,7 +465,7 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr if (!ipHeader.IsChecksumOk ()) { - m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, interface); + m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, m_node->GetObject (), interface); return; } @@ -547,7 +547,7 @@ Ipv4L3Protocol::Send (Ptr packet, m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex); packetCopy->AddHeader (ipHeader); - m_txTrace (packetCopy, ifaceIndex); + m_txTrace (packetCopy, m_node->GetObject (), ifaceIndex); outInterface->Send (packetCopy, destination); } return; @@ -571,7 +571,7 @@ Ipv4L3Protocol::Send (Ptr packet, Ptr packetCopy = packet->Copy (); m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex); packetCopy->AddHeader (ipHeader); - m_txTrace (packetCopy, ifaceIndex); + m_txTrace (packetCopy, m_node->GetObject (), ifaceIndex); outInterface->Send (packetCopy, destination); return; } @@ -613,7 +613,7 @@ Ipv4L3Protocol::Send (Ptr packet, else { NS_LOG_WARN ("No route to host. Drop."); - m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, 0); + m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject (), 0); } } @@ -666,7 +666,7 @@ Ipv4L3Protocol::SendRealOut (Ptr route, if (route == 0) { NS_LOG_WARN ("No route to host. Drop."); - m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, 0); + m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject (), 0); return; } packet->AddHeader (ipHeader); @@ -682,7 +682,7 @@ Ipv4L3Protocol::SendRealOut (Ptr route, if (outInterface->IsUp ()) { NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ()); - m_txTrace (packet, interface); + m_txTrace (packet, m_node->GetObject (), interface); outInterface->Send (packet, route->GetGateway ()); } else @@ -690,7 +690,7 @@ Ipv4L3Protocol::SendRealOut (Ptr route, NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ()); Ipv4Header ipHeader; packet->RemoveHeader (ipHeader); - m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, interface); + m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject (), interface); } } else @@ -698,7 +698,7 @@ Ipv4L3Protocol::SendRealOut (Ptr route, if (outInterface->IsUp ()) { NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ()); - m_txTrace (packet, interface); + m_txTrace (packet, m_node->GetObject (), interface); outInterface->Send (packet, ipHeader.GetDestination ()); } else @@ -706,7 +706,7 @@ Ipv4L3Protocol::SendRealOut (Ptr route, NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestination ()); Ipv4Header ipHeader; packet->RemoveHeader (ipHeader); - m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, interface); + m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject (), interface); } } } @@ -729,7 +729,7 @@ Ipv4L3Protocol::IpMulticastForward (Ptr mrtentry, PtrGetObject (), i); return; } NS_LOG_LOGIC ("Forward multicast via interface " << i); @@ -766,7 +766,7 @@ Ipv4L3Protocol::IpForward (Ptr rtentry, Ptr p, const Ip icmp->SendTimeExceededTtl (ipHeader, packet); } NS_LOG_WARN ("TTL exceeded. Drop."); - m_dropTrace (header, packet, DROP_TTL_EXPIRED, interface); + m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject (), interface); return; } m_unicastForwardTrace (ipHeader, packet, interface); @@ -1036,8 +1036,7 @@ Ipv4L3Protocol::RouteInputError (Ptr p, const Ipv4Header & ipHeade { NS_LOG_FUNCTION (this << p << ipHeader << sockErrno); NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno); - m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, 0); + m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject (), 0); } - }//namespace ns3 diff --git a/src/internet-stack/ipv4-l3-protocol.h b/src/internet-stack/ipv4-l3-protocol.h index 32a1fb633..def314481 100644 --- a/src/internet-stack/ipv4-l3-protocol.h +++ b/src/internet-stack/ipv4-l3-protocol.h @@ -258,10 +258,10 @@ private: TracedCallback, uint32_t> m_localDeliverTrace; // The following two traces pass a packet with an IP header - TracedCallback, uint32_t> m_txTrace; - TracedCallback, uint32_t> m_rxTrace; + TracedCallback, Ptr, uint32_t> m_txTrace; + TracedCallback, Ptr, uint32_t> m_rxTrace; // (ifindex not valid if reason is DROP_NO_ROUTE) - TracedCallback, DropReason, uint32_t> m_dropTrace; + TracedCallback, DropReason, Ptr, uint32_t> m_dropTrace; Ptr m_routingProtocol;